s32k3 “Lpspi_Ip_SyncTransmit_FromIsr” Can this function use DMA transmission?

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

s32k3 “Lpspi_Ip_SyncTransmit_FromIsr” Can this function use DMA transmission?

927件の閲覧回数
chenxinyi
Contributor I

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;
}
0 件の賞賛
返信
2 返答(返信)

905件の閲覧回数
PetrS
NXP TechSupport
NXP TechSupport

Hi,

not sure of teh RTD version you are using, but seems Lpspi_Ip_SyncTransmit_FromIsr() is not in RTD.
The code cannot use DMA because the code explicitly disables it.
If you want DMA → use Lpspi_Ip_AsyncTransmit() with DMA enabled in SpiPhyUnit / RM / DMAMUX.

BR, Petr

0 件の賞賛
返信

895件の閲覧回数
chenxinyi
Contributor I

Hi Petr, Thank you for your reply. I have a follow-up question regarding SPI performance.

In our system, the MCU acts as SPI master, and a host (slave) asserts a GPIO interrupt pin to signal that a frame is ready. The MCU then initiates an SPI transfer in the interrupt callback, parses the data, and forwards it over CAN.

We currently use Lpspi_Ip_SyncTransmit, which provides stable throughput across four CAN channels. However, when switching to DMA-based Lpspi_Ip_AsyncTransmit to maximize speed, the transmission becomes highly unstable—channel rates fluctuate significantly.And the overall speed also fails to reach the level of Lpspi_Ip_SyncTransmit.

Is there a recommended approach to achieve stable, high-speed SPI transfers with Lpspi_Ip_AsyncTransmit in this interrupt-driven master setup?

Best regards, chen

0 件の賞賛
返信
%3CLINGO-SUB%20id%3D%22lingo-sub-2322178%22%20slang%3D%22en-US%22%20mode%3D%22CREATE%22%3Es32k3%E3%80%8CLpspi_Ip_SyncTransmit_FromIsr%E3%80%8D%E3%81%93%E3%81%AE%E9%96%A2%E6%95%B0%E3%81%AFDMA%E8%BB%A2%E9%80%81%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%81%8B%EF%BC%9F%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2322178%22%20slang%3D%22en-US%22%20mode%3D%22CREATE%22%3E%3CP%3E%E8%B3%AA%E5%95%8F%E3%81%AF%E3%82%BF%E3%82%A4%E3%83%88%E3%83%AB%E3%81%AB%E3%82%82%E3%81%82%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%80%81%E3%81%93%E3%81%AE%E6%A9%9F%E8%83%BD%E3%81%AF%20DMA%20%E8%BB%A2%E9%80%81%E3%82%92%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%81%AE%E3%81%A7%E3%81%97%E3%82%87%E3%81%86%E3%81%8B%3F%E5%85%83%E3%81%AE%E9%96%A2%E6%95%B0%E3%81%AE%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E4%BB%A5%E4%B8%8B%E3%81%AB%E8%B2%BC%E3%82%8A%E4%BB%98%E3%81%91%E3%81%BE%E3%81%99%E3%80%82%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-c%22%3E%3CCODE%20translate%3D%22no%22%3ELpspi_Ip_StatusType%20Lpspi_Ip_SyncTransmit_FromIsr(const%20Lpspi_Ip_ExternalDeviceType%20*ExternalDevice%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20uint8%20*TxBuffer%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20uint8%20*RxBuffer%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20uint16%20Length%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20uint32%20TimeOut)%0A%7B%0A%20%20%20%20LPSPI_Type%20*Base%3B%0A%20%20%20%20Lpspi_Ip_StateStructureType%20*State%3B%0A%20%20%20%20uint8%20NumberOfWrites%2C%20NumberOfReads%3B%0A%20%20%20%20Lpspi_Ip_StatusType%20Status%20%3D%20LPSPI_IP_STATUS_SUCCESS%3B%0A%20%20%20%20uint32%20TimeoutTicks%20%3D%20OsIf_MicrosToTicks(TimeOut%2C%20LPSPI_IP_TIMEOUT_METHOD)%3B%0A%20%20%20%20uint32%20CurrentTicks%20%3D%200u%3B%20%2F*%20initialize%20current%20counter%20*%2F%0A%20%20%20%20uint32%20ElapsedTicks%20%3D%200u%3B%20%2F*%20elapsed%20will%20give%20timeout%20*%2F%0A%20%20%20%20uint8%20Instance%20%3D%200u%3B%0A%0A%20%20%20%20UBaseType_t%20uxInterruptStatus%3B%0A%0A%20%20%20%20%23if%20(LPSPI_IP_DEV_ERROR_DETECT%20%3D%3D%20STD_ON)%0A%20%20%20%20DevAssert(ExternalDevice%20!%3D%20NULL_PTR)%3B%0A%20%20%20%20DevAssert(0u%20!%3D%20Length)%3B%0A%20%20%20%20DevAssert(0u%20!%3D%20TimeOut)%3B%0A%20%20%20%20Lpspi_Ip_CheckValidParameters(ExternalDevice%2C%20Length)%3B%0A%20%20%20%20%23endif%0A%20%20%20%20Instance%20%3D%20ExternalDevice-%26gt%3BInstance%3B%0A%20%20%20%20State%20%3D%20Lpspi_Ip_apxStateStructureArray%5BInstance%5D%3B%0A%20%20%20%20%23if%20(LPSPI_IP_DEV_ERROR_DETECT%20%3D%3D%20STD_ON)%0A%20%20%20%20DevAssert(State%20!%3D%20NULL_PTR)%3B%0A%20%20%20%20%23endif%0A%0A%20%20%20%20Base%20%3D%20Lpspi_Ip_apxBases%5BInstance%5D%3B%0A%20%20%20%20%2F%2F%20SchM_Enter_Spi_SPI_EXCLUSIVE_AREA_08()%3B%0A%20%20%20%20uxInterruptStatus%20%3D%20taskENTER_CRITICAL_FROM_ISR()%3B%0A%20%20%20%20if%20(LPSPI_IP_BUSY%20%3D%3D%20State-%26gt%3BStatus)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_08()%3B%0A%20%20%20%20%20%20%20%20taskEXIT_CRITICAL_FROM_ISR(uxInterruptStatus)%3B%0A%20%20%20%20%20%20%20%20Status%20%3D%20LPSPI_IP_STATUS_FAIL%3B%0A%20%20%20%20%7D%0A%20%20%20%20else%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%2F*%20Mark%20the%20hardware%20as%20busy.%20*%2F%0A%20%20%20%20%20%20%20%20State-%26gt%3BStatus%20%3D%20LPSPI_IP_BUSY%3B%0A%20%20%20%20%20%20%20%20State-%26gt%3BExternalDevice%20%3D%20ExternalDevice%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20SchM_Exit_Spi_SPI_EXCLUSIVE_AREA_08()%3B%0A%20%20%20%20%20%20%20%20taskEXIT_CRITICAL_FROM_ISR(uxInterruptStatus)%3B%0A%0A%20%20%20%20%20%20%20%20%2F*%20Disable%20DMA%20requests%20and%20all%20interrupts%20*%2F%0A%20%20%20%20%20%20%20%20Base-%26gt%3BDER%20%3D%200u%3B%0A%20%20%20%20%20%20%20%20Base-%26gt%3BIER%20%3D%200u%3B%0A%20%20%20%20%20%20%20%20Base-%26gt%3BCFGR0%20%3D%20State-%26gt%3BExternalDevice-%26gt%3BCfgr0%3B%0A%0A%20%20%20%20%20%20%20%20%2F*%20Reset%20current%20FIFO%20slots%20are%20available%20to%20fill%20at%20beginning%20of%20job%20(HLD).*%2F%0A%20%20%20%20%20%20%20%20State-%26gt%3BCurrentTxFifoSlot%20%3D%20LPSPI_IP_FIFO_SIZE_U8%3B%0A%20%20%20%20%20%20%20%20Lpspi_TransmitTxInit_FromIsr(Instance%2C%20(const%20uint8%20*)TxBuffer%2C%20Length)%3B%0A%20%20%20%20%20%20%20%20Lpspi_TransmitRxInit(Instance%2C%20RxBuffer%2C%20Length)%3B%0A%0A%20%20%20%20%20%20%20%20CurrentTicks%20%3D%20OsIf_GetCounter(LPSPI_IP_TIMEOUT_METHOD)%3B%20%2F*%20initialize%20current%20counter%20*%2F%0A%20%20%20%20%20%20%20%20while%20(State-%26gt%3BRxIndex%20!%3D%20State-%26gt%3BExpectedFifoReads)%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F*%20RECEIVE%20DATA%20*%2F%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F*%20Read%20all%20Data%20available%20in%20receive%20HW%20fifo.%20*%2F%0A%20%20%20%20%20%20%20%20%20%20%20%20NumberOfReads%20%3D%20(uint8)(((Base-%26gt%3BFSR)%20%26amp%3B%20LPSPI_FSR_RXCOUNT_MASK)%20%26gt%3B%26gt%3B%20LPSPI_FSR_RXCOUNT_SHIFT)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(NumberOfReads%20!%3D%200u)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F*%20Limits%20to%20remaining%20frames.%20*%2F%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(NumberOfReads%20%26gt%3B%20(State-%26gt%3BExpectedFifoReads%20-%20State-%26gt%3BRxIndex))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20NumberOfReads%20%3D%20(uint8)(State-%26gt%3BExpectedFifoReads%20-%20State-%26gt%3BRxIndex)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F*%20If%20these%20are%20the%20first%20frames%20of%20this%20channel.%20Current%20TXFIFO%20slot%20must%20be%20plus%201%20because%20the%20slot%20of%20CMD%20have%20moved%20out%20*%2F%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(0u%20%3D%3D%20State-%26gt%3BRxIndex)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20State-%26gt%3BCurrentTxFifoSlot%20%2B%3D%201u%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F*%20Read%20Data%20from%20RX%20FIFO%20*%2F%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Lpspi_Ip_ReadDataFromFifo(Instance%2C%20NumberOfReads)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F*%20Update%20current%20FIFO%20slots%20are%20available%20to%20fill%20.*%2F%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20State-%26gt%3BCurrentTxFifoSlot%20%2B%3D%20NumberOfReads%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ElapsedTicks%20%3D%200u%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F*%20TRANSMIT%20DATA%20*%2F%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F*%20Push%20Data%20until%20HW%20fifo%20is%20full%20or%20transfer%20is%20done.%20*%2F%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F*%20After%20driver%20code%20read%20all%20frames%20in%20RX%20FIFO%2C%20if%20there%20are%20still%20some%20frames%20in%20TX%20FIFO%2C%20at%20the%20time%20before%20driver%20code%20check%20number%20of%20frames%20available%20in%20TX%20FIFO%0A%20%20%20%20%20%20%20%20%20%20%20%20to%20prepare%20to%20fill%20TX%20FIFO.%20At%20that%20time%2C%20interrupt%20occurred%2C%20and%20the%20time%20to%20process%20interrupt%20is%20longer%20than%20the%20time%20to%20transfer%20all%20frames%20in%20TX%20FIFO.%0A%20%20%20%20%20%20%20%20%20%20%20%20So%20TX%20FIFO%20will%20be%20empty%20and%20some%20frames%20received%20in%20RX%20FIFO%2C%20then%20the%20program%20is%20returned%20from%20interrupt%20and%20fill%20TX%20FIFO%20until%20full.%0A%20%20%20%20%20%20%20%20%20%20%20%20And%20there%20is%20a%20interrupt%20occurred%20after%20that%20before%20read%20all%20frames%20in%20RX%20FIFO%2C%20and%20the%20time%20to%20process%20interrupt%20is%20longer%20than%20the%20time%20to%20transfer%20all%20frames%20in%20TX%20FIFO.%0A%20%20%20%20%20%20%20%20%20%20%20%20State-%26gt%3BCurrentTxFifoSlot%20variable%20is%20used%20to%20hanlde%20number%20of%20frames%20are%20%22on%20bus%20transfer%22.%20They%20are%20always%20less%20than%20FIFO%20size%20*%2F%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20((State-%26gt%3BCurrentTxFifoSlot%20!%3D%200u))%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(State-%26gt%3BExpectedFifoWrites%20!%3D%20State-%26gt%3BTxIndex)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20NumberOfWrites%20%3D%20State-%26gt%3BCurrentTxFifoSlot%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F*%20Limits%20to%20remaining%20frames.%20*%2F%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(NumberOfWrites%20%26gt%3B%20(State-%26gt%3BExpectedFifoWrites%20-%20State-%26gt%3BTxIndex))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20NumberOfWrites%20%3D%20(uint8)(State-%26gt%3BExpectedFifoWrites%20-%20State-%26gt%3BTxIndex)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F*%20Push%20Data%20into%20TX%20FIFO%20*%2F%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Lpspi_Ip_PushDataToFifo(Instance%2C%20NumberOfWrites)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20State-%26gt%3BCurrentTxFifoSlot%20-%3D%20NumberOfWrites%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ElapsedTicks%20%3D%200u%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20((FALSE%20%3D%3D%20State-%26gt%3BKeepCs)%20%26amp%3B%26amp%3B%20(0u%20!%3D%20(Base-%26gt%3BTCR%20%26amp%3B%20LPSPI_TCR_CONT_MASK)))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F*%20Clear%20CS%20*%2F%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Base-%26gt%3BTCR%20%26amp%3B%3D%20~(LPSPI_TCR_CONT_MASK%20%7C%20LPSPI_TCR_CONTC_MASK)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20ElapsedTicks%20%2B%3D%20OsIf_GetElapsed(%26amp%3BCurrentTicks%2C%20LPSPI_IP_TIMEOUT_METHOD)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(ElapsedTicks%20%26gt%3B%3D%20TimeoutTicks)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Status%20%3D%20LPSPI_IP_TIMEOUT%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20((LPSPI_IP_STATUS_SUCCESS%20!%3D%20Status)%20%7C%7C%20(0u%20%3D%3D%20Length))%0A%20%20%20%20%20%20%20%20%7B%0A%23if%20(STD_OFF%20%3D%3D%20LPSPI_IP_DEV_ERROR_DETECT)%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F*%20Return%20Fail%20status%20if%20length%20is%200.%20Error%20Detect%20is%20enabled%2C%20nothing%20need%20to%20be%20done%20here%20*%2F%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(0u%20%3D%3D%20Length)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Status%20%3D%20LPSPI_IP_STATUS_FAIL%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%23endif%0A%20%20%20%20%20%20%20%20%20%20%20%20State-%26gt%3BStatus%20%3D%20LPSPI_IP_FAULT%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20else%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20State-%26gt%3BStatus%20%3D%20LPSPI_IP_IDLE%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20return%20Status%3B%0A%7D%3C%2FCODE%3E%3C%2FPRE%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-2322796%22%20slang%3D%22en-US%22%20mode%3D%22CREATE%22%20translate%3D%22no%22%3ERe%3A%20s32k3%20%E2%80%9CLpspi_Ip_SyncTransmit_FromIsr%E2%80%9D%20Can%20this%20function%20use%20DMA%20transmission%3F%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2322796%22%20slang%3D%22en-US%22%20mode%3D%22CREATE%22%3E%3CP%3E%3CSPAN%3E%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%E3%80%81Petr%E3%81%95%E3%82%93%E3%80%82%E3%81%94%E8%BF%94%E4%BF%A1%E3%81%82%E3%82%8A%E3%81%8C%E3%81%A8%E3%81%86%E3%81%94%E3%81%96%E3%81%84%E3%81%BE%E3%81%99%E3%80%82SPI%3C%2FSPAN%3E%3CSPAN%3E%E3%83%91%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%B3%E3%82%B9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E8%BF%BD%E5%8A%A0%E3%81%AE%E8%B3%AA%E5%95%8F%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82%3C%2FSPAN%3E%3C%2FP%3E%3CP%3E%3CSPAN%3E%E7%A7%81%E3%81%9F%E3%81%A1%E3%81%AE%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%A7%E3%81%AF%E3%80%81MCU%20%E3%81%AF%20SPI%20%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%BC%E3%81%A8%E3%81%97%E3%81%A6%E6%A9%9F%E8%83%BD%E3%81%97%E3%80%81%E3%83%9B%E3%82%B9%E3%83%88%20(%E3%82%B9%E3%83%AC%E3%83%BC%E3%83%96)%20%E3%81%AF%20GPIO%20%E5%89%B2%E3%82%8A%E8%BE%BC%E3%81%BF%E3%83%94%E3%83%B3%E3%82%92%E3%82%A2%E3%82%B5%E3%83%BC%E3%83%88%E3%81%97%E3%81%A6%E3%80%81%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%81%AE%E6%BA%96%E5%82%99%E3%81%8C%E5%AE%8C%E4%BA%86%E3%81%97%E3%81%9F%E3%81%93%E3%81%A8%E3%82%92%E9%80%9A%E7%9F%A5%E3%81%97%E3%81%BE%E3%81%99%E3%80%82%E6%AC%A1%E3%81%AB%E3%80%81MCU%20%E3%81%AF%E5%89%B2%E3%82%8A%E8%BE%BC%E3%81%BF%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E3%81%A7%20SPI%20%E8%BB%A2%E9%80%81%E3%82%92%E9%96%8B%E5%A7%8B%E3%81%97%E3%80%81%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E8%A7%A3%E6%9E%90%E3%81%97%E3%81%A6%20CAN%20%E7%B5%8C%E7%94%B1%E3%81%A7%E8%BB%A2%E9%80%81%E3%81%97%E3%81%BE%E3%81%99%E3%80%82%20%3C%2FSPAN%3E%3C%2FP%3E%3CP%3E%3CSPAN%3E%E7%8F%BE%E5%9C%A8%E3%80%814%E3%81%A4%E3%81%AECAN%E3%83%81%E3%83%A3%E3%83%8D%E3%83%AB%E9%96%93%E3%81%A7%E5%AE%89%E5%AE%9A%E3%81%97%E3%81%9F%E3%82%B9%E3%83%AB%E3%83%BC%E3%83%97%E3%83%83%E3%83%88%E3%82%92%E6%8F%90%E4%BE%9B%E3%81%99%E3%82%8B%3CSTRONG%3ELpspi_Ip_SyncTransmit%3C%2FSTRONG%3E%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82%E3%81%97%E3%81%8B%E3%81%97%E3%80%81%E9%80%9F%E5%BA%A6%E3%82%92%E6%9C%80%E5%A4%A7%E5%8C%96%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%ABDMA%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AE%3CSTRONG%3ELpspi_Ip_AsyncTransmit%3C%2FSTRONG%3E%E3%81%AB%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88%E3%82%8B%E3%81%A8%E3%80%81%E4%BC%9D%E9%80%81%E9%80%9F%E5%BA%A6%E3%81%8C%E9%9D%9E%E5%B8%B8%E3%81%AB%E4%B8%8D%E5%AE%89%E5%AE%9A%E3%81%AB%E3%81%AA%E3%82%8A%E3%80%81%E3%83%81%E3%83%A3%E3%83%8D%E3%83%AB%E3%83%AC%E3%83%BC%E3%83%88%E3%81%8C%E5%A4%A7%E3%81%8D%E3%81%8F%E5%A4%89%E5%8B%95%E3%81%97%E3%81%BE%E3%81%99%E3%80%82%3C%2FSPAN%3E%3CSPAN%3E%E3%81%BE%E3%81%9F%E3%80%81%E5%85%A8%E4%BD%93%E7%9A%84%E3%81%AA%E9%80%9F%E5%BA%A6%E3%82%82%3CSTRONG%3ELpspi_Ip_SyncTransmit%3C%2FSTRONG%3E%E3%81%AE%E3%83%AC%E3%83%99%E3%83%AB%E3%81%AB%E9%81%94%E3%81%97%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82%3C%2FSPAN%3E%3C%2FP%3E%3CP%3E%3CSPAN%3E%E3%81%93%E3%81%AE%E5%89%B2%E3%82%8A%E8%BE%BC%E3%81%BF%E9%A7%86%E5%8B%95%E5%9E%8B%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%BC%20%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%81%A7%3CSTRONG%3ELpspi_Ip_AsyncTransmit%3C%2FSTRONG%3E%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E5%AE%89%E5%AE%9A%E3%81%97%E3%81%9F%E9%AB%98%E9%80%9F%20SPI%20%E8%BB%A2%E9%80%81%E3%82%92%E5%AE%9F%E7%8F%BE%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E6%8E%A8%E5%A5%A8%E3%81%95%E3%82%8C%E3%82%8B%E3%82%A2%E3%83%97%E3%83%AD%E3%83%BC%E3%83%81%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%81%8B%3F%20%3C%2FSPAN%3E%3C%2FP%3E%3CP%3E%3CSPAN%3E%E5%AE%9C%E3%81%97%E3%81%8F%E3%81%8A%E9%A1%98%E3%81%84%E8%87%B4%E3%81%97%E3%81%BE%E3%81%99%E3%80%81%E3%83%81%E3%82%A7%E3%83%B3%3C%2FSPAN%3E%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-2322486%22%20slang%3D%22en-US%22%20mode%3D%22CREATE%22%20translate%3D%22no%22%3ERe%3A%20s32k3%20%E2%80%9CLpspi_Ip_SyncTransmit_FromIsr%E2%80%9D%20Can%20this%20function%20use%20DMA%20transmission%3F%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2322486%22%20slang%3D%22en-US%22%20mode%3D%22CREATE%22%3E%3CP%3E%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%E3%80%81%3C%2FP%3E%0A%3CP%3E%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%20RTD%20%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%81%AF%E3%82%8F%E3%81%8B%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%81%8C%E3%80%81Lpspi_Ip_SyncTransmit_FromIsr()%20%E3%81%AF%20RTD%20%E3%81%AB%E3%81%AF%E3%81%AA%E3%81%84%E3%82%88%E3%81%86%E3%81%A7%E3%81%99%E3%80%82%3CBR%20%2F%3E%E3%82%B3%E3%83%BC%E3%83%89%E3%81%A7%E3%81%AF%20DMA%20%E3%81%8C%E6%98%8E%E7%A4%BA%E7%9A%84%E3%81%AB%E7%84%A1%E5%8A%B9%E3%81%AB%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%9F%E3%82%81%E3%80%81DMA%20%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82%3CBR%20%2F%3EDMA%20%E3%81%8C%E5%BF%85%E8%A6%81%E3%81%AA%E5%A0%B4%E5%90%88%20%E2%86%92%20SpiPhyUnit%20%2F%20RM%20%2F%20DMAMUX%20%E3%81%A7%20DMA%20%E3%82%92%E6%9C%89%E5%8A%B9%E3%81%AB%E3%81%97%E3%81%A6%20Lpspi_Ip_AsyncTransmit()%20%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%BE%E3%81%99%E3%80%82%3C%2FP%3E%0A%3CP%3EBR%E3%80%81%E3%83%9A%E3%83%88%E3%83%AB%3C%2FP%3E%3C%2FLINGO-BODY%3E