This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RM57L843: SPI DMA Ping Pong Configuration

Part Number: RM57L843


Hello,

I have configured SPI DMA in normal mode to transmit and receive data from external ADC.

But I want to continuously receive ADC samples, for that I want to configure SPI DMA receive in Ping Pong style configuration.

How can I implement DMA ping pong configuration, an example code will be helpful.

Thanks,

Shantanu S.

  • Hello Shantanu,

    For SPI receive, the source address of DMA transfer is SPI BUF register which is fixed. You can modify the destination address in DMA interrupt notification or SPI INT notification.

    dmaRAMREG->PCP[DMA_CH0].IDADDR  = (uint32)&NEW_ADDR;

  • Hi,

    Do I need to disable DMA and then perform the buffer change and then re-enable DMA ? , since I'm changing the control packet configuration.

    Regards,

    Shantanu S.

  • Hello Shantanu,

    No.

    Please see the notes in TRM:

    NOTE: Changing the contents of a channel control packet will clear the corresponding pending bit (Section 20.3.1.2) if the channel has a pending status. If the control packet of an active channel (as indicated in Section 20.3.1.3) is changed, then the channel will stop immediately at an arbitration boundary. When the same channel is triggered again, it will begin with the new control packet information.

    I'd like to know when or at what condition you switch the DMA destination to other buffer.

  • Hello,

    Currently I'm switching buffer in dmaGroupANotification(), bellow is the attached code.

     g_dmaCTRL stctrl_rx; // control packet object
    
    void dmaGroupANotification(dmaInterrupt_t inttype, uint32 channel)
    {
    
        /*  enter user code between the USER CODE BEGIN and USER CODE END. */
        /* USER CODE BEGIN (8) */
        if(inttype == LFS){
            if(channel == DMA_CH0){
                ucRxThrDMAflag_g=1; // flag to indicate dma interrupt for processing of buffers
                if( ePING_BUFF == ELastUsedBuff )
                {
                    stctrl_rx.DADD = (uint32_t)&stDCDCDMAMeas_g.uiDMARxPong; /* switch to pong buff */
                    ELastUsedBuff = ePONG_BUFF;
                    EBuffToProcess = ePING_BUFF;
                    dmaSetCtrlPacket(DMA_CH1, stDCDCDMAMeas_g.stctrl_rx);
                    cycles_PMU_code = 1;
                    gioSetBit(hetPORT1, BIT23, 1);//tp 28
                }
                else
                {
                    stctrl_rx.DADD = (uint32_t)&stDCDCDMAMeas_g.uiDMARxPing; /* switch to ping buff */
                    ELastUsedBuff = ePING_BUFF;
                    EBuffToProcess = ePONG_BUFF;
                    dmaSetCtrlPacket(DMA_CH1, stctrl_rx);
                    
                }
    
                /* trigger dma  */
                dmaSetChEnable(DMA_CH0, DMA_HW);
                dmaSetChEnable(DMA_CH1, DMA_HW);
                spiREG1->GCR1   |= (1U << 24UL);
                spiREG1->INT0   |= (1U << 16UL);
            }
        }
    }

    I have initialize the control packet object in my initialization, below is the code for it;

    stctrl_rx.DADD = (uint32_t)&stDCDCDMAMeas_g.uiDMARxPing; /* initialize rx destination to ping buff */
    ELastUsedBuff = ePING_BUFF;
    
    stctrl_rx.SADD        = (uint32_t)&(spiREG1->BUF);
    stctrl_rx.CHCTRL      = 0;
    stctrl_rx.FRCNT       = COUNT;
    stctrl_rx.ELCNT       = 1;
    stctrl_rx.ELDOFFSET   = 0;                /* element destination offset */
    stctrl_rx.ELSOFFSET   = 0;                /* element destination offset */
    stctrl_rx.FRDOFFSET   = 0;                /* frame destination offset   */
    stctrl_rx.FRSOFFSET   = 0;                /* frame destination offset   */
    stctrl_rx.PORTASGN    = PORTB_READ_PORTA_WRITE;
    stctrl_rx.RDSIZE      = ACCESS_16_BIT;
    stctrl_rx.WRSIZE      = ACCESS_16_BIT;
    stctrl_rx.TTYPE       = FRAME_TRANSFER;   /* transfer type              */
    stctrl_rx.ADDMODERD   = ADDR_FIXED;       /* address mode read          */
    stctrl_rx.ADDMODEWR   = ADDR_INC1;        /* address mode write         */
    stctrl_rx.AUTOINIT    = AUTOINIT_OFF;     /* autoinit                   */
    
        dmaSetCtrlPacket(DMA_CH0, stDCDCDMAMeas_g.stctrl_tx);
        dmaSetCtrlPacket(DMA_CH1, stDCDCDMAMeas_g.stctrl_rx);
        dmaEnableInterrupt(DMA_CH0, LFS, DMA_INTA);
        dmaEnableInterrupt(DMA_CH1, LFS, DMA_INTA);
        dmaEnable();  //enable dma

    I hope this is sufficient and I'm doing it the right way.

    Let me know if you want to know any other details.

    Regards,

    Shantanu S.

  • Please try your code. if any issue, let me know.