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/TMS320F28075: HWI and timer interrupt routine preemption

Part Number: TMS320F28075
Other Parts Discussed in Thread: SYSBIOS

Tool/software: TI-RTOS

Hi,

I'm developing an application with SYS/BIOS 6.46.1.38.

I'm using 3 HW interrupt routines (HWI, configured through modules ti.sysbios.family.c28.Hwi and ti.sysbios.interfaces.IHwi):

HWI_routine_1 (interrupt number 82)

HWI_routine_2 (interrupt number 103)

HWI_routine_3 (interrupt number 198)

and an interrupt routine triggered by TIMER0 (configured through module ti.sysbios.family.c28.Timer):

TIMER_routine

I've configured all HWI Masking options as MaskingOption_ALL, because I wanted that all HWI routines didn't preempt each other (i. e. an HW interrupt is executed completely before another Hw interrupt routine is started).

Moreover I've read that all timer interrupt routines are executed in HWI context, therefore I think that TIMER_routine doesn't preempt HWI routines and HWI routines don't preempt TIMER_routine.
Is this correct?


Now I want that TIMER_routine (only!) can preempt all HWI routines.

I know that I should set

Masking options = MaskingOption_BITMASK

and then I should set two masks:

Nested interrupt disable mask

Nested interrupt restore mask

but I haven't understood what is the meaning of these two masks and how I should set to get what I want.


Let's consider for instance HWI_routine_3, linked to interrupt 198 (INT9.15, USBA).

I want that HWI_routine_3 can be preempted by TIMER_routine but cannot be preempted by HWI_routine_1 and HWI_routine_2.

What numbers should I write in "Nested interrupt disable mask" and "Nested interrupt restore mask"?


Thanks in advance.

Regards

Demis

  • Demis,

    Now I want that TIMER_routine (only!) can preempt all HWI routines.
    I know that I should set
    Masking options = MaskingOption_BITMASK
    and then I should set two masks:
    Nested interrupt disable mask
    Nested interrupt restore mask
    but I haven't understood what is the meaning of these two masks and how I should set to get what I want.

    --The interrupt disable mask, means while executing that particular Hwi, which Hwis to disable.
    --The interrupt restore mask, means when returning from the Hwi, which Hwis to to enable

    You need to determine which Hwi # corresponds the the Timer interrupt. So when you execute your other Hwis, you want to disable everything except the Timer Hwi.

    In your scenario, Interrupt 198 exists on INT9 which is bit 9 in the bitmask. Routine 1 is bit 7, Routine 2 is bit 9 also.
    The default Timer0 interrupt is on bit 1.
    To disable everything except Timer0 interrupt, set disableMask to 0xFFFE.
    To leave everything enabled and only disable bit 7 and bit 9 is: 0x0140.

    Judah
  • Judah,
    thank you for the support.

    I've used this configuration for HWI 198:
    Masking options = MaskingOption_BITMASK
    disableMask = 0xFFFE; // only TIMER0 HWI enabled
    restoreMask = 0xFFFF; // all HWI enabled

    and I've seen that HWI_routine_3 (interrupt 198) is preempted by TIMER_routine. That's OK.

    However I've noted another fact I didn't expect: TIMER_routine is preempted by HWI_routine_3!

    So I've come back to previous setting and I've configure HWI 198 with:
    Masking options = MaskingOption_ALL

    However TIMER_routine is preempted by HWI_routine_3 anyway!

    I've read that in SYS/BIOS TIMER interrupt service routine is executed in HWI context, so I expected that TIMER_routine cannot be preempted by HWI routine but on the contrary TIMER_routine IS PREEMPTED by HWI routine.

    I want that HWI, SWI and task cannot preempt TIMER_routine.

    How should I configure TIMER resource inside SYS/BIOS to achieve this goal?

    Thanks.

    Regards,

    Demis
  • Demis,

    I forgot to mention that in my last post that the default Timer is created with a Hwi which has only SELF masked out.
    So this is why you see other Hwi can preempt the Timer Hwi.

    I need to further look to see if you can pass a Hwi_Params into the Timer_Create for the default Timer. If you cannot then
    What you will need to do is create your own Timer and configure the clock to run base on your Timer. This way you can control
    what Hwi's can and cannot preempty your Timer Hwi.

    Judah
  • To create your own Timer with your own handler that mask out everything:

    // Tell the Clock module that YOU are providing the periodic interrupt
    Clock.tickSource = Clock.TickSource_USER;

    // this example uses the c28 Timer module
    var Timer = xdc.useModule('ti.sysbios.family.c28.Timer');

    // create a dmtimer config parameter object
    var timerParams = new Timer.Params();

    // make sure you set the period to 1000 us (1ms)
    timerParams.period = 1000;

    timerParams.hwiParams = new Hwi.Params();
    timerParams.hwiParams.disableMask = 0xFFFF;
    timerParams.hwiParams.restoreMask = 0xFFFF;

    // Provide your own timer interrupt handler function.
    Timer.create(0, '&myTimerTick', timerParams);

    In your 'C' code, add your timer interrupt handler and have it
    call Clock_tick(), which will perform all of the Clock module
    tick duties:
  • Judah,
    thank you for your hit but it seems not to work.

    Let's go in order.

    In my application I use 2 timers and 1 clock with the following settings:

    // TIMER_FREE_RUNNING
    // no interrupt service routine
    var timer0Params = new Timer.Params();
    timer0Params.instance.name = "TIMER_FREE_RUNNING";
    timer0Params.prescale = 119;
    timer0Params.period = 4294967295;
    timer0Params.periodType = xdc.module("ti.sysbios.interfaces.ITimer").PeriodType_COUNTS;
    Program.global.TIMER_FREE_RUNNING = Timer.create(-1, null, timer0Params);

    // TIMER_DSP_ARM
    // interrupt service routine: ISR_WFrame, called every 100 us (100 MICROseconds)
    var timer1Params = new Timer.Params();
    timer1Params.instance.name = "TIMER_DSP_ARM";
    timer1Params.period = 100; // 100 us (MICROseconds)
    Program.global.TIMER_DSP_ARM = Timer.create(0, "&ISR_WFrame", timer1Params); // linked to TIMER0

    // CLOCK
    // interrupt service routine: ClockSpiIO, called in a SWI context every 1 ms (1 MILLIsecond)
    Clock.tickPeriod = 1000; // 1 ms (MILLIsecond)
    Clock.swiPriority = 1;
    var clock0Params = new Clock.Params();
    clock0Params.instance.name = "CLOCK_SPI_IO";
    clock0Params.period = 1;
    clock0Params.startFlag = true;
    Program.global.CLOCK_SPI_IO = Clock.create("&ClockSpiIO", 1, clock0Params);


    Following PARTIALLY your hints I've slightly changed only TIMER_DSP_ARM settings adding three lines:

    // TIMER_DSP_ARM
    // interrupt service routine: ISR_WFrame
    var timer1Params = new Timer.Params();
    timer1Params.instance.name = "TIMER_DSP_ARM";
    timer1Params.period = 100;

    timerParams.hwiParams = new Hwi.Params(); // [added]
    timerParams.hwiParams.disableMask = 0xFFFF; // [added]
    timerParams.hwiParams.restoreMask = 0xFFFF; // [added]

    Program.global.TIMER_DSP_ARM = Timer.create(0, "&ISR_WFrame", timer1Params); // linked to TIMER0

    However the behaviour is the same: ISR_WFrame (timer interrupt routine) is preempted by HWI_routine_3. That's OK, I know I haven't followed your hints completely.


    Then I've configured Clock and timer following your indications strictly (I hope...):

    // TIMER_DSP_ARM
    // interrupt service routine: ISR_WFrame
    var timer1Params = new Timer.Params();
    timer1Params.instance.name = "TIMER_DSP_ARM";
    timer1Params.period = 100; // 100 us (MICROseconds)
    timerParams.hwiParams = new Hwi.Params(); // [added]
    timerParams.hwiParams.disableMask = 0xFFFF; // [added]
    timerParams.hwiParams.restoreMask = 0xFFFF; // [added]
    Program.global.TIMER_DSP_ARM = Timer.create(0, "&ISR_WFrame", timer1Params); // linked to TIMER0

    // CLOCK
    // interrupt service routine: ClockSpiIO (called in a SWI context)
    Clock.tickPeriod = 100; // 100 us (MICROsecond) [changed]
    Clock.tickSource = Clock.TickSource_USER; // [added]
    Clock.swiPriority = 1;
    var clock0Params = new Clock.Params();
    clock0Params.instance.name = "CLOCK_SPI_IO";
    clock0Params.period = 10; // [changed]
    clock0Params.startFlag = true;
    Program.global.CLOCK_SPI_IO = Clock.create("&ClockSpiIO", 1, clock0Params);

    // timer interrupt service routine
    void ISR_WFrame(void)
    {
    Clock_tick(); // [added]

    // Other stuff...
    }

    Unfortunately this doesn't work anyway: ISR_WFrame is still preempted by HWI_routine_3.

    Have I made any mistake in following your indications?

    Do you have any other hints?

    Thank you.

    Demis
  • Judah,
    good news.

    After last test I've restored my original configuration.
    Then I've made only a single change to Timer configuration, adding 2 lines inspired by HWI configuration:

    var timer1Params = new Timer.Params();
    timer1Params.instance.name = "TIMER_DSP_ARM";
    timer1Params.period = 100;
    timer1Params.hwiParams = new Hwi.Params(); // [added]
    timer1Params.hwiParams.maskSetting = xdc.module("ti.sysbios.interfaces.IHwi").MaskingOption_ALL; // [added]
    Program.global.TIMER_DSP_ARM = Timer.create(0, "&ISR_WFrame", timer1Params);

    Doing so I see that ISR_WFrame (i.e. TIMER_routine) is not preempetd by HWI interrupt service routine.

    In other words the solution is to create an explicit HWI for timer data structure and then configure it like it was an ordinary HWI.

    Do you see any drawback in this solution?
    Is there any disadvantage or unexpected side-effect?

    During the test another doubt has arisen.
    Suppose to have an HWI with MaskingOption_ALL selected.
    When its interrupt service routine ends, which HWI are enabled?
    All interrupts?
    Only the same interrupts that were enabled before the execution of the interrupt service routine ?
    Or which ones?

    There is another question strictly connected with it.
    Suppose I have an HWI configured like this:
    Masking options = MaskingOption_BITMASK;
    disableMask = 0xFFFE; // only interrupt 0 can preempt HWI interrupt routine
    restoreMask = 0xFFFF. // all interrupts are enabled after HWI interrupt routine

    When interrupt service routine ends all interrupts are enabled.
    But if I want to restore only those interrupts that were enabled before interrupt service routine was executed, how can I do?
    I cannot set a restoreMask with a static value because I don't know it at compile time (in generale it can change at every call of the HWI interrupt routine).

    So, how can I do?

    Thanks.

    Demis
  • Demis,

    Not sure the single change of setting mask to "MaskingOption_ALL" would make a difference since this simple sets:

    hwi->disableMask = 0xffff;
    hwi->restoreMask = 0xffff;

    But if that works, good!  There is no drawback to that solution, in fact that was going to be my next suggestion.

    Its a restore mask so it "&" the restore mask with the interrupts that were enabled prior to calling the Hwi isr.

    Judah

  • Judah,

    judahvang said:

    Not sure the single change of setting mask to "MaskingOption_ALL" would make a difference since this simple sets:

    hwi->disableMask = 0xffff;
    hwi->restoreMask = 0xffff;

    The simple sets of the mask don't work, I'm sure because I tested them.

    I think those sets work only if the use of bitmask is enabled, i.e. if masking option is set to "MaskingOption_BITMASK". I didn't test that configuration but I'm confident that it works because is similar to HWI.

    judahvang said:

    Its a restore mask so it "&" the restore mask with the interrupts that were enabled prior to calling the Hwi isr.

    OK, that's good.

    Thank you for your support.

    Demis