EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Cortex M4 Interrupt states

Started by yuvraj25 7 years ago13 replieslatest reply 7 years ago857 views

Hello,

I am working on #Cortex M4 and currently I am in a situation where in from the interrupt (exception) routine I want to enter into thread mode and execute a function and then again return back to handler mode. When I enter into thread mode (By changing the PSR register and using BX instruction) the the IPSR register is cleared but active exception becomes pending. 

What can be the reason that the Active exception becomes pending ?

Regards,

Yuvraj

[ - ]
Reply by Ivan Cibrario BertolottiJanuary 16, 2017

Hello,

as far as I know, the behavior you are observing is normal.  There is an exception whose handling has not been completed, but the processor is currently executing in thread mode (because it has been forcibly put in that mode, bypassing the ordinary exception entry/exit mechanism).  So, the exception is pending by definition.

It is worth noting that the ARMv7-M architecture reference manual first gives a slightly simplified definition of "pending exception" (Section B1.3.2) and then gives the full explanation (Section B1.5).  The full explanation (plus a look at the exception handling pseudocode) is needed to understand how the processor behaves in this particular case.

I would like to remark that manipulating PSR bits related to exception handling is normally done only by operating system programmers, in a very careful way.  This is because it is quite easy to bring the processor into "borderline" states, like the one you are observing.   So, I join MichaelKellett in asking whether you are using an RTOS or not.

Moreover, what escapes me a little bit is why you would like to go back and forth from handler to thread mode while an exception is being handled.  I am probably missing something but no use cases come into my mind.

Regards,
Ivan

[ - ]
Reply by MichaelKellettJanuary 16, 2017

Are you using an RTOS - if so which one.

I ask because I've never had any need to directly manipulate registers when using Keil's RTOS,

MK

[ - ]
Reply by Tim WescottJanuary 16, 2017

First, I echo everyone who's asking about an RTOS -- if you're using one, there's a mechanism for doing what you want through the RTOS.

Second, I question whether you need to do what you're doing.  There's no reason, if you have well-written code, that you can't call "ordinary" code from within an ISR.  If it's a bad idea to do so within an interrupt context, then for the most part it's still a bad idea to do so after convincing the processor that it's not within an interrupt context.

Perhaps you could give a broader view of what you're trying to accomplish, and why you're trying to accomplish it in exactly that way.  You'll get suggested alternatives, hopefully with reasons on why they're being suggested.

[ - ]
Reply by yuvraj25January 16, 2017

Hello,

I am working on development of a proprietary RTOS. The Use case of entering into thread mode from exception handler is that the ISR is executed in Handler mode hence (supervisory mode) but I want to provide a function to the users that will be executed in User mode. So I need to enter into thread mode execute that function and then return back into handler mode(I am using PendSV for returning back to handler mode). 

But when i enter into thread mode the active interrupt goes to pending state. One important thing i missed to mention is that before entering into thread mode I disable the interupts using BASEPRI(at this time the interrupt is still active)and then enter into thread mode(this is the instance when active interrupt becomes pending) and when the interrupts are enabled the pending interrupt becomes active and I again enter in ISR(Unintended behaviour).

Regards,

Yuvraj

[ - ]
Reply by Tim WescottJanuary 16, 2017

The fact that you're developing your own RTOS pretty much sweeps the "you should let the RTOS do this" comments off the table.

Unfortunately, my experience with the Cortex M-series won't help you: I had a mind to build my own RTOS for the Cortex as a hobby project, and dealing with interrupts cleanly utterly defeated me.  I ended up using FreeRTOS.  8-bit microprocessors have a much easier interrupt mechanism.

It may not be a bad idea to look for as many open-source RTOS's as you can (FreeRTOS and Micro-C/OS-III, if it's still open source, come to mind).  Don't look for the purposes of copying code, but rather for looking at how they handle the whole return-from-interrupt thing.  I know that in the case of FreeRTOS there's a priority level below which the RTOS will intercept interrupts, and above which all of the interrupts are purely the responsibility of the developer, but it's been too long for me to remember the details.

(It was actually through taking the above suggestion for myself that I ended up using FreeRTOS: I didn't really _need_ to roll my own RTOS, and once I realized how easy it would be to just _use_ FreeRTOS, I decided that I'd stick with being a control system and signal processing expert who can code rather than trying to become a system programming expert.)

[ - ]
Reply by Ivan Cibrario BertolottiJanuary 16, 2017

Many operating systems do not support execution of unprivileged code (in this case thread-mode code) from within an interrupt handler at all.  Microkernel-based operating systems do, but their approach is to put the thread-mode code in an unprivileged task, and then wake up the task from a short, privileged interrupt handler.

Some monolithic/layered operating systems offer similar features, too, by using a similar strategy: split the interrupt handling code into a privileged and an unprivileged handler, and trigger the execution of the unprivileged part *after returning from* (not *within*) the privileged part.  Case in point: the ISR/DSR mechanism in eCos.

There are good reasons for this.  An important one is portability, which should be a primary goal of an RTOS.  Although I guess (not totally sure on this) that switching from handler to thread mode and then back may be possible on Cortex-M, it may be hard (or even impossible) to do the same on other architectures.

I agree that browsing the source code of some open-source RTOS (the ones that support the feature you are looking for) is a good starting point.  Before doing that, I would start by studying very carefully the ARM architecture reference manual, to make sure that what you are trying to accomplish is architecturally supported.

[ - ]
Reply by yuvraj25January 16, 2017

Hello Ivan,

Thank you very much for your valuable support. Sorry for providing insufficient and incorrect information in the question. Here is more clarification of the problem.

The Exact meaning of entering into thread mode from handler is nothing but returning from handler for which I set the LR value to 0xFFFFFFF9(Enter thread and use Main Stack) and perform use BX instruction (BX Lr).

I will put it in following steps

1. Currently executing Handler mode for and exception say No 40 (Priority say 12), FAULTMASKhas value 1

2. Steps for entering thread mode

     2.1 set BASEPRI to 0x01 Because BX LR clear FAULTMASK

     2.2 Put the address of function which i want to execute in thread mode into          PC

     2.3 Put 0xFFFFFFF9 into LR

     2.4 BX LR Instruction

When I execute BX LR Instruction (As seen in debug mode using single stepping) The interrupt active register BIT for exception 40 becomes zero and Interrupt pending bit becomes 1 FAULTMASK is 0 and BASEPRI is 0x01. 

Can I say that because Interrupt active bit is cleared the exception return is successfull ? But then Why the interrupt Pending bit is set ?

Is this some how related to priority escalation ?

[ - ]
Reply by Ivan Cibrario BertolottiJanuary 16, 2017

Hello,

no problem, thanks for the extra information, it's hard to reason about these things without having a fairly complete picture.  I have a couple of (hopefully helpful) additional remarks/questions.

(1) I assume that in step 2.2 you are modifying the PC saved on the topmost stack frame (offset +18 for a basic frame) because of two considerations.

(1a) If you modify the PC register directly you never reach step 2.3 because the processor jumps immediately.

(1b) Moreover, BX LR with LR=0xFFFFFFF9 reads its target jump destination from that location (PopStack() pseudocode in the ARM reference manual).

In this case, please take into account that, on the same stack frame, the processor holds in xPSR (offset +1C) some internal state pertaining to the interrupted instruction (that is, the instruction that was executing when exception 40 was accepted).

I am referring in particular to the EPSR fields of that register, which hold information to properly resume LDM/STM (ICI field) and conditional instructions (IT fields). BX LR with LR=0xFFFFFFF9 restores this information.

Starting the execution of one instruction (the one you are jumping to) using the internal processor state belonging to another instruction (the interrupted one) must be handled with utmost care.

For instance, starting the execution of another instruction when the processor (using the EPSR information from the stack frame restored by BX LR) expects to resume an interrupted LDM/STM will lead to undefined behavior and most probably lock the processor.

You may refer to the ARM reference manual Table B1-2 and Section B1.5.10 for more information on this.  Please also note that this is a time-dependent issue, so the same code may work or fail depending on which instruction was hit by the interrupt (hard to predict of course).

You may also encounter a similar issue with the LR register.  BX LR when LR=0xFFFFFFF9 will also restore LR from the topmost stack frame (offset +14)... this is the LR that was in effect when exception 40 was accepted, and is probably invalid in the user context you are jumping to.

(2) This is minor but... are you setting FAULTMASK=1 yourself in step 1?  The processor doesn't do it normally.  If so, any particular reason for doing that?

(3) To my experience, debuggers may or may not not provide 100% reliable information when used in exception handlers, especially when dealing with exception entry and return.

I am sorry, I realize that I probably made the picture even more complex than it already was... but these seemingly tiny details are truly important.  As Tim Wescott very appropriately pointed out earlier, the Cortex interrupt handling mechanism is far from being simple.

Best regards,
Ivan

[ - ]
Reply by yuvraj25January 16, 2017

Hello Ivan,

Yes, Changing the PC means Changing the PC value in the stack.

Also I change PSR Value in the stack as 0x01000000

So after executing BX LR the valw in xPSR is 0x01000000


Regards,

Yuvraj

[ - ]
Reply by Ivan Cibrario BertolottiJanuary 16, 2017

If the stack frame is set up correctly, it should work because it would mimick exactly the normal exception exit sequence, except for the target PC.

I did it myself on a Cortex-M3 (LPC1768) a couple of years ago, and I'm positive that the M4 works the same in this area.  The only difference is that the M4 saves an extended stack frame if the FP unit is in use.

As far as I remember, I didn't modify FAULTMASK and BASEPRI though.  I quickly went through the pseudocode in the ARMREF.  It seems to me that there may be the (somewhat implicit) assumption that, upon exception return, the current exception priority is higher (numerically lower) than BASEPRI.

I would check if the code works when you leave BASEPRI untouched.

Regards,
Ivan

[ - ]
Reply by yuvraj25January 16, 2017

Hello Ivan,


The reason for interrupt going from ACTIVE to PENDING state at exception return is

The interrupt is timer interrupt and before acknowledging the interrupt i was entering into thread mode( returning from interrupt) because of which the interrupt was is getting pended.

Regards,

Yuvraj

[ - ]
Reply by Ivan Cibrario BertolottiJanuary 16, 2017

It just came into my mind that a similar question (returning to an arbitrary thread-mode address from an ISR) was asked a couple of years ago for the Cortex-M3 (M4 is the same from this point of view).

http://stackoverflow.com/questions/9526077/cortex-m3-changing-interrupt-return-address

One of the answers describes the issue with the saved EPSR even better than I did above.

Ivan


[ - ]
Reply by yuvraj25January 16, 2017

I am working on development of a proprietary RTOS. The Use case of entering into thread mode from exception handler is that the ISR is executed in Handler mode hence (supervisory mode) but I want to provide a function to the users that will be executed in User mode. So I need to enter into thread mode execute that function and then return back into handler mode(I am using PendSV for returning back to handler mode). 

But when i enter into thread mode the active interrupt goes to pending state. One important thing i missed to mention is that before entering into thread mode I disable the interupts using BASEPRI(at this time the interrupt is still active)and then enter into thread mode(this is the instance when active interrupt becomes pending) and when the interrupts are enabled the pending interrupt becomes active and I again enter in ISR(Unintended behaviour).

Regards,

Yuvraj

Memfault Beyond the Launch