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.

TMS570LS1227: SPI2 communication problem in slave mode when DMA is enabled

Part Number: TMS570LS1227
Other Parts Discussed in Thread: ADS125H02, HALCOGEN

I've configured SPI2 as slave and MIBSPI1 as master and both use DMA. When MIBSPI1 isn't in use, SPI2 works fine but when MIBSPI1 starts data transfer, SPI2 communication fails. As far as I could see, the data in the DMA buffer is shifted a few bits.

There are 3 ADC chips connected to the MIBSPI port and the MCU reads data at 7.2K sample rate from each ADC chips. SPI2 and MIBSPI1 use BTC and FTC DMA interrupts respectively. I also changed dmaFTCAInterrupt function in sys_dma.c and it calls another function when FTC interrupt is triggered.

Another thing is that data size of the SPI2 isn't fixed. It first receives 3 16-bits words as header. This header contains the package size and then the MCU changes DMA buffer size to send/receive number of bytes defined in the header.

When the SPI2 is configured in ISR mode, it works without problem up to 4MHz.

#define CONFIG_SPI_TX_DMA_CH    DMA_CH13
#define CONFIG_SPI_RX_DMA_CH    DMA_CH12
#define CONFIG_SPI_TX_DMA_REQ   3ul
#define CONFIG_SPI_RX_DMA_REQ   2ul

#define CONFIG_SPI_HEADER_SIZE  3
#define CONFIG_SPI_PORT         spiREG2

#define CONFIG_SPI_TX_ADDR      ((uint32_t)(&(CONFIG_SPI_PORT->DAT1)) + 2)
#define CONFIG_SPI_RX_ADDR      ((uint32_t)(&(CONFIG_SPI_PORT->BUF)) + 2)



void dmaConfigSPICtrlTxPacket(g_dmaCTRL * g_dmaCTRLPKT_TX, uint32 sadd, uint32 dadd, uint16 FrameCnt)
{
    g_dmaCTRLPKT_TX->SADD      = sadd;               /* source address             */
    g_dmaCTRLPKT_TX->DADD      = dadd;               /* destination  address       */
    g_dmaCTRLPKT_TX->CHCTRL    = 0;                  /* channel control            */
    g_dmaCTRLPKT_TX->FRCNT     = FrameCnt;           /* frame count                */
    g_dmaCTRLPKT_TX->ELCNT     = 1;                  /* element count              */
    g_dmaCTRLPKT_TX->ELDOFFSET = 0;                  /* element destination offset */
    g_dmaCTRLPKT_TX->ELSOFFSET = 0;                  /* element source offset      */
    g_dmaCTRLPKT_TX->FRDOFFSET = 0;                  /* frame destination offset   */
    g_dmaCTRLPKT_TX->FRSOFFSET = 0;                  /* frame source offset        */
    g_dmaCTRLPKT_TX->PORTASGN  = 4;                  /* port b                     */
    g_dmaCTRLPKT_TX->RDSIZE    = ACCESS_16_BIT;      /* read size                  */
    g_dmaCTRLPKT_TX->WRSIZE    = ACCESS_16_BIT;      /* write size                 */
    g_dmaCTRLPKT_TX->TTYPE     = FRAME_TRANSFER;     /* transfer type              */
    g_dmaCTRLPKT_TX->ADDMODERD = ADDR_INC1;          /* address mode read          */
    g_dmaCTRLPKT_TX->ADDMODEWR = ADDR_FIXED;         /* address mode write         */
    g_dmaCTRLPKT_TX->AUTOINIT  = AUTOINIT_ON;        /* autoinit                   */
}

void dmaConfigSPICtrlRxPacket(g_dmaCTRL * g_dmaCTRLPKT_RX, uint32 sadd, uint32 dadd, uint16 FrameCnt)
{
    g_dmaCTRLPKT_RX->SADD      = sadd;               /* source address             */
    g_dmaCTRLPKT_RX->DADD      = dadd;               /* destination  address       */
    g_dmaCTRLPKT_RX->CHCTRL    = 0;                  /* channel control            */
    g_dmaCTRLPKT_RX->FRCNT     = FrameCnt;           /* frame count                */
    g_dmaCTRLPKT_RX->ELCNT     = 1;                  /* element count              */
    g_dmaCTRLPKT_RX->ELDOFFSET = 0;                  /* element destination offset */
    g_dmaCTRLPKT_RX->ELSOFFSET = 0;                  /* element source offset      */
    g_dmaCTRLPKT_RX->FRDOFFSET = 0;                  /* frame destination offset   */
    g_dmaCTRLPKT_RX->FRSOFFSET = 0;                  /* frame source offset        */
    g_dmaCTRLPKT_RX->PORTASGN  = 4;                  /* port b                     */
    g_dmaCTRLPKT_RX->RDSIZE    = ACCESS_16_BIT;      /* read size                  */
    g_dmaCTRLPKT_RX->WRSIZE    = ACCESS_16_BIT;      /* write size                 */
    g_dmaCTRLPKT_RX->TTYPE     = FRAME_TRANSFER;     /* transfer type              */
    g_dmaCTRLPKT_RX->ADDMODERD = ADDR_FIXED;         /* address mode read          */
    g_dmaCTRLPKT_RX->ADDMODEWR = ADDR_INC1;          /* address mode write         */
    g_dmaCTRLPKT_RX->AUTOINIT  = AUTOINIT_ON;        /* autoinit                   */
}

void setConfigSPIDMA(void)
{
    g_dmaCTRL g_dmaCTRLPKT;

    dmaEnableInterrupt(CONFIG_SPI_RX_DMA_CH, BTC);     //Block transfer complete
    dmaReqAssign(CONFIG_SPI_RX_DMA_CH, CONFIG_SPI_RX_DMA_REQ);    //SPI2 RX
    dmaReqAssign(CONFIG_SPI_TX_DMA_CH, CONFIG_SPI_TX_DMA_REQ);    //SPI2 TX

    dmaConfigSPICtrlTxPacket(&g_dmaCTRLPKT, (uint32_t)&ResponseData, CONFIG_SPI_TX_ADDR, CONFIG_SPI_HEADER_SIZE);
    dmaSetCtrlPacket(CONFIG_SPI_TX_DMA_CH, g_dmaCTRLPKT);
    dmaConfigSPICtrlRxPacket(&g_dmaCTRLPKT, CONFIG_SPI_RX_ADDR, (uint32_t)&RX_Data.PacketArray, CONFIG_SPI_HEADER_SIZE);
    dmaSetCtrlPacket(CONFIG_SPI_RX_DMA_CH, g_dmaCTRLPKT);
    dmaSetChEnable(CONFIG_SPI_RX_DMA_CH, DMA_HW);    //SPI2 RX, hardware triggering
    dmaSetChEnable(CONFIG_SPI_TX_DMA_CH, DMA_HW);    //SPI2 TX, hardware triggering

    dmaSetPriority(CONFIG_SPI_RX_DMA_CH, HIGHPRIORITY);
    dmaSetPriority(CONFIG_SPI_TX_DMA_CH, HIGHPRIORITY);

    CONFIG_SPI_PORT->GCR1 = (CONFIG_SPI_PORT->GCR1 & 0xFFFFFFFFU) | (0x1 << 24);  //Enable SPI
    CONFIG_SPI_PORT->INT0 = (0x1 << 16); //SPI_DMAREQ; Enable DMA REQ only after setting the SPIEN bit to 1.
}

void sendAndGetSPIData(uint32_t outputBuffer, uint32_t inputBuffer, uint32_t ucDataLength)
{
    dmaRAMREG->PCP[CONFIG_SPI_TX_DMA_CH].ISADDR = outputBuffer;
    dmaRAMREG->PCP[CONFIG_SPI_TX_DMA_CH].IDADDR = CONFIG_SPI_TX_ADDR;
    dmaRAMREG->PCP[CONFIG_SPI_TX_DMA_CH].ITCOUNT = (ucDataLength << 16U) | 1;

    dmaRAMREG->PCP[CONFIG_SPI_RX_DMA_CH].IDADDR = inputBuffer;
    dmaRAMREG->PCP[CONFIG_SPI_RX_DMA_CH].ISADDR = CONFIG_SPI_RX_ADDR;
    dmaRAMREG->PCP[CONFIG_SPI_RX_DMA_CH].ITCOUNT = (ucDataLength << 16U) | 1;

    dmaSetChEnable(CONFIG_SPI_RX_DMA_CH, DMA_HW);    //SPI2 RX, hardware triggering
    dmaSetChEnable(CONFIG_SPI_TX_DMA_CH, DMA_HW);    //SPI2 TX, hardware triggering

    CONFIG_SPI_PORT->GCR1 = (CONFIG_SPI_PORT->GCR1 & 0xFFFFFFFFU) | (0x1 << 24);  //Enable SPI
    CONFIG_SPI_PORT->INT0 = (0x1 << 16); //SPI_DMAREQ; Enable DMA REQ only after setting the SPIEN bit to 1.
    while((dmaREG->PEND & (1ul << 0)) != 0ul);
}

void getConfigSPIData(uint32_t buffer, uint32_t ucDataLength)
{
    dmaRAMREG->PCP[CONFIG_SPI_RX_DMA_CH].IDADDR = buffer;
    dmaRAMREG->PCP[CONFIG_SPI_RX_DMA_CH].ISADDR = CONFIG_SPI_RX_ADDR;
    dmaRAMREG->PCP[CONFIG_SPI_RX_DMA_CH].ITCOUNT = (ucDataLength << 16U) | 1;

    dmaSetChEnable(CONFIG_SPI_RX_DMA_CH, DMA_HW);    //SPI2 RX, hardware triggering
    dmaSetChEnable(CONFIG_SPI_TX_DMA_CH, DMA_HW);    //SPI2 TX, hardware triggering
    CONFIG_SPI_PORT->GCR1 = (CONFIG_SPI_PORT->GCR1 & 0xFFFFFFFFU) | (0x1 << 24);  //Enable SPI
    CONFIG_SPI_PORT->INT0 = (0x1 << 16); //SPI_DMAREQ; Enable DMA REQ only after setting the SPIEN bit to 1.
    while((dmaREG->PEND & (1ul << 0)) != 0ul);
}

void dmaGroupANotification(dmaInterrupt_t inttype, uint32 channel)
{
    CONFIG_SPI_PORT->INT0 &= ~(1ul << 16);
    CONFIG_SPI_PORT->GCR1 &= ~(0x1 << 24);
    ProcessSPI2();
}

void dmaFTCAInterrupt(void)
{
    uint32 offset = dmaREG->FTCAOFFSET;

	if (offset != 0U)
	{
		dmaGroupANotificationFTC(FTC, offset - 1U);
	}
}

void dmaBTCAInterrupt(void)
{
    uint32 offset = dmaREG->BTCAOFFSET;

    if (offset != 0U)
    {
        dmaGroupANotification(BTC, offset - 1U);
    }
}

  • Hi Chihan Kaya,

    In the both DMA's we are only transferring one element per frame, so in that case enabling frame wise interrupt for MibSPI1 is not efficient. If frame wise interrupt is required for MibSPI1 then it would be better to use it in interrupt mode.

    --

    Thanks,

    Jagadish.

  • Hi Jagadish,

    DMA config packages for SPI2 and MIBSPI are different. For SPI2, element count is 1 and frame count is the number of words we would like to send/receive. For MIBSPI1, element count is the number of words we would like to send/receive and frame count is 1. Also, as I mentioned before, MIBSPI and SPI2 use different DMA interrupt sources. SPI2 uses BTC while MIBSPI1 uses FTC. Does changing DMA control package parameters make any difference or is there any way to use DMA for SPIs?

    You can find MIBSPI1 dma control package configuratuins below:

    void dmaMibSPIConfigCtrlTxPacket(g_dmaCTRL * g_dmaCTRLPKT_TX, uint32_t sadd, uint32_t dadd, uint32_t dsize){
        g_dmaCTRLPKT_TX->SADD      = sadd;              /* source address             */ /*TXDATA_9B*/
        g_dmaCTRLPKT_TX->DADD      = dadd;              /* destination  address       */ /*mibspiRAM1->tx[0].data*/
        g_dmaCTRLPKT_TX->CHCTRL    = 0;                 /* channel control            */
        g_dmaCTRLPKT_TX->FRCNT     = 1;                 /* frame count                */
        g_dmaCTRLPKT_TX->ELCNT     = dsize;             /* element count              */
        g_dmaCTRLPKT_TX->ELDOFFSET = 4;                 /* element destination offset */
        g_dmaCTRLPKT_TX->ELSOFFSET = 0;                 /* element source offset      */
        g_dmaCTRLPKT_TX->FRDOFFSET = 0;                 /* frame destination offset   */
        g_dmaCTRLPKT_TX->FRSOFFSET = 0;                 /* frame source offset        */
        g_dmaCTRLPKT_TX->PORTASGN  = 4;                 /* port B                     */
        g_dmaCTRLPKT_TX->RDSIZE    = ACCESS_16_BIT;     /* read size                  */
        g_dmaCTRLPKT_TX->WRSIZE    = ACCESS_16_BIT;     /* write size                 */
        g_dmaCTRLPKT_TX->TTYPE     = BLOCK_TRANSFER;    /* transfer type              */
        g_dmaCTRLPKT_TX->ADDMODERD = ADDR_INC1;         /* address mode read          */
        g_dmaCTRLPKT_TX->ADDMODEWR = ADDR_OFFSET;       /* address mode write         */
        g_dmaCTRLPKT_TX->AUTOINIT  = AUTOINIT_ON;       /* autoinit                   */
    }
    
    void dmaMibSPIConfigCtrlRxPacket(g_dmaCTRL * g_dmaCTRLPKT_RX, uint32_t sadd, uint32_t dadd, uint32_t dsize){
        g_dmaCTRLPKT_RX->SADD      = sadd;              /* source address             */ /*mibspiRAM1->rx[0].data*/ /*(uint32_t)(&(mibspiRAM1->rx[15].data))*/
        g_dmaCTRLPKT_RX->DADD      = dadd;              /* destination  address       */ /*RXDATA_9B*/
        g_dmaCTRLPKT_RX->CHCTRL    = 0;                 /* channel control            */
        g_dmaCTRLPKT_RX->FRCNT     = 1;                 /* frame count                */
        g_dmaCTRLPKT_RX->ELCNT     = dsize;             /* element count              */
        g_dmaCTRLPKT_RX->ELDOFFSET = 0;                 /* element destination offset */
        g_dmaCTRLPKT_RX->ELSOFFSET = 4;                 /* element source offset      */
        g_dmaCTRLPKT_RX->FRDOFFSET = 0;                 /* frame destination offset   */
        g_dmaCTRLPKT_RX->FRSOFFSET = 0;                 /* frame source offset        */
        g_dmaCTRLPKT_RX->PORTASGN  = 4;                 /* port B                     */
        g_dmaCTRLPKT_RX->RDSIZE    = ACCESS_16_BIT;     /* read size                  */
        g_dmaCTRLPKT_RX->WRSIZE    = ACCESS_16_BIT;     /* write size                 */
        g_dmaCTRLPKT_RX->TTYPE     = BLOCK_TRANSFER;    /* transfer type              */
        g_dmaCTRLPKT_RX->ADDMODERD = ADDR_OFFSET;       /* address mode read          */
        g_dmaCTRLPKT_RX->ADDMODEWR = ADDR_INC1;         /* address mode write         */
        g_dmaCTRLPKT_RX->AUTOINIT  = AUTOINIT_ON;       /* autoinit                   */
    } 

    Regards,
    Cihan

  • Hi Cihan,

    Can you try to set different priorities once and test it?

    Instead of same priorities for both Tx and Rx, as below

    Can you set high priority to SPI2 which is stop working when MibSPI2 is enabled, and set low priority to MibSPI2. Like as below

    dmaSetPriority(CONFIG_SPI_RX_DMA_CH, HIGHPRIORITY);
    dmaSetPriority(CONFIG_SPI_TX_DMA_CH, LOWPRIORITY);

    Please do above modification and let me know the result.

    --

    Thanks,

    Jagadish.

  • Hi Jagadish,

    Changing interrupt priority didn't make any difference. When the MIBSPI is active, SPI2 stops working.

    Regards,
    Cihan

  • Hi Cihan,

    Is it possible to share the complete project code by zip?
    --

    Thanks,

    Jagadish.

  • Hi Jagadish,

    I can't share the complete project but I can create a minimal version of the projetct which includes all DMA controls and all peripherals that use DMA.

    Regards,
    Cihan

  • Hi Cihan,

    I can create a minimal version of the projetct which includes all DMA controls and all peripherals that use DMA.

    This would really helpful to understand and resolve the issue.

    --

    Thanks,

    Jagadish.

  • Hi Jagadish,

    I sent a private message. You can find the project there.

    Regards,
    Cihan

  • Hi Cihan,

    I verified your DMA channels and Requests mapping and it looks fine for me, I will discuss with my senior colleague once and i will get back to you.

    --

    Thanks,

    Jagadish.

  • Hi Cihan,

    The SPI2 uses DMA channel 12 and channel 13, with lowest priority(As channel number increases priority will decrease) compared to the DMA channels used by MibSPI1 and MibSPI5. If MibSPI1 keeps TXing or RXing data using DMA, the SPI2 may not get served.

    So can you please allocate lowest number channels to SPI2 once and do test?

    --

    Thanks,

    Jagadish.

  • Hi Jagadish,

    As you suggested I allocated CH0 and CH1 to SPI TX and RX channels, respectively. But we still have the same communication issue.

    BTW, we use DMA for I2C as well but I forgot to add I2C DMA library. I2C uses DMA chanell CH14 and CH15. I can send it if you need.

    Regards,
    Cihan

  • Hi Cihan,

    Your DMA channel mapping looks fine now and dont know why it is failing when you enabled MibSPI1.

    Now i am trying to get inputs from my team and it might take some time. And also i dont have TMS570LS1227 board to recreate the problem at my end.

    --

    Thanks,

    Jagadish.

  • Hi Jagadish,

    Thank you for the update.

    Regards,
    Cihan

  • Hi Cihan,

    Sorry for the delay, are you still stuck with this issue?
    The problem is, i am unable to reproduce your issue at my end, can you share your entire code? 

    So that i can execute that at my end and i can reproduce the issue at my end.

    --

    Thanks,

    Jagadish. 

  • Hi Jagadish,

    Yes, we are still stuck with this problem.

    Unfortunately I can't share the full project but I could generate the issue with the project I sent you.


    Did you just test the SPI2? The thing is, this issue happens when MIBSPI1 is in use as well, There are 3 ADC chips connected to MIBSPI and we read data at 7.200 sample per second from each ADC. Another thing is, we read data from these ADC chips when they set their data ready pin. These create interrupt in the TMS and TMS reads ADC data. So you will need similar setup to reproduce the issue at your end.

    The ADC chip we use is ADS125H02.

    Regards,
    Cihan

  • Hi Cihan,

    Is SPI2 completely stops working when MibSPI1 in use or we receiving wrong data ?

    I don't have setup to create the problem,

    Can we create same issue using some memory to memory transfers on SPI2 and MibSPI1?

    Can we plan one webex session, where you can demonstrate the issue for us?

    I saw the ADS125H02 datasheet and find that this slave device will support from 2.5SPS to 40SPS, can you reduce the sampling rate from 7.2 and verify whether there is an improvement in SPI2 or not?

    --

    Thanks & Regards,

    Jagadish.

  • Hi Jagadish,
    You can find my answers below marked in red:

    Is SPI2 completely stops working when MibSPI1 in use or we receiving wrong data ?
    CK: It receives wrong data. As far as I could see, the data is shifted butthe number of bits shifted changes.

    I don't have setup to create the problem,

    Can we create same issue using some memory to memory transfers on SPI2 and MibSPI1?
    CK: Do you mean DMA or something else? Could you give more detail about that?

    Can we plan one webex session, where you can demonstrate the issue for us?
    CK: Sure, I will create a setup asap and let you know.

    I saw the ADS125H02 datasheet and find that this slave device will support from 2.5SPS to 40SPS, can you reduce the sampling rate from 7.2 and verify whether there is an improvement in SPI2 or not?
    CK: We usually run the system at 7.2K each. I also tried lower sample rates like 100SPS but no to avail.

    Regards,
    Cihan

  • Hi Cihan,

    CK: Do you mean DMA or something else? Could you give more detail about that?

    JG: I mean we don't have ADC chips to trigger your problem right, so what i am saying is in your case you are using DMA to transfer MibSPI data to the some memory right, instead of that what if we use some memory to memory transfer using DMA without any ADC chips requirement. If issue occurs even for memory to memory transfer with DMA also then we can easily trigger the issue at our end also with the same code.

    CK: Sure, I will create a setup asap and let you know.

    JG: Thanks.

    --

    Thanks & Regards,

    Jagadish.

  • Hi Jagadish,

    Is there any sample project for memory to memory transfer?

    I will also simulate mibSPI communication using SPI loopback feature. So, we can test the system without ADC chips.

    Regards,
    Cihan

  • Hi Cihan,

    DMA_memory_to_memory.zip

    The attachment is the sample memory to memory transfer example, 

    In this example we have two memories TX_DATA and RX_DATA each of 500 elements size, and DMA will transfer data from TX_DATA memory to RX_DATA memory. After transferring data to RX_DATA it clears RX_DATA and again DMA will transfer data from TX_DATA and repeats the process continuously.

    Do the following steps in your code:

    Remove Code related to MibSPI1 and add this example code to your project (No need to do any additional configurations in HALCoGen for this code)

    Here i used DMA_CH0 but in this place you can use the channel you used for MibSPI, even you can comment the clearing RX_DATA buffer because this creates some delay between transfers, if we did comment this, we can create continuous flow on DMA channel

    After doing above steps just do test and observe whether SPI2 DMA transfer data corrupting or not.

    --

    Thanks & Regards,

    Jagadish.

  • Hi Jagadish,

    Thanks for the code, I will try it.

    Regards,
    Cihan

  • Hi Jagadish,

    I added memory to memory transfer codes in to my project and changed  a little. I created 3 memory to memory dma channels and set data length to 9 elements instead 500. I also changed DMA interrupt type to FTC since in our design, FTC is used by MibSPI only and SPI2, QSPI and I2C use BTC.

    With this configuration, I could generate 150K dma data transfers per second from each of 3 channels and SPI2 worked without problem.

    I have few questions regarding your dma configuration.
    - Your setup calls dmaSetChEnable with DMA_SW and this configuration works but when I set DMA_HW, DMA transfer is triggered only when the MCU receives data from SPI2. Note that, in sys_dma.c, dmaFTCAInterrupt and dmaBTCAInterrupt ISRs call different functions. I've changed dmaFTCAInterrupt function to call a different function. The project I had sent has that change.

    - Your code has only one dmaConfigCtrlPacket call but I had to set the control package, dma channel and request assign for both TX and RX sides of all SPIs and I2C. Is is possible to configure Rx side only (or TX side only)?

    - Also your dmaConfigCtrlPacket configuration is different than mine. Are my configurations correct?

    - In our design there is one gpio pin connected to the all 3 ADC chips' enable pin. With this, we can start/stop ADC samplings. But the thing is, since all of them start measuring at the same time, they trigger gio_notification ISR at the same time and in that ISR we call a function which starts MibSPI data reading. Might this overload the MCU and mess up SPI? Does starting/stopping the ADCs with a delay (for example, the second ADC enable pin is set 20us after the first ADC pin has been set) make any difference?

    Regards,
    Cihan

  • Hi Cihan,

    - Your code has only one dmaConfigCtrlPacket call but I had to set the control package, dma channel and request assign for both TX and RX sides of all SPIs and I2C. Is is possible to configure Rx side only (or TX side only)?

    I got your point, but we can't do separate configurations for Tx and Rx in memory-to-memory transfer, we can only increase number of channels by taking more memory-to-memory transfers.

    - Also your dmaConfigCtrlPacket configuration is different than mine. Are my configurations correct?

    -Your configurations are correct.

    Might this overload the MCU and mess up SPI?

    Yes it could be possible.

    -Does starting/stopping the ADCs with a delay (for example, the second ADC enable pin is set 20us after the first ADC pin has been set) make any difference?

    I think it would help make difference, try in that way.

    --

    Thanks & Regards,

    Jagadish.

  • Hi Jagadish,

    I added offsets (delays) to start/stop the ADCs but it didn't help.

    As far as I understand, TMS570 doesn't have nested vector interrupts. How does the MCU react when it receives 2 or more interrupts at the same time? As I mentioned earlier, we have 3 ADC chips that trigger the MCU when data is ready and since all of them are connected to the same enable pin, they will likely trigger the MCU at the same time.

    Another question is, what happens when the MCU reveives another interrupt while it runs ISR from the previous interrupt? And what happens when a third interrupt comes in while the MCU is proccesing the second one? Normally when an interrupt is received, the MCU pausses the function currently being processed and jumps to the ISR and then returns to the previous function when the ISR finished. But what happens when it reveives too much interrupts before finising the previous ISR calls?

    Regards,
    Cihan

  • Hi Cihan,

    As far as I understand, TMS570 doesn't have nested vector interrupts. How does the MCU react when it receives 2 or more interrupts at the same time?

    You are right, Cortex R4/5 does not support interrupt nesting inherently.

    1. The TMS570 provides two vectors for interrupt requests: FIQs and IRQs. FIQs are higher priority than IRQs, and FIQ interrupts may interrupt IRQ interrupts.

    2. The TMS570 uses VIM to prioritize and control the interrupt sources. VIM supports 128 interrupt channels which are mapped to interrupt sources. A lower numbered channel in each FIQ and IRQ has higher priority. 

    3. The ARM Cortex-R4/5 processor does not support interrupt nesting in hardware. It does not support more than one IRQ to be taken at a time. 

    When two IRQ interrupts (or 2 FIQ interrupts) occur at the same time, the interrupt with higher priority is serviced first. The 2nd interrupt will be served after the 1st is done. 

    what happens when the MCU reveives another interrupt while it runs ISR from the previous interrupt?

    If another interrupt occurs while serving the first interrupt ISR then the interrupt pending bit of the second interrupt will get set and after completion of ISR of first interrupt, the processor will now go to the second interrupt ISR handler and starts executes it. Interrupt will never get lost in this condition.

    And what happens when a third interrupt comes in while the MCU is proccesing the second one?

    Even if third or more interrupts occurs the interrupts will never get lost, only the pending bit of the corresponding interrupt will get set. And after executing of first interrupt ISR, the processor checks which interrupt have high priority among the pending interrupts and based on that the processor executes high priority interrupt first and later it executes another interrupt which have low priority.

    The only thing is we should not get multiple interrupts from same interrupt source.

    Example: I am using two different interrupts in my application one is timer and another one is gio. And first i got timer interrupt and i am serving that interrupt and before completing serving of this timer interrupt i got two gio interrupts, in this case the gio handler will get execute only one time not two times because we have only one pending bit for each interrupt.

    I hope it will clear all your doubts related to interrupts.

    --

    Thanks & Regards,

    Jagadish.

  • Hi Jagadish,

    Thank you for your detailed answer. It cleared lots of things. I just have a final interrupt related question.

    In your example you said if you got 2 gio interrupts, the gio handler would execute only once. If there is one gio pin and it's triggered twice, it makes sense. If there are several gio interrupt sources (in our case there are 3 gio interrupt pins - gioA 5, gioA 6 and gioA 7) and these 3 pins are triggered at the same time, will the gio handler execute the last one or will the gio handler execute all 3 one after another (note that, the same pin won't be triggered twice)? Is there another interrupt flag for each of these pins? In the VIM, there aren't ISR functions for each pin individually. There are GIO high and GIO Low interrupts only.

    Regards,
    Cihan

  • Hi Cihan,

    If there are several gio interrupt sources (in our case there are 3 gio interrupt pins - gioA 5, gioA 6 and gioA 7) and these 3 pins are triggered at the same time, will the gio handler execute the last one or will the gio handler execute all 3 one after another (note that, the same pin won't be triggered twice)?


    The gio handler will execute all three one after another and no interrupt will get lost in this case.

    Whenever a gio interrupt occurs the gio interrupt bit of the corresponding interrupt will get set in "GIO Interrupt Flag Register". Here each gio pin have a separate bit, so if multiple interrupts occur then corresponding bit for each interrupt will get set. 
    So, after processing current gio interrupt handler the processor again verifies the pending gio interrupts set in above register and takes the highest priority interrupt and starts executes.  The default priority is like lower gio to higher gio number. So, in your case after executing current handler the processor again executes gioA5, gioA6 and gioA7 respectively.

    --

    Thanks & Regards,

    Jagadish.

  • Hi Jagadish,

    Thank you for the answer.

    I changed DMA BTC interrupt to FIQ, optimised the code it seems that these changes solved the problem. We can use the SPI2 DMA at 8MHz. I will try to optimise the code and test the system more to achive 8+Mhz clock speed.

    Thank you so much for all your help and support.

    Regards,
    Cihan

  • Hi Cihan,

    Good to hear that.

    --

    Regards,

    Jagadish.