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.

Got EOT Interrupt?

Other Parts Discussed in Thread: TM4C123GH6PZ

I have a board with TI TM4C123GH6PZ, the board(SSI MASTER) has a spi connection with TM4C123GH6PZ(SSI SLAVE) at SSI1.

in TM4C codes, i disabled SSI 4 interrupt by codes:

 SSIIntClear ( SSI1_BASE, 3 );
 SSIIntDisable ( SSI1_BASE, 0xf ); //Disable SSI four interrupts, except EOT and DMA TX/RX
 IntEnable ( INT_SSI1 );

then enable DMA TX/RX and SSI1 by codes

    SSIDMAEnable ( SSI1_BASE, SSI_DMA_RX | SSI_DMA_TX );
    SSIEnable ( SSI1_BASE );

but in SSI1 ISR codes, I notice sometimes u32IntStatus is 0.  I think this case the interrupt cause is an EOT interrupt,

void SSI1IntHandler ( void )
{
volatile uint32_t u32IntStatus = uDMAIntStatus(); volatile uint32_t ui32Status = SSIIntStatus ( ssi1Dma.ssixBase, 1 ); SSIIntClear ( ssi1Dma.ssixBase, ui32Status ); if ( !uDMAChannelIsEnabled ( ssi1Dma.ssixRxDMAChan ) && ( u32IntStatus &(1<<(ssi1Dma.ssixRxDMAChan&0x1f)))) //if ( !uDMAChannelIsEnabled ( ssi1Dma.ssixRxDMAChan ) ) { UpdateSSIRecvBuffer ( ( void* ) &ssi1Dma ); } if ( (!uDMAChannelIsEnabled ( ssi1Dma.ssixTxDMAChan )) && ( u32IntStatus &(1<<(ssi1Dma.ssixTxDMAChan&0x1f)))) //if ( !uDMAChannelIsEnabled ( ssi1Dma.ssixTxDMAChan ) ) { ssi1Dma.dmaSendCompleted = true; } uDMAIntClear ( u32IntStatus );
}

I am not sure my guess is true: the interrupt is EOT when u32IntStatus is 0. could anyone help me? and what's an external loopback? in my case, the board and TM4C is an external loopback or not?

In Freescale SPI mode only, a condition can be created where an EOT interrupt is generated
for every byte transferred even if the FIFO is full. If the EOT bit has been set to 0 in an
integrated slave SSI and the μDMA has been configured to transfer data from this SSI to
a Master SSI on the device using external loopback, an EOT interrupt is generated by the
SSI slave for every byte even if the FIFO is full.

Thanks.

  • Hello Phage,

    There is a known errata on the TM4C12x devices. Please see errata sheet for TM4C123x devices and the errata SSI#07.

    Regards
    Amit
  • Hi Amit,

    in my case, TM4C is used as slave, the main board is SPI master.

    when uDMAIntStatus return 0 in the ISR, i checked the SSICR1 register, EOT bit is 0, the value of SSICR1 is 6(SLAVE, SSI ENABLED)

  • in the forum, i see most codes does NOT check if it is TX/RX DMA completed, most codes only check TX/RX DMA enabled or not.
    how about this scenario:
    1. RX DMA completed, 2,RX completed ISR invoked. 3 if this time, after RX DMA channel enable API invoked, check TX DMA channel enabled, what's the status of TX_DMA_CHANNEL? presume, NO ANY TX DMA operation before.
  • Hello Phage,

    On the TM4C123x devices, there is no DONE interrupt logged as a bit in the Interrupt Status of the peripheral. In fact the interrupt for DMA done is triggered on the same interrupt line as the peripheral and the CPU must go and check the status of the DMA channel to see if the interrupt is from DMA completion.

    Regards
    Amit
  • Hi Amir,

    In the datasheet it says as I has 7 interrupt types. 4 could be masked, rot and two Dan complete .

    When I masked 4. There only has rot and Dma complete interrupts.

    So when dmaint status api returns 0.  is it eot?and why eot if it is.

    How to identify eot with other means?

    Thanks.

  • Hello Phage,

    On the receive side, there is no EOT interrupt. The EOT is on the transmitter side. When the DMA interrupt is triggered and the DMA channel interrupt status bit is set, it means that the DMA has read the data from the SSI RX FIFO and stored it in SRAM.

    Regards
    Amit
  • I don't understand, how could ISR could be called when u32IntStatus = uDMAIntStatus(); u32IntStatus is 000000000000000000000. and SSI1 initialized with four interrupts disabled by code:

        SSIIntClear ( SSI1_BASE, 3 );
        SSIIntDisable ( SSI1_BASE, 0xf ); //Disable SSI four interrupt
        IntEnable ( INT_SSI1 );
    
        ConfigureSSIxDMA ( &ssi1Dma );
        SSIDMAEnable ( SSI1_BASE, SSI_DMA_RX | SSI_DMA_TX );
        SSIEnable ( SSI1_BASE );

    in the datasheet, it say there has 7 interrupt, the first four could be dsiabled by API SSIIntDisable.

    The SSI can generate interrupts when the following conditions are observed:
    ■ Transmit FIFO service (when the transmit FIFO is half full or less)
    ■ Receive FIFO service (when the receive FIFO is half full or more)
    976
    June 12, 2014
    Texas Instruments-Production DataTiva TM TM4C123GH6PZ Microcontroller
    ■ Receive FIFO time-out
    ■ Receive FIFO overrun
    ■ End of transmission
    ■ Receive DMA transfer complete
    ■ Transmit DMA transfer complete
    All of the interrupt events are ORed toge

  • Hello Phage,

    In TM4C123x devices, the DMA done interrupt is logically "OR-ed" with the interrupt from the peripheral. So even if you disable the Interrupt source in the SSI controller, but use DMA channel, the DMA completion will be triggered on the same line as the SSI interrupt.

    Regards
    Amit
  • Hi Amit,
    but uDMAIntStatus returns 0 in the ISR codes, which means no any TX/RX DMA channel completes its task, or no any DMA task to complete.
    SSIIntDisable ( SSI1_BASE, 0xf ); //Disable SSI four interrupt
    only masks the four interrupts:
    ■ Transmit FIFO service (when the transmit FIFO is half full or less)
    ■ Receive FIFO service (when the receive FIFO is half full or more)
    ■ Receive FIFO time-out
    ■ Receive FIFO overrun

    my question is the ISR is designed as DMA completed ISR as datasheet suggests. how could it be invoked while uDMAIntStatus returns 0?
    anything I do wrong in my codes?

    Thanks!
    Phage
  • Hello Phage

    Well that would require some debug. What does uDMAChannelModeGet return for the mode of operation?

    Regards
    Amit
  • Hi Amit,

    DMA does some SPI transmit and receive.

    as you can see in the code above, in the ISR codes, it checks both RxChannel and TxChannel.

    void SSI1IntHandler ( void )
    {
        volatile uint32_t u32IntStatus = uDMAIntStatus();
        volatile uint32_t ui32Status = SSIIntStatus ( ssi1Dma.ssixBase, 1 );
        SSIIntClear ( ssi1Dma.ssixBase, ui32Status );
    
        if ( !uDMAChannelIsEnabled ( ssi1Dma.ssixRxDMAChan ) && ( u32IntStatus &(1<<(ssi1Dma.ssixRxDMAChan&0x1f))))
        //if ( !uDMAChannelIsEnabled ( ssi1Dma.ssixRxDMAChan ) )
        {
            UpdateSSIRecvBuffer ( ( void* ) &ssi1Dma );
        }
        if ( (!uDMAChannelIsEnabled ( ssi1Dma.ssixTxDMAChan )) && ( u32IntStatus &(1<<(ssi1Dma.ssixTxDMAChan&0x1f))))
        //if (  !uDMAChannelIsEnabled ( ssi1Dma.ssixTxDMAChan ) )
        {
            ssi1Dma.dmaSendCompleted = true;
        }
        uDMAIntClear ( u32IntStatus );
    }

    but if use these codes:

        //if ( !uDMAChannelIsEnabled ( ssi1Dma.ssixRxDMAChan ) && ( u32IntStatus &(1<<(ssi1Dma.ssixRxDMAChan&0x1f))))
        if ( !uDMAChannelIsEnabled ( ssi1Dma.ssixRxDMAChan ) )
        {
            UpdateSSIRecvBuffer ( ( void* ) &ssi1Dma );
        }
        //if ( (!uDMAChannelIsEnabled ( ssi1Dma.ssixTxDMAChan )) && ( u32IntStatus &(1<<(ssi1Dma.ssixTxDMAChan&0x1f))))
        if (  !uDMAChannelIsEnabled ( ssi1Dma.ssixTxDMAChan ) )
        {
            ssi1Dma.dmaSendCompleted = true;
        }

    it seems working well.

    Thanks!

  • Hi Amit,

    Do I need to call uDMAChannelModeGet in the ISR?

    Thanks!
  • Hi Amit,

    modified the ISR.

    add a breakpoint in the if UARTprintf(%d_%d....);

    void SSI1IntHandler ( void )
    {
        volatile uint32_t u32IntStatus = uDMAIntStatus();
        volatile uint32_t ui32Status = SSIIntStatus ( ssi1Dma.ssixBase, 1 );
        SSIIntClear ( ssi1Dma.ssixBase, ui32Status );
    
        if ( !uDMAChannelIsEnabled ( ssi1Dma.ssixRxDMAChan ) && ( u32IntStatus &(1<<(ssi1Dma.ssixRxDMAChan&0x1f))))
        //if ( !uDMAChannelIsEnabled ( ssi1Dma.ssixRxDMAChan ) )
        {
            UpdateSSIRecvBuffer ( ( void* ) &ssi1Dma );
        }
        if ( (!uDMAChannelIsEnabled ( ssi1Dma.ssixTxDMAChan )) && ( u32IntStatus &(1<<(ssi1Dma.ssixTxDMAChan&0x1f))))
        //if (  !uDMAChannelIsEnabled ( ssi1Dma.ssixTxDMAChan ) )
        {
            ssi1Dma.dmaSendCompleted = true;
        }
        if ( u32IntStatus == 0)
        {
        	UARTprintf("%d_%d\n", uDMAChannelModeGet(ssi1Dma.ssixRxDMAChan), uDMAChannelModeGet(ssi1Dma.ssixTxDMAChan));
        }
        uDMAIntClear ( u32IntStatus );
    }

    then i see 0_0 in the serial port.

    Thanks!

  • the ssi1Dma is defined and initialized :
    ssixDMAStruct ssi1Dma =
    {
    .ssixBase = SSI1_BASE,
    .ssixDataRegAddr = SSI1_BASE + SSI_O_DR,
    .ssixTxDMAChan = UDMA_CH25_SSI1TX,
    .ssixRxDMAChan = UDMA_CH24_SSI1RX,
    ...
    };
  • Hello Phage,

    The configuration seems correct. Can you please confirm if you are using BASIC mode, or PING-PONG mode or AUTO mode of transfer?

    uDMAChannelModeGet must be called in the ISR.

    Regards
    Amit
  • hi Amir,

    I checked the get mode api return value for both tx and rx channel. They are zero when udmaintstatus returns zero.

    And in my opinion,

    Get mode api and is channel enable is similar. They are used to check which dam channel completed.

    I am not sure which one can know if there is no tx or rx dam operation. If no dma operation, what value should both api return?

    Can they know from the returned value it is nodma or dam completed?

    Thanks,

  • basic mode used.
  • Hello Phage,

    That is strange that the uDMAIntStatus is returning 0. I would need to check this in a test case of mine.

    Regards
    Amit