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.

TIRTOS 2.10 to 2.12 SPI CHANGES CAUSING TASK TO FREEZE

Other Parts Discussed in Thread: TM4C1294NCPDT, SYSBIOS

Running latest CCSV6.1 on Windows 8.1 with latest TIRTOS 2.12, converting a TIRTOS 2.10 project

My question: "What has changed in the TIRTOS version 2.12 regarding the SPI Operation?."

Previously my code ran fine, but now I find the task which has the SPI operating freezes when the following code is executed

lcdTransferOK = SPI_transfer(LCD_SPI, &lcdTransaction);

 

With TIRTSOS 2.10 there was no issue, however under 2.12 the task containing this call will run a random number of times then freeze completely. ROV shows the task as Blocked UNKNOWN.

 

To verify the SPI is the issue, I changed the SPI_Open to include transferTimeout of 1000

SPI_Params_init(&lcdSpiParams);

lcdSpiParams.mode = SPI_MASTER;

lcdSpiParams.frameFormat = SPI_POL1_PHA1; // clock high in idle, clock on rising edge

lcdSpiParams.transferMode = SPI_MODE_BLOCKING;

lcdSpiParams.transferTimeout = 1000;

lcdSpiParams.dataSize = 8;

lcdSpiParams.bitRate = 1000000;

lcdSpiParams.transferCallbackFxn = NULL;

LCD_SPI = SPI_open(Board_SPI3, &lcdSpiParams);

 

Now my task runs but intermittently freezes for 1000ms then resumes again.

So I know the SPI is what is causing the freezing, what I don't know is why?

 

 

  • Hi Barry,

    There were a few changes from TI-RTOS 2.10 to 2.12.  Please see the migration docs for more info especially look for Hardware Attributes Changes section.

    Vikram

  • Hello Vikram

    I have read this document and as far as I can see all changes have been made to my code, the SPI is initialising and running.
    However I still find the SPI is requiring to use the timeout every so often instead of completing normally each time.
    The migration document says for SPI I just need to add the intPriority (Which I have done).
    There are no other SPI specific changes mentioned in the documents.

    const SPITivaDMA_HWAttrs spiTivaDMAHWAttrs[A30307P26_SPICOUNT] = {
    {
    SSI0_BASE,
    INT_SSI0,
    (~0),
    &spiTivaDMAscratchBuf[0],
    0xFFFFFFFF,
    UDMA_CHANNEL_SSI0RX,
    UDMA_CHANNEL_SSI0TX,
    uDMAChannelAssign,
    UDMA_CH10_SSI0RX,
    UDMA_CH11_SSI0TX
    },
    {
    SSI1_BASE,
    INT_SSI1,
    (~0),
    &spiTivaDMAscratchBuf[1],
    0,
    UDMA_CHANNEL_SSI1RX,
    UDMA_CHANNEL_SSI1TX,
    uDMAChannelAssign,
    UDMA_CH12_SSI2RX,
    UDMA_CH13_SSI2TX
    },
    {
    SSI3_BASE,
    INT_SSI3,
    (~0),
    &spiTivaDMAscratchBuf[2],
    0,
    UDMA_SEC_CHANNEL_TMR2A_14,
    UDMA_SEC_CHANNEL_TMR2B_15,
    uDMAChannelAssign,
    UDMA_CH14_SSI3RX,
    UDMA_CH15_SSI3TX
    }
    };

    There is no mention in the migration document of the new parameters available in the SPIParams but looking through the code I found them.
    Previously the SPI had no option for the transferTimeout but ran without issue.
    Now in this latest library If I don't set a transferTimeout value the task will freeze waiting for the SPI to complete.
    So something other than just intPriority seems to be at play here.
    I have tried setting the intPriority to the default as recommended and also to different fixed values but always the SPI will at some point have to time out. I know this because it is driving an LCD and when the 1000ms timeout occurs it is easy to see the animation on my LCD freeze. If I have no transferTimeout (like it used to work) the LCD will just freeze.
  • Hi Barry,

    Sorry for the delayed response. This post somehow slipped through the cracks. Are you still facing the issue? Which Tiva Board are you using? Have you tried the SPI loopback example to check if it is working?

    I can try setting up the example if you can tell me the Tiva Board that you are using.

    Thanks,
    Vikram

  • Hello Vikram

    Thanks for the response.

    I was about to chase this up myself.
    I am not using a development board, I am using our own PCB with TMS4C129ENCPT processor.
    I am running an application which uses USB, ETHERNET, UARTS, watchdog interrupts, timer interrupts, ADC, I2C and SPI.
    So quite a lot working together.

    In the TIRTOS version 2.10 I called SpiTransfer with no issues.
    Since changing to 2.12 I find the Spi_Transfer now freezes after a number of calls.

    I verified it is the transfer locking using the debugger and managed to get it working by setting the transferTimeout value to 10ms (expecting a transfer in 1ms)
    If I extend the transferTimeout to 1000ms it is very easy to see the intermittent pauses as the SPI freezes and the timeout kicks in.

    I have not tried the example as it is not trying to do DMA with the other tasks running like my actual code doeas and it seems it
    is this sharing with other tasks which may be the issue.

    I have correctly added intPriority to the SPITivaDMA_HWAttrs
    Currently I am only using SSI0 but other SSI allowed for in the structure

    /* SPI configuration structure, describing which pins are to be used */
    const SPITivaDMA_HWAttrs spiTivaDMAHWAttrs[A30307P26_SPICOUNT] = {
        {
        SSI0_BASE,
            INT_SSI0,
        (~0),
            &spiTivaDMAscratchBuf[0],
            0xFFFFFFFF,
            UDMA_CHANNEL_SSI0RX,
            UDMA_CHANNEL_SSI0TX,
            uDMAChannelAssign,
            UDMA_CH10_SSI0RX,
            UDMA_CH11_SSI0TX
        },
        {
            SSI1_BASE,
            INT_SSI1,
        (~0),
            &spiTivaDMAscratchBuf[1],
            0,
            UDMA_CHANNEL_SSI1RX,
            UDMA_CHANNEL_SSI1TX,
            uDMAChannelAssign,
            UDMA_CH12_SSI2RX,
            UDMA_CH13_SSI2TX
        },
        {
            SSI3_BASE,
            INT_SSI3,
        (~0),
            &spiTivaDMAscratchBuf[2],
            0,
            UDMA_SEC_CHANNEL_TMR2A_14, // BAZ - not sure about this? Recommended by TI person but SSI1 was wrong from them!
            UDMA_SEC_CHANNEL_TMR2B_15, // BAZ - not sure about this? Recommended by TI person but SSI1 was wrong from them!
            uDMAChannelAssign,
            UDMA_CH14_SSI3RX,
            UDMA_CH15_SSI3TX
        }
    };

    Regards
    Barry

  • Hi Barry,

    I think the spiTivaDMAHWAttrs setup looks good except for the highlighted elements below:

    Barry Andrews said:
        {
            SSI1_BASE,
            INT_SSI1,
        (~0),
            &spiTivaDMAscratchBuf[1],
            0,
            UDMA_CHANNEL_SSI1RX,
            UDMA_CHANNEL_SSI1TX,
            uDMAChannelAssign,
            UDMA_CH12_SSI2RX,
            UDMA_CH13_SSI2TX
        },

    Shouldn't these be SSI1?

    Vikram

  • Hello Vikram

    Previously I was using SSI1 to read a serial flash with these setting and no issues, I haven't tested this under TIRTOS 2.12 yet.

    You can correct me if I am wrong here but I currently have SSI0 using channels 10 & 11 of the DMA.

    So my understanding is I cannot use the same DMA channels for SSI1, I need to use unique DMA channels for each device that requires DMA.

    The defines are the most common recommended DMA channels, not the only channels

    For each DMA channel there are a number of defines

    The definition for SSI1 only has channels 10 & 11 same as SSI0 so I cannot assign both SSI devices the same DMA channels.

    I just tried changing this to

    UDMA_CH24_SSI1RX, UDMA_CH25_SSI1TX

    And this worked fine, so I will use these settings

    If I am wrong here, by all means please correct me.

    Even with this changed to channels 24 & 25 I still am having the intermittent pauses on SSI0.

    Thanks

    Barry

  • Just an update.

    It is SSI3 which is driving my LCD continuously and locking intermittently, SSI0 is the one not being used.
    I am not using SSI1 all the time, just for diagnostics at the moment as I develop the FLASH reading / writing functions.
    I have noticed that sometimes this also freezes for my 1000ms timeout period
    so it seems that definitely SSI1 and SSI3 and possibly all SPI channels are affected by the change from 2.10 to 2.12
  • Barry, Can you please provide us an example to reproduce the issue? Thanks.

  • Hello Vikram

    I am not sure how much of the other tasks being active is required to cause the issue to occur.

    I haven't cut my code back to a minimum to see at what point it will operate correctly and at what point it will fail.

    Below is the function call that locks up and freezes waiting for the SPI_Transfer to complete.

    If I set the transferTimeout to say 1000 I will see intermittent 1000ms pauses in my animation.

    This task that is freezing is simply updating the LCD write buffer and writing that to the display.

    This gives me animated icons for the operator, so it is easy to see the freezing.

    If I leave transferTimeout at 0 the LCD task will just halt and the other tasks all run fine.

    I am not using the callback function for transfer complete.

    When the task halts it will be waiting for the transfer complete mutex.

    Below is how I initialise the SPI and how I call it and all my SPI initialisation tables in my board definition.

    Whilst I setup for 3 possible SSI only the serial flash and the LCD are used.

    The serial flash only runs a few times at start up to check the flash is present as I haven't finished the flash code yet.

    LCD runs continuously on a 50ms update.

    //*****************************************************************************

    // LCD SPI interface items

    //*****************************************************************************

    static SPI_Handle LCD_SPI;

    static SPI_Transaction lcdTransaction;

    static UChar lcdRxBuffer[MAX_LCD_WR];

    UInt lcdTransferOK;

    #ifdef ST7565_DIRTY_PAGES

    uint8_t ST7565_dirty_pages;

    #endif

    //*****************************************************************************

    // Writes a data word to the LCD.

    //*****************************************************************************

    static void WriteBLock(UChar * ui8Data, UChar Size)

    {

    // Address HIGH - DATA

    SetLCD_A0;

    // Limit to size of buffer

    if (Size > MAX_LCD_WR)

    Size = MAX_LCD_WR;

    // Initialise LCD SPI transaction structure

    lcdTransaction.count = Size;

    lcdTransaction.txBuf = (Ptr)ui8Data;

    lcdTransaction.rxBuf = (Ptr)lcdRxBuffer;

    // Initiate SPI transfer

    lcdTransferOK = SPI_transfer(LCD_SPI, &lcdTransaction);

    }

    //*****************************************************************************

    // Writes a command byte to the LCD.

    //*****************************************************************************

    static void WriteCommand(uint8_t ui8Data)

    {

    // Address LOW - COMMAND

    ClrLCD_A0;

    // Initialise LCD SPI transaction structure

    lcdTransaction.count = 1;

    lcdTransaction.txBuf = (Ptr)&ui8Data;

    lcdTransaction.rxBuf = (Ptr)lcdRxBuffer;

    // Initiate SPI transfer

    lcdTransferOK = SPI_transfer(LCD_SPI, &lcdTransaction);

    }

    // ===========================================================

    // ST7565_init - Initialises the LCD interface using SPI3

    // ===========================================================

    void ST7565_init(char StartSpi)

    {

    uint32_t ui32ClockMS;

    SPI_Params lcdSpiParams;

    if (StartSpi)

    {

    // Initialise SPI handle with Master mode

    SPI_Params_init(&lcdSpiParams);

    lcdSpiParams.mode = SPI_MASTER;

    lcdSpiParams.frameFormat = SPI_POL1_PHA1; // clock high in idle, clock on rising edge

    lcdSpiParams.transferMode = SPI_MODE_BLOCKING;

    // lcdSpiParams.transferTimeout = 250; // BAZ: Sanity timer added in 2.12 because SPI was freezing

    lcdSpiParams.transferTimeout = 10; // BAZ: Sanity timer added in 2.12 because SPI was freezing

    lcdSpiParams.dataSize = 8;

    lcdSpiParams.bitRate = 1000000; // 1MHz clocking

    lcdSpiParams.transferCallbackFxn = NULL;

    LCD_SPI = SPI_open(Board_SPI3, &lcdSpiParams);

    if (LCD_SPI != NULL)

    {

    System_printf("LCD SPI initialised\n");

    System_flush();

    }

    }

    // Determine the number of system clock cycles in 1mS

    ui32ClockMS = CYCLES_FROM_TIME_US(ui32SysClock, 1000);

    // Divide by 3 to get the number of SysCtlDelay loops in 1mS.

    ui32ClockMS /= 3;

    SetLCD_A0; // Address line high

    SysCtlDelay(10 * ui32ClockMS); // Delay for 10ms.

    ClrLCD_RST; // Activate LCD RESET

    SysCtlDelay(250 * ui32ClockMS); // Delay for 250ms

    SetLCD_RST; // RESET OFF

    SysCtlDelay(250 * ui32ClockMS); // Delay for 250ms

    WriteCommand(ST7565_CMD_BIAS_9); // Set LCD Bias

    WriteCommand(ST7565_CMD_VERTICAL_REVERSE); // Common Direction Select, bit3=1,reverse direction=0,normal

    WriteCommand(ST7565_CMD_POWER_CONTROL | ST7565_PWR_INTERNAL_CONV);

    SysCtlDelay(20 * ui32ClockMS); // Delay for 20ms.

    WriteCommand(ST7565_CMD_POWER_CONTROL | ST7565_PWR_INTERNAL_CONV | ST7565_PWR_INTERNAL_REG);

    SysCtlDelay(20 * ui32ClockMS); // Delay for 20ms.

    WriteCommand(ST7565_CMD_POWER_CONTROL | ST7565_PWR_INTERNAL_CONV | ST7565_PWR_INTERNAL_REG | ST7565_PWR_INTERNAL_FOL);

    SysCtlDelay(20 * ui32ClockMS); // Delay for 20ms.

    WriteCommand(ST7565_CMD_RESISTOR | 0x04); // Set ra/rb 0x25

    WriteCommand(ST7565_CMD_VOLUME_MODE); // Set Contrast

    WriteCommand(39); // Contrast = 39 (Range 0..63)

    WriteCommand(ST7565_CMD_DISPLAY_ON); // Display ON

    ST7565_blank(); // Blank the display

    ST7565_flip_screen(1); // set the screen orientation to suit standard ASE position

    SetLCD_BL; // turn on the LCD backlight

    }

    /* SPI objects */

    SPITivaDMA_Object spiTivaDMAobjects[A30307P26_SPICOUNT];

    #if defined(__TI_COMPILER_VERSION__)

    #pragma DATA_ALIGN(spiTivaDMAscratchBuf, 32)

    #elif defined(__IAR_SYSTEMS_ICC__)

    #pragma data_alignment=32

    #elif defined(__GNUC__)

    __attribute__ ((aligned (32)))

    #endif

    uint32_t spiTivaDMAscratchBuf[A30307P26_SPICOUNT];

    /* SPI configuration structure, describing which pins are to be used */

    const SPITivaDMA_HWAttrs spiTivaDMAHWAttrs[A30307P26_SPICOUNT] = {

    {

    SSI0_BASE,

    INT_SSI0,

    (~0),

    &spiTivaDMAscratchBuf[0],

    0xFFFFFFFF,

    UDMA_CHANNEL_SSI0RX,

    UDMA_CHANNEL_SSI0TX,

    uDMAChannelAssign,

    UDMA_CH10_SSI0RX,

    UDMA_CH11_SSI0TX

    },

    {

    SSI1_BASE,

    INT_SSI1,

    (~0),

    &spiTivaDMAscratchBuf[1],

    0,

    UDMA_CHANNEL_SSI1RX,

    UDMA_CHANNEL_SSI1TX,

    uDMAChannelAssign,

    UDMA_CH24_SSI1RX,

    UDMA_CH25_SSI1TX

    },

    {

    SSI3_BASE,

    INT_SSI3,

    (~0),

    &spiTivaDMAscratchBuf[2],

    0,

    UDMA_SEC_CHANNEL_TMR2A_14,

    UDMA_SEC_CHANNEL_TMR2B_15,

    uDMAChannelAssign,

    UDMA_CH14_SSI3RX,

    UDMA_CH15_SSI3TX

    }

    };

    const SPI_Config SPI_config[] = {

    {&SPITivaDMA_fxnTable, &spiTivaDMAobjects[0], &spiTivaDMAHWAttrs[0]},

    {&SPITivaDMA_fxnTable, &spiTivaDMAobjects[1], &spiTivaDMAHWAttrs[1]},

    {&SPITivaDMA_fxnTable, &spiTivaDMAobjects[2], &spiTivaDMAHWAttrs[2]},

    {NULL, NULL, NULL},

    };

    /*

    * ======== A30307P26_initSPI ========

    */

    Void A30307P26_initSPI(Void)

    {

    // SSI0 - MicroSD

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    GPIOPinConfigure(GPIO_PA2_SSI0CLK);

    GPIOPinConfigure(GPIO_PA3_SSI0FSS);

    GPIOPinConfigure(GPIO_PA4_SSI0XDAT0);

    GPIOPinConfigure(GPIO_PA5_SSI0XDAT1);

    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);

    // SSI1 - Serial Flash

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);

    GPIOPinConfigure(GPIO_PB5_SSI1CLK);

    GPIOPinConfigure(GPIO_PB4_SSI1FSS);

    GPIOPinConfigure(GPIO_PE4_SSI1XDAT0);

    GPIOPinConfigure(GPIO_PE5_SSI1XDAT1);

    GPIOPinTypeSSI(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5);

    GPIOPinTypeSSI(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5);

    // SPI3 - The Mono LCD SPI Port

    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);

    GPIOPinConfigure(GPIO_PQ0_SSI3CLK);

    GPIOPinConfigure(GPIO_PQ1_SSI3FSS); // Hardware control of CS

    GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0);

    GPIOPinConfigure(GPIO_PQ3_SSI3XDAT1);

    GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);

    A30307P26_initDMA();

    SPI_init();

    }

  • Barry, 

    Setting transferTimeout = 0 will cause the SPI transfer to immediately timeout. Maybe your SPI transfer for animation takes longer than the other timeout values you tried setting. 

    Have you tried setting transferTimeout = SPI_WAIT_FOREVER?

    lcdSpiParams.transferTimeout = SPI_WAIT_FOREVER;

    Vikram

  • Sorry that was my error in my description.

    It's not when I set timeoutTransfer to 0 that it locks, it is when I leave it as default (SPI_WAIT_FOREVER) that it does exactly what it says and waits forever.

    It I set the timeout to something longer than I expect the transfer to wait it will recover.

    If it is SPI_WAIT_FOREVER sometimes it works and exits when the transfer is complete (which in my case should be less than 1ms) but sometimes it never returns.

    That's where my issue lies it is like there is a timing issue with the SPI complete notification and the mutex such that sometime the complete notification doesn't exit the mutex and hence that task just stays blocked.

  • I don't have the exact Tiva device but I have a Connected Launchpad with TM4C1294NCPDT which is very similar to the the device you have. I am able to get the spiloopback working using TI-RTOS 2.12.01.33. I went further and modified the example to continuously do a loopback spi transfer for 1000 times. I did not see the SPI task freezing/blocking. My SPI configuration uses default transferTimeout (i.e. SPI_WAIT_FOREVER)

    If it is SPI_WAIT_FOREVER sometimes it works and exits when the transfer is complete (which in my case should be less than 1ms) but sometimes it never returns.

    From the statement, it looks like it works sometimes. Is there any other higher priority Task/Hwi/Swi that is continuously running when SPI blocks for I/O and SPI Task never gets to run again? if not, you may need to run the spiloopback example and test or cut down your application code to identify the issue.

    I am attaching the spiloopback code that I used to test for your reference.

    Vikram1376.spiloopback_TivaTM4C1294NCPDT.zip

  • Thanks for the effort Vikram.

    My application has 6 other tasks running, one which has higher priority 1 terminates before the issues occur.

    There is one other with the same priority 2, all the other tasks are priority 3.

    I also have Ethernet running, USB running which generate their own timer interrupts and tasks.

    As well as this I am using Analog inputs (not under DMA) and I have timer interrupts running.

    So it is a pretty full on application.

    Where do you suggest I start reducing in order to isolate the cause of the issue?

  • I suggest starting with the spiloopback example or just running SPI part of your application to make sure the configuration for TI-RTOS 2.12 is working fine. If we have an example that can reproduce the issue, then it would help identifying the cause.

    Vikram
  • I just cut everything back to absolute minimum.
    Turned off all Ethernet and USB.
    Turned off the watchdog.
    Turned off all tasks except the initialisation task and the LCD task.
    Left the SPI transfer timeout at default of FOREVER

    Run the application for 1r 2 minutes and LCD will eventually freeze.
    My LCD task does a Mailbox_pend with timeout of 50ms then the LCD update as I have turned the other tasks and interrupts off this will always timeout at 50ms.

    So a lot more than 1000 iterations occurring (more like 5000 to 10000) and only one task running as Init task just checks all my system settings then terminates itself.

    Looking at ROV, NDK stack is Blocked and Idle task is running.

    If I get rid of the Init task the LCD task stops almost immediately - Here is the call stack when it freezes

    1 ti_sysbios_knl_Task_schedule__I() at Task.c:75,PC = 0x00012138 FP = 0x20000DD8
    2 ti_sysbios_knl_Task_restore__E(unsigned int) at Task.c:320,PC = 0x0001A8FA FP = 0x20000DF8
    3 ti_sysbios_knl_Semaphore_pend__E(struct ti_sysbios_knl_Semaphore_Object *, unsigned int) at Semaphore.c:191,PC = 0x0000535C FP = 0x20000E00
    4 SPITivaDMA_transfer(struct SPI_Config *, struct SPI_Transaction *) at SPITivaDMA.c:544,PC = 0x0001614C FP = 0x20000E60
    5 SPI_transfer(struct SPI_Config *, struct SPI_Transaction *) at SPI.c:122,PC = 0x0001C990 FP = 0x20000E78
    6 WriteCommand(unsigned char) at st7565.c:95,PC = 0x00017810 FP = 0x20000E80
    7 ST7565_Flush(void *) at st7565.c:447,PC = 0x00017D3E FP = 0x20000E88
    8 LCD_Task(unsigned int, unsigned int) at lcdTask.c:1747,PC = 0x00008A06 FP = 0x20000E98
  • Barry,

    I am unable to reproduce the issue with my app. I increased the number of iterations to 50000.  Can you provide me a small application that I can use to reproduce this issue? It would also be helpful if I have to file a bug report.

    Thanks,

    Vikram

  • Barry,

    I referred this issue to the TI-RTOS drivers team.  We were able to reproduce the issue and fix it. The new fix will be available in the TI-RTOS 2.14.00.10 (release scheduled for the end of the week). Alternatively, you can replace the SPITivaDMA.c in <tirtos_2_12_01_33>/packages/ti/drivers/spi with the attached file and re-build the TI-RTOS drivers.

    Hope this helps.

    Vikram8765.SPITivaDMA.c

  • Thanks, that most definitely helps.

    I have built the drivers and tested.

    Now seems to work correctly, thanks.

    Will keep an eye on it but so far so good :), normally would have hung within a few seconds of starting, now running for 5 mins without any lockup