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.
Dear TI experts,
could you help me please? Thanks so much.
MCU: TMS570LS20216, this MCU hardware not support IRQ preempt IRQ in default;
In my application, IRQs from high priority to low priority: adc1group0Interrupt, adc1group1Interrupt, adc1group2Interrupt, adc2group0Interrupt, vPreemptiveTick. vPreemptiveTick is FreeRTOS operating systems 1ms tick interrupt, I reconfigured it to IRQ VIM channel[61] which is lower priority (vimREG->CHANMAP[61]=2). The FreeRTOS is generated from HalCoGen ver2.10.
In my application, we need implement this requirement: when adc2group0Interrupt is in service, we need enable higher IRQs(adc1group0Interrupt, adc1group1Interrupt, adc1group2Interrupt) preempt this interrupt, but lower priority IRQ(vPreemptiveTick) can’t preempt this interrupt.
The following is adc2group0Interrupt() code, when using ETM trace tool, I found sometimes os task will run after entering this interrupt, I don’t know why this happens, I don’t want to os task run after entering this interrupt:
#pragma INTERRUPT(adc2Group0Interrupt, IRQ)
void adc2Group0Interrupt(void)
{
/* used to save the interrupt enable/disable settings */
uint32 interrupt_setting_1 = 0;
adcREG2->GxINTFLG[0U] = 9U;
/* save the interrupt enable/disable settings */
interrupt_setting_1 = (uint32)(vimREG->REQMASKSET1);
/*
* adc2Group0Interrupt is in VIM channel[50],
* diable all lower priority interrupts and adc2Group0Interrupt itself.
* So, only higher priority will preempt this interrupt.
*/
vimREG->REQMASKCLR1 = 0xFFFC0000;
/*
* Manually save context, and Enable IRQ interrupt.
*/
asm(" STMFD SP!, {R0-R12, LR}");/*Save R0- R12, LR_irq*/
asm(" mrs lr, spsr"); /* Copy SPSR_irq to LR */
asm(" STMFD SP!, {LR}"); /* Save SPSR_irq */
asm(" MSR CPSR_c, #0x1F"); /* Enable IRQ (Sys Mode) */
asm(" STMFD SP!, {LR}"); /* Save LR */
Rte_Run_Application_Logics();
/*
* Manually restore context, and disable IRQ.
*/
asm(" LDMFD SP!, {LR}"); /* Restore LR */
asm(" MSR CPSR_c, #0x92"); /* Disable IRQ (IRQ Mode) */
asm(" LDMFD SP!, {LR}"); /* Restore SPSR_irq to LR */
asm(" MSR SPSR_cxsf, LR"); /* Copy LR to SPSR_irq */
asm(" LDMFD SP!, {R0-R12, LR}");/* Restore LR */
/* restore the interrupt enable/disable settings */
vimREG->REQMASKSET1 = interrupt_setting_1;
}
Fumin
I will consult with some more folks here. Right now I am only able to think of the RTI interrupt coming in during the window in which MASKCLR1 is not yet written. So VIM recognizes the interrupt and kicks off IRQ which gets taken as soon as IRQ is enabled on the CPU. Have you tried pushing the MASKCLR1 write further up? Let me chk today and get back.
Fumin
One other thing to try is that you clear the ADC interrupt after disabling the lower priority interrupts. That way a new assertion of IRQ to processor does not happen before you disable the lower priority interrupts. However, I haven't had the opportunity to try this myself.
Fumin,
What is the interrupt that you see in your trace?
As soon as the new mask is applied, if an interrupt was pending, it is cleared, so when IRQ is enabled again, you should not see any lower request.
Note that FIQ will still be active and will interrupt IRQ.
Please let me know.
Dear Jean-Marc and Abhishek Shankar,
So many thanks for your quickly response.
It's the OS tick interrupt "vPreemptiveTick".
I think Abhishek Shankar's reply maybe right, i will test it later.
Maybe the "vPreemptiveTick" IRQ is detected but not serviced before i enable IRQ, when i enable IRQ, so, it will be serviced.
But it's only a guess, it need confirm from you-TI experts.
And by the way, if i read vim register "pending interrupt read location register[0:1]" (offset: 0x20,0x24), is there any side effects ? It will clear the pending interrupt request?
When I add this red color statement, I didn’t find os task will execute any more (of course, maybe I didn’t capture it, but it really executes):
Uint32 Vim_pending_int_0=0;
Uint32 Vim_pending_int_1=0;
/*
* adc2Group0Interrupt is in VIM channel[50],
* diable all lower priority interrupts and adc2Group0Interrupt itself.
* So, only higher priority will preempt this interrupt.
*/
vimREG->REQMASKCLR1 = 0xFFFC0000;
if( (0 != vimREG->INTREQ0)||(0 != vimREG->INTREQ1) )
{
Vim_pending_int_0 = vimREG->INTREQ0;
Vim_pending_int_1 = vimREG->INTREQ1;
}
/*
* Manually save context, and Enable IRQ interrupt.
*/
asm(" STMFD SP!, {R0-R12, LR}");/*Save R0- R12, LR_irq*/
asm(" mrs lr, spsr"); /* Copy SPSR_irq to LR */
asm(" STMFD SP!, {LR}"); /* Save SPSR_irq */
asm(" MSR CPSR_c, #0x1F"); /* Enable IRQ (Sys Mode) */
asm(" STMFD SP!, {LR}"); /* Save LR */
Fumin,
Reading the vimREG->INTREQ0 or vimREG->INTREQ1 has no effect and will not clear any pending request.
So in your code, I don't see why it is helping aside from delaying the rest of the code.
In your device startup, are you using the MPU to change the default setting for the peripheral region?
Fumin,
I just realized that in your code you are doing:
vimREG->CHANMAP[61] = 2;
This will map the req 2 on channel 61. This is ok. What about the channel 2. It will stay also mapped to request 2.
In other words the request 2 is now mapped to two channels. Channel 2 and Channel 61.
If I'm correct, Halcogen does not provide support (yet) for channel remapping. So I assume you are doing that in your own code.
Without your full initialization code, I can't see what is going on.
Dear Jean-Marc,
Yes, you are right, i remapping by writing code, the request 2 is now mapped to two channels:Channel 2 and Channel 61. And i only enable channel61 interrupt.
In startup code , i call _mpuInit_() function before main() function. _mpuInit_() function is generated by HalCoGen and i didn't change it.
Fumin,
What is the status on your post? Did I answered your question?
If so, can you mark it as "Verified Answer" so I can close this thread?