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.

RTOS/TM4C1290NCZAD: Configuring zero latency interrupt in uartecho_DK_TM4C129X_TI_TivaTM4C129XNCZAD example project causes a crash

Part Number: TM4C1290NCZAD
Other Parts Discussed in Thread: SYSBIOS, SEGGER

Tool/software: TI-RTOS

Hi,

I wanted to test zero latency interrupts by modifying the uartecho_DK_TM4C129X_TI_TivaTM4C129XNCZAD example project but I it keeps crashing as soon as I enable the zero latency functionality for the UART0 interrupt.

I modified the two following things to enable zero latency for the UART0 interrupt:

in DK_TM4C129X.c I set UART0 int priority to 2 << 5

const UARTTiva_HWAttrs uartTivaHWAttrs[DK_TM4C129X_UARTCOUNT] = {
    {
        .baseAddr = UART0_BASE,
        .intNum = INT_UART0,
        .intPriority = 2 << 5,
        .flowControl = UART_FLOWCONTROL_NONE,
        .ringBufPtr  = uartTivaRingBuffer[0],
        .ringBufSize = sizeof(uartTivaRingBuffer[0])
    }
};

In uartecho.cfg I added:

m3Hwi.disablePriority = 96;

As soon as I applied those changes the program started crashing with the following output in CCS console:

This example does not attempt to minimize code or data footprint
Starting the UART Echo example
System provider is set to SysMin. Halt the target to view any SysMin contents in ROV.
FSR = 0x0000
HFSR = 0x40000000
DFSR = 0x0000000b
MMAR = 0x140f0530
BFAR = 0x140f0530
AFSR = 0x00000000
Terminating execution...

If I disable zero latency for UART0 int by changing its priority to 3 << 5 OR by changing m3Hwi.disablePriority to 64 everything works fine again.

What am I missing? Is there anything else that needs to be enabled/configured in order to use zero latency interrupts?

Below I attached the example project with my modifications.

uartecho.zip

Thank you,

Peter A.

  • Feel your (unanswered post) pain.

    Your entry of "Zero Latency" w/in (top of forum's) Search Box - will yield a barrage of near/similar issues - may prove worthwhile...
  • Zero latency interrupts cannot make a scheduler call (e.g. Semaphore_post). The UART driver calls Semaphore_post.

    Todd
  • Todd - thank you - appreciated.

    May we ask the name & location of the supporting document - which enabled your response?       To my best knowledge - (at least for the 4C123 series) - no such guidance appears.     (it is expected that such a document originated from ARM - yet they have many - and you've found/know the one "in play.")

    In addition - if it is likely that other limitations or special handlings are required - would it not make sense for those to be "listed" - and well publicized - so that (many, other) posters do not fall (one after another) to such trap?

    Thanks again...

  • Look in the SYS/BIOS (TI-RTOS Kernel) API references (also called cdoc). Look in the <TI-RTOS Install Dir>/docs/Documentation_Overview_tivac.html and search for Kernel Runtime APIs. Look at the ti.sysbios.family.arm.m3 page and search for zero. Here's the warning
    WARNING
    Zero latency interrupts are NOT HANDLED by the SYS/BIOS interrupt dispatcher! Instead, they are vectored to directly. As such, and because they are NOT DISABLED BY Hwi_disable(), these interrupt handlers are SEVERELY RESTRICTED in terms of the SYS/BIOS APIs they can invoke and THREAD SAFETY MUST BE CAREFULLY CONSIDERED! See the descriptions of Hwi_disable() and and Hwi.disablePriority for more details.

    Or a more direct route: processors.wiki.ti.com/.../BIOS_for_Stellaris_Devices and you'll see "Thus, a zero latency interrupt handler should never call any BIOS APIs ."
  • Thank you Todd - again appreciated.

    Yet - in firm/my case - we employ ARM MCUs from several - and do NOT use any "vendor locked" aids. (btw - this a "client dictated" requirement - under the theory that one firm - cannot at all times - supply the optimal device!)

    We employ multi-seat, paid IAR and Segger Debug/Program tools - and may employ FreeRTOS - but never any "vendor-locked" artifice.

    From a reasonably recent (i.e. yesterday) reading gleaned @ ARM's site - I believe that the Cortex M3/M4 family devices - even from different vendors - behave w/great commonality. (and that by ARM's intent)

    I assume then that this limitation (may) be specific to your firm's RTOS/sysbios. That may be best confirmed by (another) visit to the ARM site - and search... Again, thank you...
  • SYS/BIOS, by design, manages the vector table. Like with most things, there are pros and cons with this approach. The major pro is that ISR management from the users perspective is the same across the entire family of TI processors (CortexA, CortexM, MSP, C5x, C6x, C2000, etc.) when you use SYS/BIOS. We understand that for some applications, they do not want to incur any overhead on specific interrupts. It's for those use cases that we recommend using (what SYS/BIOS calls) zero-latency interrupts (with the noted restrictions).
  • Thank you - and surely that unification makes sense - for those likely to accept/bow to, "single vendor" (always & only.)

    Appreciate your comments & insights.

    You might consider that users such as my firm - required to select/support ARM MCUs from multiple sources (i.e the best source under that product/project's "selection criteria matrix") - will (necessarily) AVOID any such "vendor-locked" methods - as they prove "non-transferable."      (and will prevent Re-use, and further "build" upon such "broad" (multi-source) MCU knowledge base) 

  • ToddMullanix said:
    It's for those use cases that we recommend using (what SYS/BIOS calls) zero-latency interrupts (with the noted restrictions).

    A side note for other's reference. Other RTK/RTOS implementations will call these non-managed interrupts. The TI nomenclature here is somewhat odd and even a touch misleading.

    Many RTKs implement a multi-leveled approach to interrupt handling involving

    1. Unmanaged interrupts
      1. Normal interrupts. Do not save RTK context and so cannot make RTK calls or only a very restricted set of one or two (Say setting a semaphore). These have low overhead but since they cannot communicate with the main application very well are restricted in their use.
    2. Managed interrupts
      1. This is the general purpose interrupt structure. They have sufficient context saved to allow a use of a subset of RTK calls. Typically that subset would include semaphores, FIFOs, queues etc.. They rely on triggering other threads to do the majority of the work within the RTKs priority scheme.
    3. High/interrupt/Fast priority threads
      1. Special high priority threads that can be triggered by a managed interrupt. They have access to the full RTK set of calls.
    4. Normal real time threads

    Any particular RTK/RTOS  may have some subset of the above variations.

    Robert

  • Hi Robert,

    I agree that zero-latency is a little misleading. I'll open an enhancement request to make it clearer in the docs.

    Thanks for the feedback!

    Todd
  • Hi,

    Thank you very much for your responses.

    I was able to configure GPIO P1 pin interrupt as zero latency. However, I could not get it to work when I was configuring the P1 pin using TI-RTOS's GPIO_init() function and related structures(please see the code below). Only when I configured the P1 pin using direct Tivaware calls (example below) I was able to use it as zero latency int.

    This does not work:

    GPIO_PinConfig gpioPinConfigs[] = {
        /* Input pins */
        /* DK_TM4C129X_BUTTON_SELECT */
       GPIOTiva_PP_1 | GPIO_CFG_IN_PU,
        /* DK_TM4C129X_BUTTON_UP */
        GPIOTiva_PN_3 | GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_RISING,
        /* DK_TM4C129X_BUTTON_DOWN */
        GPIOTiva_PE_5 | GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_RISING,
    
    
    
        /* Output pins */
        /* DK_TM4C129X_LED_G */
        GPIOTiva_PQ_7 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        /* DK_TM4C129X_LED_B */
        GPIOTiva_PQ_4 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        /* DK_TM4C129X_LED_R */
        GPIOTiva_PN_5 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW
    };
    
    GPIO_CallbackFxn gpioCallbackFunctions[] = {
        NULL,  /* DK_TM4C129X_BUTTON_SELECT */
        NULL,  /* DK_TM4C129X_BUTTON_UP */
        NULL   /* DK_TM4C129X_BUTTON_DOWN */
    };
    
    
    const GPIOTiva_Config GPIOTiva_config = {
        .pinConfigs = (GPIO_PinConfig *)gpioPinConfigs,
        .callbacks = (GPIO_CallbackFxn *)gpioCallbackFunctions,
        .numberOfPinConfigs = sizeof(gpioPinConfigs)/sizeof(GPIO_PinConfig),
        .numberOfCallbacks = sizeof(gpioCallbackFunctions)/sizeof(GPIO_CallbackFxn),
        .intPriority = 7 << 5
    };
    
    
    ......
    
    	/* Initialize peripheral and pins */
        GPIO_init();
    	
    	// Configure zero latency int
    	Error_Block eb;
        Error_init(&eb);
    
        Hwi_Params params;
        Hwi_Params_init(&params);
        params.enableInt = true;
        params.priority = 1 << 5;
    
        Hwi_create(INT_GPIOP1, SelectButtonCb, &params, &eb);

    And this works:

    	
    	GPIO_PinConfig gpioPinConfigs[] = {
        /* Input pins */
        /* DK_TM4C129X_BUTTON_SELECT */
       //GPIOTiva_PP_1 | GPIO_CFG_IN_PU,
        /* DK_TM4C129X_BUTTON_UP */
        GPIOTiva_PN_3 | GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_RISING,
        /* DK_TM4C129X_BUTTON_DOWN */
        GPIOTiva_PE_5 | GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_RISING,
    
    
    
        /* Output pins */
        /* DK_TM4C129X_LED_G */
        GPIOTiva_PQ_7 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        /* DK_TM4C129X_LED_B */
        GPIOTiva_PQ_4 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
        /* DK_TM4C129X_LED_R */
        GPIOTiva_PN_5 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW
    };
    
    
    GPIO_CallbackFxn gpioCallbackFunctions[] = {
        //NULL,  /* DK_TM4C129X_BUTTON_SELECT */
        NULL,  /* DK_TM4C129X_BUTTON_UP */
        NULL   /* DK_TM4C129X_BUTTON_DOWN */
    };
    
    /* The device-specific GPIO_config structure */
    const GPIOTiva_Config GPIOTiva_config = {
        .pinConfigs = (GPIO_PinConfig *)gpioPinConfigs,
        .callbacks = (GPIO_CallbackFxn *)gpioCallbackFunctions,
        .numberOfPinConfigs = sizeof(gpioPinConfigs)/sizeof(GPIO_PinConfig),
        .numberOfCallbacks = sizeof(gpioCallbackFunctions)/sizeof(GPIO_CallbackFxn),
        .intPriority = 7 << 5
    };
    
    .......
    
    
        /* Initialize peripheral and pins */
        GPIO_init();
    
    
        // Select button configuration
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
        SysCtlDelay(2);
        GPIOPinTypeGPIOInput(GPIO_PORTP_BASE, GPIO_PIN_1);
        GPIOIntTypeSet(GPIO_PORTP_BASE, GPIO_PIN_1, GPIO_RISING_EDGE);
        GPIOIntEnable(GPIO_PORTP_BASE, GPIO_INT_PIN_1);
    
    
        Error_Block eb;
        Error_init(&eb);
    
        Hwi_Params params;
        Hwi_Params_init(&params);
        params.enableInt = true;
        params.priority = 1 << 5;
    
        Hwi_create(INT_GPIOP1, SelectButtonCb, &params, &eb);

    Is that by design? Or am I missing something?

    I also noticed that when I call Hwi_disable() and Hwi_restore inside of zero latency interrupt sometimes it does not work. Normal interrupts either does not get disabled or restored.

    Is there any restriction on using these functions from zero latency ints?

    Please find my project attached below for reference.

    uartecho_zerolatency.zip

  • You cannot call Hwi_disable/restore from a zero latency interrupt.

    Todd
  • Hi Todd,
    Thank you for the response.

    What about the first question in my previous post?

    Can I use GPIO_init() and related structures to configure an input pin and then use Hwi_create() with adequate interrupt priority to configure zero latency interrupt for that PIN?
    Or do I have to use direct Tivaware calls to configure a PIN that is going to be used as a source of zero latency interrupt?