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.
I Implement the operating system for a customer. One of OS features is to enable the user to configure interrupts with any priority and my OS is responsible for handling these interrupt using VIM controller.
Customer only implement the handler content itself and me as OS developer create the wrapper for this handler.
The design goes like the following (only pseudo code to show the idea):
OS_Wrapper:
B USER_HANDLER
B END_ISR
END_ISR:
clear the interrupt at VIM (clear VIM_STS bit for this source)
And it is expected from the user in his user handler (USER_HANDLER) to clear the interrupt at its source.
So the clearing for interrupt at its source is done first then clearing it at VIM (Interrupt is configured as level interrupt in VIM_INTTYPE)
The problem happens when the exact same interrupt is triggered again during the handling of the first user handler.
Then the sequence will be as follows:
1-User handler is entered and interrupt is cleared at its source.
2-Interrupt comes again and raise the interrupt source again.
3-OS clears VIM flag at END_ISR
4-Now we have interrupt source is 1 and VIM flag is 0. Software stuck forever for this interrupt and never assert VIM flag to 1 again even if the source is kept triggered over and over again.
(The only way to get away from this state is to clear the soucrce explictly and wait for the sourcr to come again)
Expectation:
If interrupt source is 1 then VIM should be 1 again so the interrupt is triggered again (The same interrupt did not get missed if it comes during the handling of the previous handler of the same interrupt)
Hi
Could you please let me know the below details:
Are you using a custom Interrupt Handler and not the IRQ Handler given by the SDK?
Are you able to reproduce this issue in the IRQ handler in the SDK?
clear the interrupt at VIM (clear VIM_STS bit for this source)
Are you clearing the interrupt based on if the interrupt is level trigger or pulse trigger?
level trigger --> clear the interrupt after executing the user interrupt and clearing the peripheral interrupt.
pulse trigger --> clear the interrupt first and then enter the user ISR to clear the peripheral interrupt.
Thanks & Regards
Sri Vidya
Are you using a custom Interrupt Handler and not the IRQ Handler given by the SDK?
I am not using Handler given by the SDK.
Are you able to reproduce this issue in the IRQ handler in the SDK?
No I did not try the handler in SDK as I should do the handler myself
Are you clearing the interrupt based on if the interrupt is level trigger or pulse trigger?
As I mentioned it is a level interrupt and I have followed the datasheet regarding the required sequence
The problem happens when the exact same interrupt is triggered again during the handling of the first user handler.
Are you also using the Hwip_enable and Hwip_disable to allow nesting of the interrupts.
Is it possible to share your code as I can only verify the nesting from the SDK handler and it is working fine.
Now we have interrupt source is 1 and VIM flag is 0. Software stuck forever for this interrupt and never assert VIM flag to 1 again even if the source is kept triggered over and over again.
Could you also specify which interrupt source/peripheral are you using?
Is the same case happening for both level and pulse trigger interrupts?
I think you are already aware of the Assembly handler of the SDK:
In SDK, The interrupt first comes to the Assembly handler and then enters the C handler. For Free Rtos this is present in the file:
C:\ti\mcu_plus_sdk_am243x_08_05_00_24\source\kernel\freertos\portable\TI_ARM_CLANG\ARM_CR5F\portASM.S.
API name is HwiP_irq_handler:
Thanks & regards
Sri Vidya
I cannot share my code but let my explain the situation on SDK code
void __attribute__((section(".text.hwi"))) HwiP_irq_handler_c(void)
{
int32_t status;
uint32_t intNum;
#ifndef HWIP_VIM_VIC_ENABLE
volatile uint32_t gdummy;
/* Read to force prioritization logic to take effect */
gdummy = HwiP_getIRQVecAddr();
#endif
status = HwiP_getIRQ(&intNum);
if(status==SystemP_SUCCESS)
{
uint32_t isPulse = HwiP_isPulse(intNum);
HwiP_FxnCallback isr;
void *args;
if(isPulse)
{
HwiP_clearInt(intNum);
}
isr = gHwiCtrl.isr[intNum];
args = gHwiCtrl.isrArgs[intNum];
#ifdef HWIP_NESTED_INTERRUPTS_IRQ_ENABLE
/* allow nesting of interrupts */
HwiP_enable();
#endif
if(isr!=NULL)
{
isr(args);
}
/* disallow nesting of interrupts */
HwiP_disable();
if(!isPulse)
{
HwiP_clearInt(intNum);
}
HwiP_ackIRQ(intNum);
}
else
{
/* spurious interrupt */
gHwiCtrl.spuriousIRQCount++;
HwiP_ackIRQ(0);
}
}
user handler:
isr()
{
/* Clear interrupt at source */
/* Same interrupt comes again here and interrupt source is raised again */
}
Then the sequence is as the following (level interrupt):
1-Interrupt is cleared at source in user handler isr()
2-Interrupt at source is raised again for the same interrupt
3-HwiP_clearInt() is called and now VIM STS is cleared but Interrupt at source is 1
4-The stuck happen for this interrupt as mentioned in the description.
Are you also using the Hwip_enable and Hwip_disable to allow nesting of the interrupts ?
I use something similar but I do not think this is relevant to this issue.
Could you also specify which interrupt source/peripheral are you using?
It is compare match timer interrupt from RTI3.
Is the same case happening for both level and pulse trigger interrupts?
Yes I tried to change the interrupt to pulse and the same happens.
Understood. The sequence seems to be same as SDK.
Thank you for answering the questions.
Could you please let me know what is frequency in which you are triggering this RTI Interrupt? I will try to reproduce this with the SDK IRQ handler to better understand the stuck scenario.
Thanks & Regards
Sri Vidya
Thank you for your follow up
I do not trigger it with high frequency but simulate it with busy wait for some time
form the user handler you can do something like the following:
isr()
{
/* Clear interrupt at source */
TRIGGER_INTERRUPT();
sleep(200000);
}
void sleep ( unsigned int s )
{
volatile VAR (uint32, AUTOMATIC) sleepCounter;
for ( sleepCounter = (uint32) 0U; sleepCounter < (uint32) s ; sleepCounter++ )
{
;
}
}
and at TRIGGER_INTERRUPT you can but a small value in the compare register so it the compare match happens before the sleep function ends
Hi
Got it. I will try to reproduce at my end please allow me some time.
Regards
Sri Vidya
Take your time
FYI
I tried to change the interrupt to pulse and it worked (previously when I changed it to pulse I did not change the sequence of when the flags were cleared)
So seems this is a bug in level interrupt
Another important note:
We have another project with another target J7 which is cortexR also using the VIM.
I tried the same sequence on it and I found when VIM is cleared and still interrupt source == 1 it immediately raise the VIM flag again which is expected and which is not happening in VIM of Am263x for interrupts of level type
HI
I tried to change the interrupt to pulse and it worked
Yes thats what I was thinking to.
Pulse Interrupt should work.
So seems this is a bug in level interrupt
A level interrupt is assumed to be used when there are multiple spurious interrupts for the same interrupt like a GPIO external interrupt.
So level interrupt is expected to work like this.
I tried the same sequence on it and I found when VIM is cleared and still interrupt source == 1 it immediately raise the VIM flag again which is expected and which is not happening in VIM of Am263x for interrupts of level type
Oh I am not aware of J7 IRQ Handler.
But I will cross check with our SW team if this is expected from our IRQ level interrupt handler.
Anyway glad you are unblocked.
Regards
Sri Vidya
So level interrupt is expected to work like this.
Hi
What I can find in datasheet is exactly the opposite
Got it. Will pass on this information.
Thanks & regards
sri vidya
Hi
This looks like a timing issue on when the level interrupt is cleared at VIM STS.
If you clear the STS bit along with the source in your ISR, And then you try to trigger the interrupt again.
I think this will resolve the issue you are facing for level interrupt.
Is this what you are expecting?
Regards
Sri Vidya
I think that I have already explained the bug enough till now and explained it how could it happen in SDK code and I believe that it is really a bug
Sorry but I cannot explain over and over again
Hi
Apologies for the inconvenience caused.
I will raise a Jira ID for this issue and assign to SW team.
We will try to fix it in SDK in future releases.
Thanks & Regards
Sri Vidya