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.

TMS570LS0914: Transmission of an SPI message is interrupted

Part Number: TMS570LS0914
Other Parts Discussed in Thread: TMS570LS1224

In my application I use the Mibspi5 for the transmission of 6 * 8Bit message packets. I am observing that it happens that the transmission of a message is interrupted. So in my example 5 bytes are sent first and only after about 2ms the remaining byte is sent afterwards.

How can it happen that a transfer is not fully completed?

The figure shows the transmitted signals. The last section shows that the last byte is sent out much later.

  • Here I have another example with a shorter interruption.

  • From 2nd picture, I noticed that 4 bytes (1st+2nd+3rd+4th) were transferred first, then 2 bytes (6th+7th or 5th+6th) after a short interval. But you transmitted 5 bytes + 2 bytes, and one byte (5th byte or 7th byte) is lost. is my understanding right?

  • Hello,

    There are always packets of 6 bytes sent. What you can see on the picture are 6 bytes, where the first 4 (1st+2nd+3rd+4th) are sent first. And only after a short interruption the other two (5th+6th).

    No byte is missing during this transmission. However, there is a pause between the bytes.

    Kind Regards

    Konstanty

  • Hello again,

    before each transmission the interrupts should be deactivated with _disable_interrupt_(); from the sys_core.h Immediately after sending, the interrupts are switched on again with _enable_interrupt_();.

    For testing I made a while loop where the interrupts are disabled and only one message is sent. Obviously I am still able to receive a response via mibspi5 interrupt.

    So are no interrupts disabled with the function _disable_interrupt_();?

    Kind regards

    Konstanty Kuczynski

  • Hello Konstanty,

    I am sorry that I did not read your message carefully. I though there is 7 words. SPI is inherently synchronous, so a small gap between each word should not cause problem. 

    There are couple things which may affect the delay:

    1. If CSHOLD is not set, the CS setup time (C2TDELAY+2 VCLK period) and hold time (C2EDELAY VCLK period). The minimum setup time is  2VCLK periods

    2. If WDELAY is enabled, the delay between 2 words is (WDELAY+2)*VCLK period

    3. If WDELAY is not enabled, there is at least 2VCLK periods delay between two words if CSHOLD is not set.

    _disable_interrupt_() will disable IRQ and FIQ in CPU level. The TXINTFLG should still be set when the word is copied from SPIDAT or TXBUF register to the shift register. But no IRQ or FIQ interrupt is generated until the _enable_interrupt_() is called.

  • Hello QJ,

    I have to add something that I have not quite correctly described. I use SPI4 to send the messages and MibSPI5 to receive them.

    I have checked the configurations again. CSHOLD is set and WDELAY = 0. The VCLK frequency is 60Mhz which means that one period lasts 16.67ns.

    The device has no problems with the short distances (e.g. from the second picture). However, the 2ms interrupt during transmission causes problems so that the device does not respond to this message and detects an error.

    I have just disabled all other interrupts (except timer interrupts) as a test. From time to time there are still messages with 2ms interrupts during transmission.

    Are there other possibilities that could cause the problem?

    Kind regards

    Konstanty Kuczynski

  • If CSHOLD=1, and WDELAY=0, the delay between messages is caused by overhead in the spi transmit. Do you use polling mode for data transmission?

  • Yes im using the polling method.

    What does overhead mean at this point? How could I avoid that?

    Kind Regards

    Konstanty Kuczynski

  • Hello,

    spiTransmitData() function transmits data and receive data as well. I just checked the disassembly code for the while() loop in spiTransmitData(), I think the overhead should not be that long (2ms).

    The highlighted instruction writes data to SPI_DAT1 register for transmission.

  • Hello,

    I just run a test on TMS570LS1224 launchpad, the delay between 2 words is less than 1us (CSHOLD=0)

    HCLK=160MHz; VCLK=80MHz, and SPI baudrate = 1mbps; charlen=16; data=0xaaa5, 0xaaa5, 0xaaa5, ...

  • Hello,

    thank you for the support.

    Normally (mostly) this distance between messages is similarly small.

    If this is another interrupt in the system that interrupts the sending of the message, I still don't understand why I can't avoid this with calling _disable_interrupt_(). If I switch interrupts off during transmission, no further interrupts may occur. Or do I misunderstand?

    The tranmiss function, minimally adapted for our application, is as follows:

    static SPI_STATUS_t spi_TMS570LS_transmitPolling(const SPI_CommInterfaceConfig* comConfig, uint8_t length, const uint16_t *dataTx)
    {
        SPIRegister* spiRegister = spi_TMS570LS_getChannel(comConfig->spiChannel);
        volatile uint32_t dataRx;
    
        uint32_t transmitData = ((uint32_t) comConfig->format << 24U) | ((uint32_t) comConfig->chipSelect << 16U) |
                ((uint32_t) SPI_TMS570LS_DELAY_COUNTER_ENABLE << 26) | ((uint32_t) SPI_TMS570LS_CHIP_SELECT_HOLD_CONFIG << 28);
    
        uint8_t nrOfData = comConfig->dataLength;
        if(comConfig->dataLength == 0)
        {
            nrOfData = length;
        }
    
        while(nrOfData != 0U)
        {
            if((spiRegister->FLG & 0x000000FFU) !=0U)
            {
               break;
            }
    
            if(nrOfData == 1U)
            {
                transmitData &= ~(1u << SPI_TMS570LS_CS_HOLD_ACTIVE_AFTER_TRANSACTION_POS);    // disable CS after last transaction
            }
    
            spiRegister->DAT1 = (transmitData & 0xFFFF0000u) | (uint32_t) *dataTx;   // send data
            dataTx++;
    
            uint16_t timeout = spiWaitForTransactionFinished(spiRegister, 0xFF);
            if(timeout == 0u)
            {
                break;
            }
    
            dataRx = spiRegister->BUF;     // clear receive buffer
            nrOfData--;
        }
    
        return spi_TMS570LS_evaluateFailureState(spiRegister, (uint8_t) (spiRegister->FLG & 0xFFU));
    }

    Kind regards

    Konstanty Kuczynski

  • Hi Konstanty,

    The code looks good. You can use PMU to measure the CPU cycles used by the timeout function. I think it should not take that long.The delay in my test is very short.