Hi all,
I'm new to the SysBIOS world, and I have a problem related to HWI preemption over SWI. Things seem to be working pretty fine, except for this case where I have the following situation :
An Interrupt occurs, resulting in an HWI being called (Timer_Handler). This HWI posts a SWI (mySwi). This SWI is called after completion of the first HWI.Then during execution of the SWI, another Interrupt occurs (I2C_Handler). My problem is that this new Interrupt doesn't preempt the SWI, though I need it to.
I am running SysBIOS on a platform similar to Stellaris, with a Cortex-M4F.
Here is the code for setting up the corresponding HWI and SWI dynamically :Swi_Handle mySwi;
Int main(){ Hwi_Params hwiParams; Swi_Params swiParams; Hwi_Handle myHwi[64];
Swi_Params_init(&swiParams); swiParams.priority = 0x40;
// create new SWI mySwi = Swi_create(sensorSwi, &swiParams, NULL); if(mySwi == NULL) { send_msg(1,0xBAD00); }
Hwi_Params_init(&hwiParams); hwiParams.arg = 0; hwiParams.enableInt = FALSE; hwiParams.priority = 0x20; // > 0x0, reserved for zero-latency interrupt myHwi[33] = Hwi_create(49, I2C_Handler, &hwiParams, NULL); if(myHwi[39] == NULL){ send_msg(1,0xBAD00+49); }
myHwi[39] = Hwi_create(55, Timer_Handler, &hwiParams, NULL); if(myHwi[39] == NULL){ send_msg(1,0xBAD00+39); }
Hwi_enableInterrupt(49); Hwi_enableInterrupt(55);
BIOS_start();
return 0;}
Then the Timer_Handler HWI :
Void Timer_Handler(UArg arg){ u32 swiKey;
// we disable SWI so it can be posted upon completion of the HWI swiKey = Swi_disable();
// [...] Swi_post(mySwi); // [...]
clr_pending_irq(); // we restore the SWI and the remaining SWIs can be posted Swi_restore(swiKey);}
Does somebody have an idea why the SWI never gets interrupted by the Hardware Interrupt ?Thanks in advance,
Michael
Which version of SYS/BIOS are you using?
Can you try setting the interrupt priority to 0x40 and see if this changes the behavior?
Are you certain the I2C interrupt is going off during the execution of the Swi?
Within your Swi code please add this snippet and report the value of hwiKey:
UInt hwiKey;
hwiKey = Hwi_disable();
Hwi_restore(hwiKey);
Alan
Michael,
I don't see much problem in the logic..
Is this ok..?
Michael FillingermyHwi[33] = Hwi_create(49, I2C_Handler, &hwiParams, NULL); if(myHwi[39] == NULL){ send_msg(1,0xBAD00+49); }
You seem to be assigning for myHwi[33] and checking/handling the error for myHwi[39]. Does this mess up your system (that code is not here).
Hope this helps..
With best regards,
Madhvapathi Sriram
Thanks and regards,
Something else a little troublesome about your code is that the array of Hwi Handles (myHwi[]) is defined as a local variable in main().
Hopefully you're not referencing this array somewhere else in your code.
Hi all
thank you for all your answers. You're right about the myHwi[33] referencing. This was corrected since and of course didn't change the problem.
I've had environment problems since I posted this thread, so I haven't been able to get the keyHwi yet, but hopefully things will run correctly again today.
Also, I'm not referencing myHwi anywhere, but for the sake of it, I'll have it global, since there's no point in having it declared locally in main, as you rightfully suggested !
I'm certain the I2C IRQ is firing, because I'm running everything on RTL simulation, and I can see the isr bus of the CM4, and more specifically the I2C IRQ toggling. Then in simulation it stays asserted forever, and by looking at the instruction bus of the CM4, I can see it's stuck in the SWI function, waiting for a flag to toggle.
I'll post again today, as soon as everything's back up again.
Thanks again
Hi again,
ok so I could re-run the whole thing.
I've added the code for keyHwi, and got keyHwi = 0x0
Also, I made a mistake in my first message : when I put hwiParams.priority = 0x20; the I2C interrupt never gets serviced, independantly of being in a SWI or not ! In a smaller testcase that I have which only exercises I2C, it wouldn't work with priority = 0x20;
This smaller test does work with hwiParams.priority = 0x0; but then the problem stated in this thread occurs, whatever priority I put for my SWI.
In the end, it appears I have 2 issues : why wouldn't the interrupt be serviced with a priority of 0x20, and why my SWI doesn't get interrupted ?
Best regards
Intriguing indeed..
Not being carried away by your latest findings (which indeed can be some more issues), coming back to the original post and your finding with the hwiKey.
Looks like between, the first h/w interrupt handler and the next somewhere the HWIs are getting disabled.
1) So, need to see what's so special code in the Timer_Handler() that can potentially disable interrupts. For example, what does clr_pending_irq() do?
2) Is there anything in the SWI that has something potentially damaging?
Hi,
very good point. I kind of forgot about that custom function I had to write.
It doesn't do much, but still, it could break something I guess :
1. On our platform, there is an Interrupt Distributor that forwards Interrupts to other IPs, the CM4 in our case. So we first need to clear the IRQ at Interrupt Distributor level.
2. The only other thing it's doing, is clearing the interrupt at NVIC level. Now I guess that's where there could be an issue : somehow, it wouldn't work at the beginning of the project, so I added the clear manually in my code.
I just I removed the NVIC clearing, so now all that remains is the INTDIST clearing, and though the good thing is that all that was working before is still working, it didn't solve our issue.
In the SWI, I don't see what could be wrong : the first thing it does -- and that's where it gets stuck -- is performing an I2C read, and thus writing to a bunch of I2C registers, and then waiting for a flag to toggle, telling that data has been received. This flag is supposed to toggle upon I2C interrupt reception.
I guess I could share the whole code, but I cannot do it in an external forum unfortunately.
Regards
Note : I'm running on SysBIOS 6.33.03.33 and XDC Tools 3.23.01.43
The activity on this thread has died down and I'm wondering if you still have an outstanding issue. Can you summarize where you are on this and what further help you are seeking?
Hi David,
thanks for following up on this.
Unfortunately, I still have the issue, and I had to move on to something else in the meanwhile (I can avoid the problem by using polling for now).
To summarize my problem, I've got the following sequence occuring :
1. An interrupt occurs, lauching an ISR
2. This ISR posts a SWI and exits
3. The SWI is waiting for another interrupt to occur (which should toggle a flag)
4. The other interrupt does occur (visible in Simulation), but the SWI is not interrupted, and is stuck in an endless loop
Is the flag being polled in the Swi in step #3 declared as a volatile? Is it possible the ISR is indeed running but the flag check was optimized away?
Scott
Hi Scott
yes all my flags are declared globally as volatile (in fact, being slightly paranoid on this one, I've declared all my globals as volatile ...)
I'm sure the ISR never launches, as I'm sniffing the instruction bus of the CM4 and once it gets to the instructions within the SWI, it never ever leaves. In particular, it doesn't fetch the exception vector related to the IRQ coming in...
I believe the problem is due to setting the interrupt priority to zero.
This value informs Hwi_create() that you are defining a zero-latency-interrupt. This topic is discussed here (see "Configuring a Zero Latency Interrupt"):
http://processors.wiki.ti.com/index.php/SYS/BIOS_for_Stellaris_Devices#SYS.2FBIOS_M3_Hardware_Interrupt_.28Hwi.29_Handling
Consequently, the interrupt is NOT routed through the dispatcher.
This results in the Swi function running within the interrupt thread itself, at the same thread (NVIC) priority as the interrupt.
Consequently, the interrupt can NOT interrupt itself.
Zero Latency Interrupts are NOT ALLOWED TO POST Swis or Semaphores! Behavior such as you're seeing (or WORSE) will result.
I think you have to find out why the interrupt doesn't go off when you set the priority to 0x20.
One thing to keep in mind is that all dispatched interrupts (ie non-Zero Latency interrupts) are disabled in main().
They get enabled by SYS/BIOS within the BIOS_start() call.
ok I'm back on this issue (I cannot work 100% on it unfortunately).
The good news is, after a lot of trials and errors, I finally found the solution to my problem, though I'm not entirely sure if it's normal that it works ;)
The solution was not only to have the HWI that posts the SWI with an interrupt priority of 0x20 (which I understand), but also the HWI that interrupts the SWI, even though that one doesn't contain any Swi_post or anything else.
Do you feel that this is the expected behavior ?
I'm glad its working. But no, this doesn't sound right to me.
The Hwi that interrupts the Swi that doesn't contain any Swi_post() or anything else should be able to be configured as a zero latency interrupt (ie priority = 0).
Just to get current, please list the interrupts and their respective priorities defined in your application.
here is the interrupt list and their priorities :
- 1 SWI which has priority 1 (though I don't think it really matters in the end)
- 64 HWI, though "only" 30 are created and enabled. In the working code, all of them have priority 0x20. When it wasn't working, only the Timer HWI which was posting the SWI had a priority of 0x20, all others had 0x0. In the use case I am running, just 3 HWI are being used (the Timer HWI, the I2C HWI and another HWI which is completely unrelated and wasn't occuring at the same time).
Do you think there is something I can do to help understand this behavior ?
By the way, something is still a bit off, because I have another issue, which is basically, that I cannot create all 64 HWI that would be needed by my application. But that's probably another subject that I will try to solve, or else post another thread in these forums.