The chip I use is s32k144
I want to ask when SPI sending interrupt is triggered:
In LPSPI_DRV_MasterTransferBlocking function Start SPI data transmission, but the SPI data transmission is completed in the SPI middle service function. I want to know when the SPI transmission interrupt is triggered
Also, what is the condition when SPI receiving interrupt is triggered? Is it when SPI controller puts data into RX FIFO
In addition, does s32k144 have a special chip manual? The chip manual on the official website is a series of chip manuals, and there is no structural block diagram of each module inside the chip, which looks inconvenient
1.you can refer to the following registers,which comes from S32K-RM,
51.3.1.5 Status Register (SR)
2.no separate datasheet for S32K144
BR!
Jim,
The TDF field of SPI status register is read-only and can only mark whether SPI transmission is completed. I would like to ask how to trigger SPI interrupt through software
static status_t LPSPI_DRV_MasterStartTransfer(uint32_t instance,
const uint8_t * sendBuffer,
uint8_t * receiveBuffer,
uint16_t transferByteCount)
{
DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
DEV_ASSERT(g_lpspiStatePtr[instance] != NULL);
/* Instantiate local variable of type dspi_master_state_t and point to global state */
lpspi_state_t * lpspiState = g_lpspiStatePtr[instance];
LPSPI_Type *base = g_lpspiBase[instance];
edma_transfer_size_t dmaTransferSize = EDMA_TRANSFER_SIZE_1B;
/* Check that we're not busy. */
if (LPSPI_GetStatusFlag(base, LPSPI_MODULE_BUSY))
{
return STATUS_BUSY;
}
#ifdef ERRATA_E10655
else
{
/* Double check to fix errata e10655. */
if (LPSPI_GetStatusFlag(base, LPSPI_MODULE_BUSY))
{
return STATUS_BUSY;
}
}
#endif
/* Verify if the number of bytes is divided by number of bytes/frame. */
if ((transferByteCount % lpspiState->bytesPerFrame) != (uint16_t)0)
{
return STATUS_ERROR;
}
/* Clean RX and TX buffers */
LPSPI_SetFlushFifoCmd(base, true, true);
/* The second flush command is used to avoid the case when one word is still in shifter. */
LPSPI_SetFlushFifoCmd(base, true, true);
if(lpspiState->isPcsContinuous == true)
{
LPSPI_SetContCBit(base);
}
lpspiState->status = LPSPI_TRANSFER_OK;
/* Clear all interrupts sources */
(void)LPSPI_ClearStatusFlag(base, LPSPI_ALL_STATUS);
/* Enable fault interrupts sources */
LPSPI_SetIntMode(base,LPSPI_TRANSMIT_ERROR , true);
if (receiveBuffer != NULL)
{
LPSPI_SetIntMode(base,LPSPI_RECEIVE_ERROR , true);
}
/* Configure rxCount depending on transfer type.*/
if (receiveBuffer == NULL)
{
lpspiState->rxCount = 0;
LPSPI_SetRxmskBit(base);
}
else
{
lpspiState->rxCount = transferByteCount;
LPSPI_ClearRxmaskBit(base);
}
/* Configure watermarks */
LPSPI_SetRxWatermarks(base, 0U);
LPSPI_SetTxWatermarks(base, 2U);
if (lpspiState->transferType == LPSPI_USING_INTERRUPTS)
{
/* Fill out the other members of the run-time state structure. */
lpspiState->txBuff = (const uint8_t *)sendBuffer;
lpspiState->rxBuff = (uint8_t *)receiveBuffer;
lpspiState->txFrameCnt = 0;
lpspiState->rxFrameCnt = 0;
lpspiState->txCount = transferByteCount;
/*For continuous mode an extra word must be written to negate the PCS */
if (lpspiState->isPcsContinuous == true)
{
lpspiState->txCount++;
}
/* Update transfer status */
lpspiState->isTransferInProgress = true;
/* Enable RDF interrupt if RX buffer is not NULL. */
if (lpspiState->rxBuff != NULL)
{
LPSPI_SetIntMode(base, LPSPI_RX_DATA_FLAG, true);
}
/* Enable the TDF and RDF interrupt. */
LPSPI_SetIntMode(base, LPSPI_TX_DATA_FLAG, true);
}
else
{
/* When LPSPI use DMA frames with 3 bytes size are not accepted. */
switch(lpspiState->bytesPerFrame)
{
case 1: dmaTransferSize = EDMA_TRANSFER_SIZE_1B; break;
case 2: dmaTransferSize = EDMA_TRANSFER_SIZE_2B; break;
case 4: dmaTransferSize = EDMA_TRANSFER_SIZE_4B; break;
default : dmaTransferSize = EDMA_TRANSFER_SIZE_4B; break;
}
/* Configure TX DMA channel */
if (sendBuffer != NULL)
{
(void)EDMA_DRV_ConfigMultiBlockTransfer(lpspiState->txDMAChannel, EDMA_TRANSFER_MEM2PERIPH,
(uint32_t)sendBuffer, (uint32_t)(&(base->TDR)), dmaTransferSize, (uint32_t)1U<<(uint8_t)(dmaTransferSize),
(uint32_t)transferByteCount/(uint32_t)((uint32_t)1U <<(uint8_t)(dmaTransferSize)), true);
}
else
{
(void)EDMA_DRV_ConfigMultiBlockTransfer(lpspiState->txDMAChannel, EDMA_TRANSFER_PERIPH2PERIPH,
(uint32_t)(&(lpspiState->dummy)), (uint32_t)(&(base->TDR)), dmaTransferSize, (uint32_t)1U<<(uint8_t)(dmaTransferSize),
(uint32_t)transferByteCount/(uint32_t)((uint32_t)1U <<(uint8_t)(dmaTransferSize)), true);
}
/* Configure RX DMA channel if is used in current transfer. */
if(receiveBuffer != NULL)
{
(void)EDMA_DRV_ConfigMultiBlockTransfer(lpspiState->rxDMAChannel, EDMA_TRANSFER_PERIPH2MEM,
(uint32_t)(&(base->RDR)),(uint32_t)receiveBuffer, dmaTransferSize, (uint32_t)1U<<(uint8_t)(dmaTransferSize),
(uint32_t)transferByteCount/(uint32_t)((uint32_t)1U <<(uint8_t)(dmaTransferSize)), true);
(void)EDMA_DRV_InstallCallback(lpspiState->rxDMAChannel, (LPSPI_DRV_MasterCompleteRX),(void*)(instance));
/* Start RX channel */
(void)EDMA_DRV_StartChannel(lpspiState->rxDMAChannel);
}
/* If RX buffer is null the transfer is done when all bytes were sent. */
(void)EDMA_DRV_InstallCallback(lpspiState->txDMAChannel, (LPSPI_DRV_MasterCompleteDMATransfer),(void*)(instance));
/* Start TX channel */
(void)EDMA_DRV_StartChannel(lpspiState->txDMAChannel);
/* Update transfer status */
lpspiState->isTransferInProgress = true;
/* Enable LPSPI DMA request */
if (receiveBuffer!=NULL)
{
LPSPI_SetRxDmaCmd(base, true);
}
LPSPI_SetTxDmaCmd(base, true);
}
return STATUS_SUCCESS;
}
In this function, only SPI sending and receiving interrupt are enabled, but which statement triggers SPI interrupt
Can SPI sending interrupt be triggered by software? If so, how to operate?
there are some demos in s32 ds, you can refer to these demos.
you can set the transfer interrupt callback & callback parameter in following task menu.
BR!
Jim,
SPI interrupt is enabled in SPI initialization function, that is, NVIC will accept SPI interrupt request, and SPI interrupt service function has been defined in interrupt vector table. These have been determined in demo. I want to further clarify how to trigger SPI interrupt and issue interrupt request
status_t LPSPI_DRV_MasterInit(uint32_t instance, lpspi_state_t * lpspiState,
const lpspi_master_config_t * spiConfig)
{
DEV_ASSERT(instance < LPSPI_INSTANCE_COUNT);
DEV_ASSERT(lpspiState != NULL);
DEV_ASSERT(spiConfig != NULL);
LPSPI_Type *base = g_lpspiBase[instance];
status_t errorCode = STATUS_SUCCESS;
/* Save runtime structure pointers so irq handler can point to the correct state structure */
g_lpspiStatePtr[instance] = lpspiState;
/* Reset the LPSPI registers to their default state */
LPSPI_Init(base);
/* Set for master mode */
(void)LPSPI_SetMasterSlaveMode(base, LPSPI_MASTER);
/* Set Pin configuration such that SDO=out and SDI=in */
(void)LPSPI_SetPinConfigMode(base, LPSPI_SDI_IN_SDO_OUT, LPSPI_DATA_OUT_RETAINED, true);
/* Calculate the FIFO size for the LPSPI */
LPSPI_GetFifoSizes(base, &(lpspiState->fifoSize));
/* Configure bus for this device. If NULL is passed, we assume the caller has
* preconfigured the bus and doesn't wish to re-configure it again for this transfer.
* Do nothing for calculatedBaudRate. If the user wants to know the calculatedBaudRate
* then they can call this function separately.
*/
errorCode = LPSPI_DRV_MasterConfigureBus(instance, spiConfig, NULL);
if (errorCode != STATUS_SUCCESS)
{
return errorCode;
}
/* When TX is null the value sent on the bus will be 0 */
lpspiState->dummy = 0;
/* Initialize the semaphore */
errorCode = OSIF_SemaCreate(&(lpspiState->lpspiSemaphore), 0);
DEV_ASSERT(errorCode == STATUS_SUCCESS);
/* Enable the interrupt */
INT_SYS_EnableIRQ(g_lpspiIrqId[instance]);
/* Finally, enable LPSPI */
LPSPI_Enable(base);
return errorCode;
}