The question, as stated in the title, is whether this function does not support DMA transmission? The original function code is pasted below.
Lpspi_Ip_StatusType Lpspi_Ip_SyncTransmit_FromIsr(const Lpspi_Ip_ExternalDeviceType *ExternalDevice,
const uint8 *TxBuffer,
uint8 *RxBuffer,
uint16 Length,
uint32 TimeOut)
{
LPSPI_Type *Base;
Lpspi_Ip_StateStructureType *State;
uint8 NumberOfWrites, NumberOfReads;
Lpspi_Ip_StatusType Status = LPSPI_IP_STATUS_SUCCESS;
uint32 TimeoutTicks = OsIf_MicrosToTicks(TimeOut, LPSPI_IP_TIMEOUT_METHOD);
uint32 CurrentTicks = 0u; /* initialize current counter */
uint32 ElapsedTicks = 0u; /* elapsed will give timeout */
uint8 Instance = 0u;
UBaseType_t uxInterruptStatus;
#if (LPSPI_IP_DEV_ERROR_DETECT == STD_ON)
DevAssert(ExternalDevice != NULL_PTR);
DevAssert(0u != Length);
DevAssert(0u != TimeOut);
Lpspi_Ip_CheckValidParameters(ExternalDevice, Length);
#endif
Instance = ExternalDevice->Instance;
State = Lpspi_Ip_apxStateStructureArray[Instance];
#if (LPSPI_IP_DEV_ERROR_DETECT == STD_ON)
DevAssert(State != NULL_PTR);
#endif
Base = Lpspi_Ip_apxBases[Instance];
// SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_08();
uxInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
if (LPSPI_IP_BUSY == State->Status)
{
// SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_08();
taskEXIT_CRITICAL_FROM_ISR(uxInterruptStatus);
Status = LPSPI_IP_STATUS_FAIL;
}
else
{
/* Mark the hardware as busy. */
State->Status = LPSPI_IP_BUSY;
State->ExternalDevice = ExternalDevice;
// SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_08();
taskEXIT_CRITICAL_FROM_ISR(uxInterruptStatus);
/* Disable DMA requests and all interrupts */
Base->DER = 0u;
Base->IER = 0u;
Base->CFGR0 = State->ExternalDevice->Cfgr0;
/* Reset current FIFO slots are available to fill at beginning of job (HLD).*/
State->CurrentTxFifoSlot = LPSPI_IP_FIFO_SIZE_U8;
Lpspi_TransmitTxInit_FromIsr(Instance, (const uint8 *)TxBuffer, Length);
Lpspi_TransmitRxInit(Instance, RxBuffer, Length);
CurrentTicks = OsIf_GetCounter(LPSPI_IP_TIMEOUT_METHOD); /* initialize current counter */
while (State->RxIndex != State->ExpectedFifoReads)
{
/* RECEIVE DATA */
/* Read all Data available in receive HW fifo. */
NumberOfReads = (uint8)(((Base->FSR) & LPSPI_FSR_RXCOUNT_MASK) >> LPSPI_FSR_RXCOUNT_SHIFT);
if (NumberOfReads != 0u)
{
/* Limits to remaining frames. */
if (NumberOfReads > (State->ExpectedFifoReads - State->RxIndex))
{
NumberOfReads = (uint8)(State->ExpectedFifoReads - State->RxIndex);
}
/* If these are the first frames of this channel. Current TXFIFO slot must be plus 1 because the slot of CMD have moved out */
if (0u == State->RxIndex)
{
State->CurrentTxFifoSlot += 1u;
}
/* Read Data from RX FIFO */
Lpspi_Ip_ReadDataFromFifo(Instance, NumberOfReads);
/* Update current FIFO slots are available to fill .*/
State->CurrentTxFifoSlot += NumberOfReads;
ElapsedTicks = 0u;
}
/* TRANSMIT DATA */
/* Push Data until HW fifo is full or transfer is done. */
/* After driver code read all frames in RX FIFO, if there are still some frames in TX FIFO, at the time before driver code check number of frames available in TX FIFO
to prepare to fill TX FIFO. At that time, interrupt occurred, and the time to process interrupt is longer than the time to transfer all frames in TX FIFO.
So TX FIFO will be empty and some frames received in RX FIFO, then the program is returned from interrupt and fill TX FIFO until full.
And there is a interrupt occurred after that before read all frames in RX FIFO, and the time to process interrupt is longer than the time to transfer all frames in TX FIFO.
State->CurrentTxFifoSlot variable is used to hanlde number of frames are "on bus transfer". They are always less than FIFO size */
if ((State->CurrentTxFifoSlot != 0u))
{
if (State->ExpectedFifoWrites != State->TxIndex)
{
NumberOfWrites = State->CurrentTxFifoSlot;
/* Limits to remaining frames. */
if (NumberOfWrites > (State->ExpectedFifoWrites - State->TxIndex))
{
NumberOfWrites = (uint8)(State->ExpectedFifoWrites - State->TxIndex);
}
/* Push Data into TX FIFO */
Lpspi_Ip_PushDataToFifo(Instance, NumberOfWrites);
State->CurrentTxFifoSlot -= NumberOfWrites;
ElapsedTicks = 0u;
}
else
{
if ((FALSE == State->KeepCs) && (0u != (Base->TCR & LPSPI_TCR_CONT_MASK)))
{
/* Clear CS */
Base->TCR &= ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK);
}
}
}
ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, LPSPI_IP_TIMEOUT_METHOD);
if (ElapsedTicks >= TimeoutTicks)
{
Status = LPSPI_IP_TIMEOUT;
break;
}
}
if ((LPSPI_IP_STATUS_SUCCESS != Status) || (0u == Length))
{
#if (STD_OFF == LPSPI_IP_DEV_ERROR_DETECT)
/* Return Fail status if length is 0. Error Detect is enabled, nothing need to be done here */
if (0u == Length)
{
Status = LPSPI_IP_STATUS_FAIL;
}
#endif
State->Status = LPSPI_IP_FAULT;
}
else
{
State->Status = LPSPI_IP_IDLE;
}
}
return Status;
}