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.

SPI slave : no more interrupts

Hello,

I'm having a problem with the SPI 1 reception in slave mode on the C6747. I'm not using BIOS.

The SPI is set up in 4-pin mode with SPIx_SCS[n]. The master uses a SCLK frequency of 128 kbps. Small packets (< 10 bytes) are sent frequently to the DSP (every 4 or 5 ms) by the master. The DSP receives each byte and the Rx ISR is executed. The ISR examines each byte and prepares the next Tx byte before the next master clock edge arrives. At this clock frequency, there is 3.9 us (half the clock period) to write the Tx byte to the SPI DATA register. To ensure the lowest ISR latency, the ISR function and associated global variables are placed in L2 RAM. Both L1P and L1D caches are enabled.

To view that the ISR is called when the DSP is running, I toggle a port pin and visualise the state on a scope.

This works fine for the first 10 or 15 seconds but after that no more SPI Rx interrupts are triggered. When debugging with an emulator, I halt after this has happened and check the SPIFLG register: the data overrun flag OVRNINTFLG is asserted.

I've tried many strategies in the Rx ISR, the following runs the longest before the SPI Rx IRQ stops triggering. Here are the first lines of my ISR (the rest are for preparing the Tx byte):

    Uint32 lReg;
    Uint8  lRxData;
    Uint8  lErr;

    lErr = 0;
    while (1)
    {
        /* check error flags in SPIFLG */
        lReg = gCommDev->SPIBUF;

        /* clear rx flags */
        gCommDev->SPIFLG = (CSL_SPI_SPIFLG_RXINTFLG_MASK |
                            CSL_SPI_SPIFLG_DLENERRFLG_MASK |
                            CSL_SPI_SPIFLG_OVRNINTFLG_MASK);

        /* if rx overrun, must read buffer again to empty RXBUF and SPIBUF */
        if (lReg & CSL_SPI_SPIBUF_RXOVR_MASK) {
            lRxData = gCommDev->SPIBUF;
        }

        if (!(lReg & (CSL_SPI_SPIBUF_RXOVR_MASK |
                      CSL_SPI_SPIBUF_DLENERR_MASK))) {
            lRxData = (Uint8)lReg;
            break;
        }
        lErr = 1;
    }

After reset, the SPI 1 is configured as so:

CSL_SpiRegsOvly gCommDev = (CSL_SpiRegsOvly)CSL_SPI_1_REGS;

/* bring the SPI out of reset state */
CSL_FINST(gCommDev->SPIGCR0, SPI_SPIGCR0_RESET, OUT_OF_RESET);
/* all SPI registers now have their default values */

/* set the preconfigure data format as 0 */

gCommDev->SPIDAT1 = CSL_FMKT(SPI_SPIDAT1_DFSEL, FORMAT0);

/* disable interrupts */

gCommDev->SPIINT0 = CSL_FMKT(SPI_SPIINT0_RXINTENA, DISABLE);

gCommDev->SPIGCR1 = CSL_SPI_SPIPC0_RESETVAL;

gCommDev->SPIFLG = ~0;        /* clear flags */

gCommDev->SPILVL = CSL_FMKT(SPI_SPILVL_RXINTLVL, INT1) |
                   CSL_FMKT(SPI_SPILVL_OVRNINTLVL, INT1) |
                   CSL_FMKT(SPI_SPILVL_DLENERRLVL, INT1);

gCommDev->SPIINT0 = CSL_FMKT(SPI_SPIINT0_RXINTENA, ENABLE) |
                    CSL_FMKT(SPI_SPIINT0_OVRNINTENA, ENABLE) |
                    CSL_FMKT(SPI_SPIINT0_DLENERRENA, ENABLE);

gCommDev->SPIPC0 = CSL_FMKT(SPI_SPIPC0_CLKFUN, SPI) |
                   CSL_FMKT(SPI_SPIPC0_SIMOFUN, SPI) |
                   CSL_FMKT(SPI_SPIPC0_SOMIFUN, SPI) |
                   CSL_FMKT(SPI_SPIPC0_SCS0FUN0, SPI);

gCommDev->SPIFMT[0] = CSL_FMK(SPI_SPIFMT_CHARLEN, 8) |
                      CSL_FMK(SPI_SPIFMT_PRESCALE, 2) |
                      CSL_FMKT(SPI_SPIFMT_POLARITY, HIGH);

/* ... */

/* here SPI 1 is configured to use IRQ 4 (the highest priority) */

/* ... */

/* activate SPI */
CSL_FINST(gCommDev->SPIGCR1, SPI_SPIGCR1_ENABLE, ENABLE);

How is it possible for the SPI 1 Rx to stop triggering interrupts? Do all status flags have to be cleared and the Rx buffer be emptied (is the above code sufficient)? One thing I do not check is the "dropped interrupt" register in the interrupt controller. Could this help me recover?

Best regards,

SC

 

  • Hi,

    Here is some additional information.

    I connected the Interrupt Error event to IRQ13 and wrote an ISR for this IRQ. I wanted to see if there was a dropped interrupt in the case of an SPI Rx overrun. If so, it would trigger this interrupt. Turns out that the Interrupt Error event is never asserted, even when I'm experiencing the problem.

    I already had a port pin toggling when I entered and exited the SPI 1 Rx ISR. I added another when this ISR detected an SPI error. I also added another for when any other ISR in my system was called (this pin is like a "OR" of all ISRs except the SPI 1 Rx ISR). I connected the SPI bus and the three port pin signals to a logic analyser. Here are my observations.

    - The SPI 1 Rx ISR can last up to 1.2 us. This is inferior to the half SPI clock period limit that I need to respect. No problems there.

    - The latency between the last SPI clock edge and the start of the SPI Rx ISR can be between 500 ns (most of the time) and .... over 50 us!!! This is why I added the third port pin to check if any other ISR was being executed when the last clock edge arrived. My other ISRs are also very short, that said there was never another ISR executing when the last SPI clock edge arrived. Even if it where the case, it could not explain this huge latency I'm seeing sometimes.

    - There are no "_disable_interrupts()" in my application code that could delay the triggering of an ISR. I sometimes disable a single IRQ via the IER register to create an atomic operation on a variable but then I enable that same IRQ afterwards. In any case, I never do this with the IRQ associated with the SPI 1 Rx event.

    What other process in the DSP could delay the triggering of an ISR?

    Best regards,

    SC

  • Hi,

    Some more info that might be pertinent:

    - My application is using the EDMA with several peripherals: McASP Rx and Tx (continuous) and UART (burst). Both transfer controllers are used.

    - Since the L1D cache is enabled and the EDMA reads and writes to SDRAM, I use the cache coherency functions (DSP/BIOS 5.x BCACHE module).

    Do coherency operations done by the cache controller stall the DSP core execution? If I instruct the "write-back" and/or "invalidate" operation to wait for completion, could this also stall the core?

    EDIT: I added a port pin signal transition before and after all calls to BCACHE functions and the execution times are very short, these do not seem to delay or stall the execution of the application. So my question remains: why can the SPI 1 Rx ISR be called so many microseconds after the event while no other ISR is executing nor a cache coherency operation underway?

    Best regards,

    SC

  • Hi again,

    This situation is really blocking me. I have to know very quickly if I have to try a whole new strategy. Or maybe I overlooked something in my existing code.

    Has someone at TI read my post? Did I do the mistake of replying to myself instead of editing my original post which maybe lowers the response priority? Also, I usually post on the C64+ forum and get quick responses, would my problem be more appropriate on that forum?

    Best regards,

    SC

  • Hi SC,

    Is it possible that some external memory access is stalling the jump to the ISR occasionally? For example if you are executing code out of DDR and it hits a refresh just before the interrupt, it might stall until it fetches the data and then jumps to the ISR.

    Can you try cutting down your code such that it is all running internally, and possibly only running code related to the SPI slave functionality? This will help us understand if there are other things running in the system that are causing this.

    Thanks

    Jeff

  • Hi Jeff,

    I'm using SDRAM to store data and code accessed less often than other parts of my application. It is impossible for me to fit everything in internal memory. I'm also using L1P and LID in the "all-cache" configuration. Should I understand that you are referring to data and/or program cache refresh after a cache miss/conflict? I went back to the Cache User's Guide (SPRUG82A) in the section Stall Conditions. If I understand correctly, EDMA operations can delay cache refresh depending on priorities.

    If I configured the L1P and L1D memories to be SRAM+cache and placed the SPI ISR in in L1P and associated data in L1D, would the SPI Rx Event triggering the IRQ have priority over a cache refresh? In other words, with the Rx event arrives will there's a cache refresh, would execution jump to the ISR right away and continue the refresh afterwards?

    I have the impression that optimizing data and code placement to achieve optimal cache use is possible but very time consuming because this must be done manually (something I don't have unfortunately!). I'm using CSS v4.2.4 with an XDS100v2 emulator. Apart from the "cache" window, is there a more powerful tool to visualize cache performance over time?

    If I have time (???), I will make a small project that fits in L2 only and see what happens. But due to my application's size in its standard implementation, external memory is required so I think I will always have this variable latency problem for this SPI ISR...

    Best regards,

    SC

     

  • SC, in the case of a cache miss, the ISR will be delayed until the miss is resolved. If this happens during a DDR refresh cycle, this could delays execution of the ISR even more.

    One thing to try would be to leave L1P and L1D both as cache and configure L2 as 1/2 cache and 1/2 SRAM. This will increase the amount of cache you have local to the processor so hopefully you will see fewer cache misses.

    Another thing you could test to help isolate the problem:  Boot and configure your system as normal.  Instead of running your application, just have an empty while loop and then let the SPI + ISR run to see if you have any interrupt problems.  This would hopefully be an easy thing to try and would give us more information on if it truly is related to the cache.

    Jeff

  • Hi Jeff,

    Thanks for confirming the behaviour and for the suggestions.

    Unfortunately, my application cannot tolerate any SPI ISR latency caused by cache misses or refresh cycles. Even if I use more cache, there's still the probability of a delay.

    I will think of another strategy for SPI.

    Best regards,

    SC