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.
Does AM2634 support self interrupt nesting?
example:
_interrupt EpwmIsr()
{
//do some task
(breakpoints)
while(1)
{
;
}
//clear relative flags
}
if I add a break point before while(1), the program can always stop at that break points instead of just once because interrupt will nest itself
-----------------------------------------------------------------------------------------------------------------------------------------------
why I choose this way(self interrupt nesting)?
assume my work now have 4 types of tasks: 62.5us/125us/250us/1ms task.
run my 62.5us task need 30us, but 125us 250us 1ms need time more than 32.5us, so i cant finish all my function within 62.5us, but 125us /250us /1ms don't need to execute every 62.5us
my solution
_interrupt 62.5us service()
{
62.5cnt = (62.5cnt++ &0x0f) //make sure 62.5cnt range in 0~15
//always do 62.5us task
//if (62.5cnt & 0x01) do 125us task
//if (62.5cnt & 0x03) do 250us task
//if (62.5cnt & 0x0f) do 1ms task
}
so in this way I can only use 1 interrupt ISR rather than 4 different priority ISRs can finish my work.
-----------------------------------------------------------------------------------------------------------------------------------------
Above all, is 2634 support self interrupt nesting? how do I configure it?
Hi zhou nanyi,
Based on your use-case, it looks like you need RTI (Real Time Interrupt or AM2634's Timer) interrupt to be self nested. This is possible, as this requires, the RTI interrupt to be clear as soon as the ISR is entered.
My another suggestion would be to use multiple compare events in the same counter with higher timeout values. This is the block diagram of a single counter in AM2634 -
I hope this helps.
Best Regards,
Aakasj
Hi Aakasj,
If RTI can support interrupt self nested, it should meet my needs, and I will try using RTI module.
As for the multiple compare events, due to the fact that running different functions can lead to changes in the running time of tasks, the system may not be aware of the running time of this task before running, so it is suitable for events for your suggestions?
Finally, epwm module does not support interrupt self nested? or there is some error in my configuration?
---------------------------------------------------------------------------------------------------------------------------------------------------
The following information is for reference
Task Schedule
Configuration and code: (edit by demo epwm_valley_switching,delete gpio configuration)
syscfg:
EPWM3
free run, divide clock by 1, TBPRD = 12500, up-count mode
EPWM->EPWM Event-Trigger
select Enable EPWM interrupt
interrupt event source: time-base counter equal to period
interrupt event count: 1 event generates interrupt
INT XBAR
XBAR output: EPWM3_INT
XBAR Instance: INT_XBAR_0
code:
/* Global variables and objects */ static HwiP_Object gEpwmHwiObject; HwiP_Params hwiPrms; /* Function Prototypes */ static void App_epwmIntrISR(void *handle); static __attribute__((noinline, naked, target("arm"), aligned(4))) void App_EPWM_ISR(void); /* Get Address of ePWM */ uint32_t epwm3TrigTimes; uint32_t gEpwmBaseAddr; uint32_t gEpwmVimStsAddr; uint32_t gEpwmVimStsClrMask; uint32_t intcBaseAddr; void epwm_valley_switching_main(void *args) { Drivers_open(); Board_driversOpen(); /* Get Address of ePWM */ gEpwmBaseAddr = CONFIG_EPWM3_BASE_ADDR; DebugP_log("EPWM Valley Switching Test Started ...\r\n"); /* For EPWM 0 */ /* Register & enable interrupt */ HwiP_Params_init(&hwiPrms); /* Integrate with Syscfg */ hwiPrms.intNum = CSLR_R5FSS0_CORE0_CONTROLSS_INTRXBAR0_OUT_0; hwiPrms.callback = &App_epwmIntrISR; hwiPrms.priority = 0x04; hwiPrms.isFIQ = FALSE; hwiPrms.isPulse = TRUE; intcBaseAddr = gHwiConfig.intcBaseAddr; gEpwmVimStsAddr = intcBaseAddr + (0x404u + (((hwiPrms.intNum)>> 5) & 0xFu) * 0x20u); gEpwmVimStsClrMask = 0x1u << ((hwiPrms.intNum) & 0x1Fu); (void) HwiP_disableInt(hwiPrms.intNum); HwiP_clearInt(hwiPrms.intNum); HwiP_setAsFIQ(hwiPrms.intNum, hwiPrms.isFIQ); HwiP_setPri(hwiPrms.intNum, hwiPrms.priority); HwiP_setAsPulse(hwiPrms.intNum, hwiPrms.isPulse); HwiP_setVecAddr(hwiPrms.intNum, (uintptr_t)&App_EPWM_ISR); HwiP_enableInt(hwiPrms.intNum); EPWM_disableInterrupt(gEpwmBaseAddr); EPWM_clearEventTriggerInterruptFlag(gEpwmBaseAddr); EPWM_enableInterrupt(gEpwmBaseAddr); } static __attribute__((noinline, naked, target("arm"), aligned(4))) void App_EPWM_ISR(void) { ISR_CALL_PULSE_NONFLOAT_REENTRANT(App_epwmIntrISR, hwiPrms, \ 146, gEpwmVimStsAddr, \ gEpwmVimStsClrMask, intcBaseAddr); } static void App_epwmIntrISR(void *handle) { epwm3TrigTimes = epwm3TrigTimes + 1; EPWM_clearEventTriggerInterruptFlag(CONFIG_EPWM3_BASE_ADDR); while(1) { ; } return; }
when I comment while(1){} in ISR, the variable epwm3TrigTimes increases every time, means my interrupt configuration is right.
when I uncomment while(1){} in ISR, the variable epwm3TrigTimes = 1, means self nested do not work.
Best regards
Hi zhou nanyi,
Let me try to reproduce this with EPWM. I will come back to you by 19th April.
Best Regards,
Aakash
Hello zhou nanyi,
We are trying to reproduce the issue at our end.
We see that you use the low latency interrupt handlers in the above code snippet - and you have chosen the pulse + reentrant version of handler appropriately.
While we try to reproduce the issue, can you please try running your ISR code with the default SDK handlers and check the behavior?
(by registering the ISR using HwiP_construct function as documented here AM263x MCU+ SDK: Optimizing applications with MCU SDK)
Thanks
K.Sanjeev
Hello zhou nanyi,
I am able to reproduce the issue. I used your snippet of code (69-75) in our 'user_isr1_tc'1ISR function (triggered by EPWM interrupt) in the dpl_low_latency_interrupt example. I observed that epwm3TrigTimes remains 1.
I suspect the issue is due to the order of VIM acknowledgement. In the ISR_CALL_PULSE_NONFLOAT_REENTRANT macro, VIM ack is performed after the user ISR. So I suspect that another interrupt is allowed to be nested, but not the same interrupt.
I have created a new macro (modified version of the macro) to perform the VIM ack before calling the user ISR, so that the self interrupt is serviced.
With this change, the issue issue is not observed. epwm3TrigTimes counts up to 36
To fix this in your application,
Can you please use this macro in line 62 and try?
ISR_CALL_PULSE_NONFLOAT_SELF_REENTRANT
Use this definition of macro:
#define ISR_CALL_PULSE_NONFLOAT_SELF_REENTRANT(fn, arg, intNum, vim_sts_addr, vim_sts_clr_mask, vim_addr) \ __asm__ volatile( \ " SUB lr, lr, #4 \n" \ " PUSH {lr} \n" \ " MRS lr, SPSR \n" \ " PUSH {lr} \n" \ " CPS #0x13 \n" \ " PUSH {r0-r4, r12} \n" \ " AND r2, sp, #4 \n" \ " SUB sp, sp, r2 \n" \ " PUSH {r2, lr} \n" \ " LDR r0, ="#vim_sts_addr" \n" \ " LDR r0, [r0] \n" \ " LDR r1, ="#vim_sts_clr_mask" \n" \ " LDR r1, [r1] \n" \ " STR r1, [r0] \n" \ " LDR r0, ="#intNum" \n" \ " LDR r0, [r0] \n" \ " LDR r1, ="#vim_addr" \n" \ " LDR r1, [r1] \n" \ " STR r0, [r1, 0x18] \n" \ " CPSIE i \n" \ " LDR r0, ="#arg" \n" \ " LDR r0, [r0] \n" \ " LDR r1, ="#fn" \n" \ " BLX r1 \n" \ " CPSID i \n" \ " POP {r2, lr} \n" \ " ADD sp, sp, r2 \n" \ " CPSID i \n" \ " DSB \n" \ " ISB \n" \ " POP {r0-r4, r12} \n" \ " CPS #0x12 \n" \ " POP {LR} \n" \ " MSR SPSR_cxsf, LR \n" \ " POP {LR} \n" \ " MOVS PC, LR \n" \ )
Thanks
K.Sanjeev
Hi K.Sanjeev,
Thank you so much for your solution, I add your code in <kernel/nortos/dpl/r5/HwiP_armv7r_vim.h>, it seems that the program now can self-nested now.
The epwm3TrigTimes always counts to 691 then code goes to bellow, perhaps it has reached the nesting limit.
void __attribute__((interrupt("UNDEF"), section(".text.hwi"))) HwiP_undefined_handler(void) { volatile uint32_t loop = 1; while(loop!=0U) { ; } }
I think it meets my solution and only when I complete my porting work can I prove whether this method is effective.
Besides, Is there anything else that needs to be modified or noted after I add this ISR_CALL_PULSE_NONFLOAT_SELF_REENTRANT?
Best regard,
Nanyi
Hello zhou nanyi,
Good to hear that it works
Besides, Is there anything else that needs to be modified or noted after I add this ISR_CALL_PULSE_NONFLOAT_SELF_REENTRANT?
No further modifications are required for this specific case. We will plan to integrate this new macro in the SDK.
If you have other interrupts in your use case which uses the macro: ISR_CALL_PULSE_FLOAT_REENTRANT (which performs floating point context save/restore), then this issue applies for that macro as well. We can provide a fix for that if required.
I have created a new macro (modified version of the macro) to perform the VIM ack before calling the user ISR, so that the self interrupt is serviced.
Thanks
K.Sanjeev
Hi Sanjeev,
Thank you again for providing technical support.
Best regards,
Nanyi Zhou