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/TM4C1294KCPDT: HWI argument not given when statically created

Part Number: TM4C1294KCPDT
Other Parts Discussed in Thread: EK-TM4C1294XL

Tool/software: TI-RTOS

I do not receive the correct number when setting up a HWI through the .cfg file. The value arg comes in with random values. The HWI is set up with:

/* ================ Application Specific Instances ================ */
var halHwi0Params = new halHwi.Params();
halHwi0Params.instance.name = "ResetIP";
halHwi0Params.arg = 6;
halHwi0Params.priority = 5;
Program.global.ResetIP = halHwi.create(68, "&IPButtonISR", halHwi0Params);

This was generated for me automatically by the XGCONF GUI. and it looks correct according to the user guide. My HWI code is:

//toggle the debug LED for now
void IPButtonISR(UArg arg){

    uint32_t ui32Status = GPIOIntStatus(GPIO_PORTK_BASE, true);
    GPIOIntClear(GPIO_PORTK_BASE, ui32Status);

    uint32_t debugLEDState = GPIOPinRead(GPIO_PORTP_BASE, GPIO_PIN_4);
    GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_4, ~debugLEDState);
}

I noticed this error because I am confused on the form of HWI. I have seen example code taking the form void HWI_function(void), but I do not understand what happens when you pass arguments to a function that doesn't accept arguments. GCC won't let me do this.

A HWI successfully gets the correct arg value every time when created dynamically:

    //this is the code at the end of main()
    InitTimer();

    Hwi_Handle hwi0;
    Hwi_Params hwiParams;
    Error_Block eb;
    Error_init(&eb);
    Hwi_Params_init(&hwiParams);
    hwiParams.arg = 5;
    hwiParams.priority = 7;
    hwiParams.instance->name = "example HWI";
    hwi0 = Hwi_create(39, myTimerISR, &hwiParams, &eb);
    if (hwi0 == NULL) {
        while(1);
    }


    /* Start BIOS */
    BIOS_start();

    return (0);
}

void myTimerISR(UArg arg){
    dummy = 0;
    dummy++;
}

The ROV agrees with the .cfg file as to what arg should be, but the same screenshot shows that the value given is not what I expect: 

  • Actually, the dynamic task doesn't get the correct value consistently either. I was never clearing the interrupt so it was constantly re-entering. Nothing had the opportunity to change arg. Random values come in for arg when the dynamic HWI is changed to

    void myTimerISR(UArg arg){
    
        uint32_t ui32Status = TimerIntStatus(TIMER2_BASE, true);
        TimerIntClear(TIMER2_BASE, ui32Status);
    
        dummy = 0;
        dummy++;
    }

  • Hi Peter,

    Can you use the arg in the function and see if that changes things. Maybe just have a volatile global variable that gets assigned the value of arg in the Hwi function.

    volatile UArg myGlobalArg;

    void IPButtonISR(UArg arg)

    {

       myGlobalArg = arg;

       ...

    Depending on your optimization settings, sometimes the compiler does tricks that CCS Variable windows does not understand. The arg value in ROV is being pulled out of the Hwi_Object. 

    Might be good to do a quick ROV->BIOS->Scan for Errors also to run out any funny business like blown stacks also.

    Why aren't you seeing this behavior with the runtime created Hwi...not sure. Maybe different optimization levels.

    Todd

  • Commenting out the line that sets the priority makes the problem "go away"

    //hwiParams.priority = 7;

    Without this line, the priority is set to -1.

    Similarly, with the static creation, setting the priority to -1 in XGCONF results in the correct arg every time.

    /* ================ Application Specific Instances ================ */
    var halHwi0Params = new halHwi.Params();
    halHwi0Params.instance.name = "ResetIP";
    halHwi0Params.arg = 6;
    halHwi0Params.priority = -1;
    Program.global.ResetIP = halHwi.create(68, "&IPButtonISR", halHwi0Params);

    What are the rules regarding HWI priorities? Do they need to be negative? My understanding is the higher task priorities are more important, but the lower HWI priorities are more important, but this is a faint memory that I can't find in writing at the moment.

    The XGCONF validation doesn't seem to catch an error in the interrupt priority field. Setting an absurdly large number become an absurdly large negative number.

  • Peter,

    Can you attach an export project? Something seems fishy here. Right click on the project->Export->General->Archive File->Next and then give it a name and Finish.

    Todd
  • Todd,

    I followed your debug steps. This is a good idea to verify the expressions window, and everything checks out. The file is attached. The project has a relative link to my driberlib.lib.

    I recreated the error on the EK-TM4C1294XL dev kit from the empty (minimal) project template because I do not access to the exact code from above from home. Press the usr sw1 button to trigger the hwi. Change the priority to -1 to get 0xBEEF.

     hwi_arg_error.zip

  • Hi Peter,

    Thanks for the example. The issue is that the Hwi you are creating is a zero-latency interrupt (kernel does not manage it so it add zero-latency). This is due to the hwiParams.priority = 2. Two is less than Hwi.disablePriority (which is 32 for TM4C). So the kernel leaves the ISR alone. So when it fires, the CPU directly calls your function as opposed to going through the kernel's stub. The kernel's stub does the following high-level things
    - Saves some registers
    - Grabs arg and calls your function
    - Restore some registers and ends

    So arg is not being set for your ISR, so whatever is on the stack will be the value for it.

    Here's some more details on zero-latency interrupts: processors.wiki.ti.com/.../BIOS_for_Stellaris_Devices

    Sorry I did not catch that earlier. Usually people use 0 for the priority to make it a zero-latency interrupt.

    Todd

  • Both static and dynamic HWIs function as expected after adjusting the priority threshold. Truthfully, the argument did not matter much to my application, but post() APIs and context saving are important. Diligence pays dividends.

    The examples form the resource explorer are a mixed bag of priority thresholds. Looking at three semi-randomly, tcp echo and uart echo have the priority threshold set to 0, but the hello example is set to 32. The empty minimal RTOS project template from the CCS project creation wizard sets the threshold to 32. The empty minimal template is the basis of the project I send you.

  • Hi Peter,

    I'm not sure which priorities you are referencing in empty, hello, TCP Echo and UART Echo. Can you give me so more details to make sure we are both on the same page?

    Todd
  • Hi Todd,

    I misspoke above. All example projects I download from the resource explorer have the priority threshold set to 32. This field shows NULL before the actual value is loaded. The value in this field becomes Hwi.disablePriority when looking at the .cfg file as raw text. This field is what I changed to get successful HWI arguments with various priorities.

    However! Hwi.disablePriority  does not show up in the raw text at all until is it changed from its default value. If you change it from 32 to something else, and then back to 32, it remains.

    Here is a screenshot for clarification:



  • Peter,

    Thanks for the clarification. It should show 32 (which is the default) in both the red circle in your pic and in the Advanced tab in XGCONF also. In regards to the .cfg when viewed as a text file....we have lots (and some could argue too many) configuration settings. The vast majority have default values, so if it not explicitly set in the .cfg file, it assumes the default. What the graphical view is showing is those explicitly set values and the defaults values for ones that are not explicitly set.

    So when you change a default value and change it back in the graphical tool, it is stored in the .cfg explicitly.

    In general we try to include the common configuration parameters in the .cfg explicitly even if the value we are using is the default. This is to help the people that edit the .cfg as a text file instead of the graphical tool. I personally only use the graphical tool when I forgot the exact name or syntax of a configuration parameter.

    Todd