cancel
Showing results for 
Search instead for 
Did you mean: 

nested interrupts

cebotor
Associate II
Posted on December 23, 2008 at 05:58

nested interrupts

14 REPLIES 14
cebotor
Associate II
Posted on May 17, 2011 at 12:57

Hello!

I have some problems with interrupts controller in stm32. I try to enable re-enter to same interrupt.

For example to make possible re-enter to systick interrupt from systick interrupt, if fist one temporary stop.

I see at simple way its impossible - its only can enter ISR with higher priority then first one. My attempts to manipulate to priority ''on the fly '' have not result too.

Is it possible without asm wrappers ?

joseph239955
Associate II
Posted on May 17, 2011 at 12:57

Hi Cebotor,

Without knowing exactly why you want to created nested systick exception,

the following method might or might not be useful.

Instead of trying to trigger the systick exception again, you could just called the systick handler inside the systick handler (I assumed your systick handler is just a C subroutine).

Alternatively, if you really need to trigger the code as a higher priority exception, you could use an unused interrupt type and set its vector same as the systick one, program this unused interrupt as higher priority and manually set the pending status of this unused to trigger it inside your systick handler. In this way you can have two levels of the same exception handler (but different exception type).

regards,

Joseph

cebotor
Associate II
Posted on May 17, 2011 at 12:57

Hello again, Joseph.yiu, thanks for your answer!

I try to make my interrupts realy reenterable, without restrictions which imposed by priority rules . I need it to implemet some different than classic RTOS task sheduler: sheduler , which call few little ''tasks'' like simple C functions without switching context. And in case of one of these task will stoped for time more than period of sheduler,then the next copy of interrupt (and sheduler) must occur from first one(not by my call, vic must call interrupt). This means that interrupt with some prioryty should be able to reenter himself. I try to understand , is it possible?

cebotor
Associate II
Posted on May 17, 2011 at 12:57

Ok, now I see that I reed docs enough before I ask my question.

is this method means I must call exc return to let nvic go back to thread mode?

by writing to PC 0xfffffff9 for example? There is no another way to go back to thread?

joseph239955
Associate II
Posted on May 17, 2011 at 12:57

It is not easy to do, and is unlikely that you can do it without asm wrapper.

One method is to use the non-base thread enable feature to change your systick handler back to thread level (requires manipulation of stack frame) so that the systick exception could happen again.

regards,

Joseph

joseph239955
Associate II
Posted on May 17, 2011 at 12:57

Yes, this invoke using a trigger a higher priority exception in your systick handler, modifiy the return stack and EXC_RETURN value, and then return to thread level directly.

Alternatively, a simpler solution could be creating an asm wrapper for the systick handler that

- modify the stack frame,

- set basepri to mask lower priority exceptions, and then

- carry out exception return with stacked return address equal

to the second half of the wrapper function

- second half of wrapper function execute in thread level, with basepri set so that onlt another systick or higher priority exceptions can take place. call your C function

- C systick handler execute at thread level

- C systick handler return to second half of wrapper function

- clear basepri

- wrapper function return to the interrupted program.

It still requires using an asm wrapper, but is more simple than using

non-base thread enable.

[ This message was edited by: joseph.yiu on 19-12-2008 13:17 ]

picguy
Associate II
Posted on May 17, 2011 at 12:57

My approach to this is to give your desired reentrant interrupt a priority X higher than priority Y. Given that higher priorities have lower numbers, numerically X is less than Y. (Edit: lost less than sign.)

ISR X does little but queue work for and software trigger ISR Y. ISR X then exits. ISR Y processes the queued work requests in order.

FWIW, I have a little help for software FIFOs on

http://www.hmtown.com/fifo.htm

(Just ignore anything specific to RS-232.)

On Cortex M3 your transition from ISR X to ISR Y only adds 6 clocks. The normal overhead for an ISR call/exit is 24 clocks.

[ This message was edited by: picguy on 20-12-2008 23:34 ]

cebotor
Associate II
Posted on May 17, 2011 at 12:57

�?ž�?º ,now I have tried few methods.

Its great idea to use queue to solve this problem, but.. its does not work because ISR Y anyway could not be interrupted with ISR Y.

We can make queue from ISR X , which will interrupt ISR Y , but ''ISR Y processes the queued work requests in order'' only when first copy of ISR Y will be completed. Or I have misunderstood you, Picguy?

I dont see the big difference between both methods offered by Joseph.yiu , because in both cases i could not manage without asm.

But method 2 work! with some little patches:

1.

- set basepri to mask lower priority exceptions,

- clear basepri

needed to keep priority rules, isnt it?

I do not need it, becouse i try to make full enable_interrupt

and let it be mutually nested.

2. Probably i am mistaken, but i see that it is impossible to correct return to the thread which was interrupted by ISR by just

POP {PC}

..because of ICI for example (Interruptible-Continuable Instruction)

So to return to the thread i use a trigger a higher priority exception (SVC) then patch the stack frame then carry out axceprion return.

And this is what I have:

/////////////////////////////////////////////////

__TEST_Wrap_enter

LDR r0,[SP,#0]

STR r0,[SP,#-44]

LDR r0,[SP,#4]

STR r0,[SP,#-40]

LDR r0,[SP,#8]

STR r0,[SP,#-36]

LDR r0,[SP,#12]

STR r0,[SP,#-32]

LDR r0,[SP,#16]

STR r0,[SP,#-28]

LDR r0,[SP,#20]

STR r0,[SP,#-24]

LDR r0,[SP,#24]

STR r0,[SP,#-20]

LDR r0,[SP,#28] ; r14

STR r0,[SP,#-16]

LDR r0,=__TEST_Wrap1

ORR r0,r0,#1

STR r0,[SP,#-12]

LDR r0,[SP,#36]

AND R0,R0,#0xff //patch to keep ISR NUMBER

ORR R0,R0,#0x01000000 // patch to clear ICI and IT fields

STR r0,[SP,#-8]

STR LR,[SP,#-4] //address to return from wrap to srack

SUB SP,SP,#44

POP {r0,PC}

;;;;;;;;;;;

__TEST_Wrap1:

POP {LR} // could be POP {PC }

BX LR

__TEST_Wrap_exit:

CPSID i

mov r0,#0x10 //It is necessary to forbid all exceptions except SVC

MSR BASEPRI, r0

CPSIE i

SVC 0x01

__TEST_Wrap_exit_1:

b __TEST_Wrap_exit_1

svc_handler_my:

mov r0,#0x40

MSR BASEPRI, r0

ADD SP,SP,#40

BX LR

//and systick ISR looks like :

void SysTickHandler(void)

{

__disable_interrupt();

SysTickHandler_before_wrap();

__TEST_Wrap_enter();

__enable_interrupt();

SysTickHandler_after_wrap();

__enable_interrupt();

__TEST_Wrap_exit();

}

/////////////////////////////////////////////////

Correct me please if I am wrong

PS Big Thanx to Joseph.yiu !

[ This message was edited by: cebotor on 22-12-2008 23:00 ]

joseph239955
Associate II
Posted on May 17, 2011 at 12:57

Hi cebotor,

Yes, you are right, I forgot that xPSR need to be saved due to ICI/IT bit.

So you need to use a separated exception return to restore the interrupted program. Sorry for misleading you a bit.

Yes, if you want to allow all interrupt to be allowed, then you don't have to set basepri.

From your example code it seems the stack frame is offset by two words

which I don't know why.

LDR r0,[SP,#28] ; r14 -> SP+28 is normally pointed to PSR in stack frame, not R14 (LR)

Another point I just thought of is that if the systick handler is not the lowest priority exception, then this method can not be used. If the systick took place when another ISR is running, then it will try returning to thread with another interrupt being active - which would lead to a fault.

The idea of copying the stack frame and created a modified version is good. But I would prefer to put the handler code in asm, and then call the C function, instead of calling the asm wrapper code from C because the stack pointer value when entering the asm wrapper might not be the same as what it is when it enter the handler. But as long you checked that in dissembled code that the stack content begin copied is correct, then that should be fine.

Joseph