Detect ISR method call in FreeRTOS - interrupt

Is it possible to determine whether a method in FreeRTOS is being invoked from the context of an ISR (interrupt service request) or a task at runtime? Maybe an existing function already exists for this or maybe it is possible to write a method that examines the stack somehow?

There are two ways to do this. I'm using a Cortex-M7 microcontroller. So I'm not 100% sure this works for your Cortex-M3. But it's worth checking in your datasheets.
FIRST APPROACH
Check the CPU registers of your Cortex-M core. Normally you have the usual R0-R12 CPU registers, a SP (Stack Pointer), a LR (Link Register) and a PC (Program Counter). There are a few extra 'special' CPU registers, more specifically: PSR, PRIMASK, FAULTMASK, BASEPRI and CONTROL. That's it for the Cortex-M7 core.
Now consider the PSR register. The PSR register stands for "Program Status Register". There is a bitfield ISR_NUMBER[8:0] in it. If it has the value 0, the CPU is in "thread mode". Thread mode is the normal non-interrupt mode. If the value is nonzero, your CPU is executing an interrupt. What interrupt? The value in ISR_NUMBER[8:0] tells you the interrupt number.
Reading the value of the PSR register is not trivial. You need to use specific assembly instruction to do that. There is no quick way to do it in C. You will need the MSR (Move general to special reg) and MRS (move special to general reg) instructions. Of course, inline assembly will make it possible to put it smoothly in your C-code :-)
SECOND APPROACH
There is a second approach. Unlike the previous one, you don't need to read out a CPU register. Instead, this second approach requires you to read out the value of a 'general' register (like there are a few thousand in your microcontroller). The register I'm referring to is the ICSR(Interrupt Control and State) register. This register is located in the SCB "System Control Block". The register has a bitfield named VECTACTIVE[8:0]. Again, this bitfield contains the number of the active interrupt. If the value is 0, the CPU is in thread mode, which means that no interrupt is currently running.
Hope this helps.

Related

whats the relation between ISR and callback function?

I am a little confused about ISR and callback function.
I just know the ISR have no input params and return value. But i use TI MCU SDK register a timer params containing callback function with input params. I want to know how does this timer ISR run the callback function? What is the actual flow CPU runs?
An interrupt (service routine) is called by hardware. A callback function is called by software, which could be a driver, OS or library.
Some libs or drivers might be designed so that you pass along a function pointer to a custom function. Then the driver implements the ISR so that the ISR calls your callback. This provides an abstraction layer at the expensive of some extra function call overhead.
I don't know how your TI driver is implemented, but it is common to have a timer driver register a list of callbacks with corresponding timeouts, then inside the ISR run a loop and check if it is time to execute a certain callback. With such designs it's important to keep the callback functions small.
As answered the hardware for a specific chip or architecture has a very specific way that interrupts are handled. A fixed address where the first instruction for a specific handler is or a fixed address where the address to the handler lives.
Then you add to this the mcu company wants to make your experience easier and tries to do much of the work for you. So they may have a generic handler for each thing and a library system where you tell their library where your code is, their software then has some, likely ram based scheme, if your handler is registered runtime, that is used by the real handler to branch/jump/call yours.
In this case the actual ISR would be TI code.
If you, in your code, have indicated you want to "handle" the interrupt then via library calls or some other scheme you indicate the interrupt you want to handle and the function you want to be called (and sure, perhaps even parameters can be part of this design scheme). This call to indicate your callback function likely also enables that interrupt into the cpu. Depending on the architecture there may be one big handler and only one interrupt or hundreds of individual interrupts and possibly a handler for each, or somewhere in the middle. So it may enable an individual interrupt or it may just enable an if-then-else path in some code the mcu vendor wrote.
interrupt comes into the cpu
cpu finds a good stopping point (between instructions usually)
cpu specific solution for finding the interrupt service routine code, either hardcoded address or hardcoded address in a vector table, or a way to register an address in the logic.
No generally you do not have parameters passed to the real isr. The isr will need to know what caused the interrupt and this is very much processor architecture specific. It is generally not "passed" to the handler like a compiled function call, instead control and status registers are often used.
In this scheme ti writes the isr, but then in some part of their software design they then call your function as if it were a normal compiled function. Possibly even with parameters depending on their design scheme.
Your function eventually finishes and returns
The ti isr finishes and indicates to the processor to continue with the code that was interrupted.

What exactly is an interrupt?

I want to understand what exactly an interrupt is for my 6502 work-alike processor project in Logisim.
I know that an interrupt does the following steps:
Stops the current program from processing
Saves all unfinished data into the stack
Does "SOMETHING"
Loads back the unfinished data and let's the program keep running normally.
My question is: what happens during that "SOMETHING" step? Does the program counter get redirected to a special program to be executed? Something like reading the pressed button's ASCII code and saving that into a register or some memory location? If so, where is that special program usually stored in the memory? And can you make such a CPU that will handle different kinds of interrupts? Maybe if you press the button "a" then it's ASCII will be stored in A register, but if you press the button "b" then it will be stored in X register?
Any help is greatly appreciated.
Edit: Thanks to everybody for answers. I learned a lot and now can proceed with my project.
My question is: what happens during that "SOMETHING" step? Does the program counter get redirected to a special program to be executed?
What happens with a 6502 maskable interrupt is this:
the interrupt is raised (by this I mean the interrupt pin on the chip is forced low.
when it's time to execute a new instruction, the 6502 checks if the interrupt pin is low and the interrupt mask in the status register is not set. If either is not thew case i.e. if the interrupt pin is high or the interrupt mask is high, the CPU just carries on.
Assuming an interrupt is required, the CPU saves the PC on the stack
The CPU then saves the status register on the stack but with the B bit set to 0. The B bit is the "break" bit. It would be set to 1 for a BRK instruction and that is the only way to tell the difference between a hardware interrupt and a BRK instruction.
The CPU then fetches the address at locations $FFFE and $FFFF and stuffs it into the PC, so execution begins again at that address.
That's all it does. Everything else is up to the programmer until the programmer executes an RTI, then the status word and the return address are pulled off the stack and restored into their respective registers. It is the programmer's responsibility to save any registers and other data.
Does the program counter get redirected to a special program to be executed? Something like reading the pressed button's ASCII code and saving that into a register or some memory location?
That is correct. In 6502 based computer systems, there are three vectors at the top of memory:
$FFFA - $FFFB : Non maskable interrupt (as above except the I bit in the status register is ignored).
$FFFC - $FFFD : Reset vector used when the CPU detects a reset
$FFFE - $FFFF : Normal interrupt vector.
The above are usually in ROM because the reset vector (at least) has to be there when the CPU powers up. Each address will point to a routine in the machine's operating system for handling interrupts.
Typically, the interrupt routine will first do an indirect jump through a vector stored in RAM. This allows the interrupt routine to be changed when the machine is running.
Then the interrupt routine has to determine the source of the interrupt. For example, on the Commodore PET thew interrupt might originate from the VIA chip or either of the PIA chips and each of those may raise an interrupt for various reasons e.g. one of the PIA chips raises an interrupt when the monitor does a vertical blank i.e. when it finishes scanning the screen and goes back to the top line. During this interrupt, the PET executes a routine to scan the keyboard and another routine to invert the cursor. Another interrupt might occur when the VIA timer hits zero and the programmer can insert an interrupt routine to, for example toggle an output line to generate a square wave for sound.
Some answers to questions in the comments.
program counter goes to address $FFFE to get relocate to the address
No, the program counter is set to whatever is at that address. If you have:
FFFE: 00
FFFF: 10
the program counter will be set to $1000 (6502 is little endian) and that's where the interrupt routine must start. Also, the vector for NMI is at $FFFA. The normal interrupt shares $FFFE with the BRK instruction, not the NMI.
What exactly the reset vector does? Does it reset the cpu?
The reset vector contains the location of the code that runs after the processor has been powered on or when a reset occurs.
What's the difference between NMI and IRQ? Then I also would like to know what's up with masking? Is it the way to set the "I" flag in Processor Status Register high or low?
The 6502 status register contains seven flags. Mostly they are to do with the results of arithmetic instructions e.g. Z is set if the result of an operation is zero, C is set when an operation overflows eight bits and for shifts. The I flag enables and disables the normal interrupt (IRQ). If it's zero, interrupts on IRQ will be respected. If it's 1, interrupts are disabled. You can set it and disable it manually with the SEI and CLI instructions and it is set automatically when an interrupt occurs (this is to prevent an interrupt from interrupting an interrupt).
NMI is a non maskable interrupt. The difference is that it ignores the state of the I flag and uses a different vector.
And finally, what are vectors? Are they synonymous for indirect addresses?
Yes.
Oh, and if you do know, how are interrupt addresses starting from $FFFA stored in ROM instead of RAM in real 6502?
You have to arrange for the address decoding logic to point those address at ROM instead of RAM. In fact, in Commodore systems the whole block from $F000 is ROM containing part of the operating system. The same probably applies to most other 6502 based systems.
There are four types of interrupt on the 6502: RESET, NMI, IRQ and BRK. The first three are hardware interrupts and the last is a software interrupt. The hardware interrupts have physical input voltages on pins on the microprocessor itself. The software interrupt is caused by a BRK instruction.
All interrupts are 'vectored'. That means when they occur the program counter (PC) is immediately loaded from an address stored in memory, and instruction execution continues from that address.
The addresses are stored as two bytes little endian format at the end of the 64k memory space. They are (in hex):
NMI $FFFA/$FFFB
RESET $FFFC/$FFFD
IRQ $FFFE/$FFFF
BRK $FFFE/$FFFF
In the case of NMI, IRQ and BRK, the current PC address is pushed on to the stack, before loading the interrupt address. The processor status register is also pushed on to the stack.
Pushing the registers on to the stack, is enough information to resume execution after the interrupt has been serviced (processed). The A, X and Y registers however, are not pushed automatically on to the stack. Instead the interrupt service routine should do this if necessary - and pull them back off the stack at the end of the service.
Notice that the IRQ and BRK vectors have the same address. In order to distinguish what happened in your service code, you need to examine the Break Bit of the pushed processor status register. The Break Bit is set if the interrupt came from a BRK instruction.
The currently executing instruction will always be completed before servicing the interrupt.
There are many subtleties to interrupt processing. One of which is which type of interrupt wins in the case that they happen (asserted) at the same time. Another is the point at which an interrupt occurs during the instruction cycle. If the interrupt occurs before the penultimate cycle of the instruction, then it will be serviced on the next instruction. If on or after the penultimate cycle, then it will be delayed until one instruction after.
IRQ interrupts can be 'switched off' or ignored by setting a bit in the processor status register, using the SEI instruction.
Typically the interrupt service routine needs to determine the cause of the interrupt (disc drive, keyboard etc.) and to make sure the interrupt condition is cleared and perform any processing (e.g. putting key presses into a buffer). It can normally do this by reading/writing specific memory locations which are mapped to hardware.
There is more information at this link: https://www.pagetable.com/?p=410
Some more information on how interrupts work in a real 8 bit machine (pages 59, 86, 295): BBC Microcomputer Advanced User Guide
And more information on the physical chip package where you can see the NMI, RES(ET) and IRQ pins on the chip package itself (pages 2,3): 6502 Datasheet
I guess you ask for hardware interrupt (IRQ or NMI). At your step 2 in stack (not in stack register) are stored program counter and flags register. Later you call RTI to resume program execution. The program counter is loaded with start address of "something" which is interrupt subroutine or program to process the interrupt. It has to store A, X, Y registers if need to modify their values and restore them before RTI. The IRQ interrupt can be masked (delayed) with I flag and NMI is non-maskable i.e. it is always processed. They have different addresses for subroutine.
An interrupt is the signal to the running processor by means of hardware or software so that the processor will give attention to that action and does the action according to the interrupt message.
There are three kinds of interrupt:
Internal interrupt :- which include the clock cycle interrupt ,in which cpu has to perform the certain action until the particular time and has to go to perform for the another operation.
Software interrupt:- This interrupt is occurred when the problem or errors occurs in the software itself. For example user tries to divide something by zero and error occurs. And there is interrupt.
External interrupt:- External interrupt is caused by IO devices for example mouse and keyboards.
Cpu is designed to handle such type of interrupt and resumes the process before the interrupt occurred.

Interrupt vector table: why do some architectures employ a "jump table" VS an "array of pointers"?

On some architectures (e.g. x86) the Interrupt Vector Table (IVT) is indeed what it says on the tin: a table of vectors, aka pointers. Each vector holds the address of an Interrupt Service Routine (ISR). When an Interrupt Request (IRQ) occurs, the CPU saves some context and loads the vector into the PC register, thus jumping to the ISR. so far so good.
But on some other architectures (e.g. ARM) the IVT contains executable code, not pointers. When an IRQ occurs, the CPU saves some context and executes the vector. But there is no space in between these "vectors", so there is no room for storing the ISR there. Thus each "vector instruction" typically just jumps to the proper ISR somewhere else in memory.
My question is: what are the advantages of the latter approach ?
I would kinda understand if the ISRs themselves had fixed well-known addresses, and were spaced out so that reasonnable IRSs would fit in-place. Then we would save one indirection level, though at the expense of some fragmentation. But this "compact jump table" approach seems to have no advantage at all. What did I miss ?
Some of the reasons, but probably not all of them (I'm pretty much self educated in these matters):
You can have fall through (one exception does nothing, and just goes to the next in the table)
The FIQ interrupt (Fast Interrupt Requests) is the last in the table, and as the name suggest, it's used for devices that need immediate and low latency processing.
It means you can just put that ISR in there (no jumping), and process it as fast as possible. Also, the way FIQ was thought with it's dedicated registers, it allows for optimal implementation of FIQ handlers. See https://en.wikipedia.org/wiki/Fast_interrupt_request
I think it has do with simplifying the processor's hardware.
If you have machine instructions (jump instructions) in the vector interrupt table, the only extra thing the processor has to do when it has to jump to an interrupt handler is to load the address of the corresponding interrupt vector in the PC.
Whereas, if you have addresses in the interrupt vector table, the processor must be able to read the interruption handler start address from memory, and then jump to it.
The extra hardware required to read from memory and writing to a register is more complex than the required to just writing to a register.

What is a kernel stack used for?

The following is a description I read of a context switch between process A and process B. I don't understand what a kernel stack is used for. There is suppose to be a per process kernel stack. And the description I am reading speaks of saving registers of A onto the kernel stack of A and also saving registers of A to the process structure of A. What exactly is the point of saving the registers to both the kernel stack and the process structure and why the need for both?
A context switch is conceptually simple: all the OS has to do is save
a few register values for the currently-executing process (onto its
kernel stack, for example) and restore a few for the
soon-to-be-executing process (from its kernel stack). By doing so, the
OS thus ensures that when the return-from-trap instruction is finally
executed, instead of returning to the process that was running, the
system resumes execution of another process...
Process A is running and then is interrupted by the timer interrupt.
The hardware saves its registers (onto its kernel stack) and enters
the kernel (switching to kernel mode). In the timer interrupt handler,
the OS decides to switch from running Process A to Process B. At that
point, it calls the switch() routine, which carefully saves current
register values (into the process structure of A), restores the
registers of Process B (from its process structure entry), and then
switches contexts, specifically by changing the stack pointer to use
B’s kernel stack (and not A’s). Finally, the OS returns-from-trap,
which restores B’s registers and starts running it.
I have a disagreement with the second paragraph.
Process A is running and then is interrupted by the timer interrupt. The hardware saves its registers (onto its kernel stack) and enters the kernel (switching to kernel mode).
I am not aware of a system that saves all the registers on the kernel stack on an interrupt. Program Counter, Processor Status, and Stack Pointer (assuming the hardware does not have a separate Kernel Mode Stack Pointer). Normally, processors save the minimum necessary on the kernel stack after an interrupt. The interrupt handler will then save any additional registers it wants to use and restores them before exit. The processor's RETURN FROM INTERRUPT or EXCEPTION instruction then restores the registers automatically stored by the interrupt.
That description assumes no change in the process.
If the interrupt handle decides to change the process, it saves the current register state (the "process context" --most processors have a single instruction for this. In Intel land you might have to use multiple instructions) then executes another instruction to load the process context of the new process.
To answer your heading question "What is a kernel stack used for?", it is used whenever the processor is in Kernel mode. If the kernel did not have a stack protected from user access, the integrity of the system could be compromised. The kernel stack tends to be very small.
To answer you second question, "What exactly is the point of saving the registers to both the kernel stack and the process structure and why the need for both?"
They serve two different purpose. The saved registers on the kernel stack are used to get out of kernel mode. The context process block saves the entire register set in order to change processes.
I think your misunderstanding comes from the wording of your source that suggests all registers are stored on the stack when entering kernel mode, rather than just the minimum number of registers needed to make the kernel mode switch. The system will usually only save what it needs to get back to user mode (and may use that same information to return back to the original process in another context switch, depending upon the system). The change in process context saves all the registers.
Edits to answer additional questions:
If the interrupt handler needs to use register not saved by the CPU automatically by the interrupt, it pushes them on the kernel stack on entry and pops them off on exit. The interrupt handler has to explicitly save and restore any [general] registers it uses. The Process Context Block does not get touched for this.
The Process Context Block only gets altered as part an actual context switch.
Example:
Lets assume we have a processor with a program counter, stack pointer, processor status and 16 general registers (I know no such system really exists) and that the same SP is used for all modes.
Interrupt occurs.
The hardware pushes the PC, SP, and PS on to the stack, loads the SP with the address of the kernel mode stack and the PC from the interrupt handler (from the processor's dispatch table).
Interrupt handler gets called.
The writer of the handler decides he is going to us R0-R3. So the first lines of the handler have:
Push R0 ; on to the kernel mode stack
Push R1
Push R2
Push R3
The interrupt handler does whatever it wants to do.
Cleanup
The writer of the interrupt handler needs to do:
Pop R3
Pop R2
Pop R1
Pop R0
REI ; Whatever the system's return from interrupt or exception instruction is.
Hardware Takes over
Restores the PS, PC, and SP from the kernel mode stack, then resumes executing where it was before the interrupt.
I've made up my own processor for simplification. Some processors have lengthy instructions that are interruptable (e.g. block character moves). Such instructions often use registers to maintain their context. On such a system, the processor would have to automatically save any registers is uses to maintain context within the instruction.
An interrupt handler does not muck with the process context block unless it is changing processes.
It's difficult to speak in general terms about how an OS works 'under the hood', because it's dependent on how the hardware works. Also, terminology isn't highly standardised.
My guess is that by the 'Process structure entry' the writer means what is commonly known as the 'context' of the process, and that contains a copy of every register. It's not possible for the interrupt code to immediately save registers to this structure, because it would have to use (and therefore modify) registers in doing so. That's why it has to save a few registers, enough so that it can do the job, somewhere immediately available, e.g. where the stack pointer is pointing, which the writer calls the 'kernel stack'.
Depending on the architecture, this could be a single stack or separate ones per process.

Which Cortex-M3 interrupts can I use for general purpose work?

I'd have some code that needs to be run as the result of a particular interrupt going off.
I don't want to execute it in the context of the interrupt itself but I also don't want it to execute in thread mode.
I would like to run it at a priority that's lower than the high level interrupt that precipitated its running but also a priority that higher than thread level (and some other interrupts as well).
I think I need to use one of the other interrupt handlers.
Which ones are the best to use and what the best way to invoke them?
At the moment I'm planning on just using the interrupt handlers for some peripherals that I'm not using and invoking them by setting bits directly through the NVIC but I was hoping there's a better, more official way.
Thanks,
ARM Cortex supports a very special kind of exception called PendSV. It seems that you could use this exception exactly to do your work. Virtually all preemptive RTOSes for ARM Cortex use PendSV to implement the context switch.
To make it work, you need to prioritize PendSV low (write 0xFF to the PRI_14 register in the NVIC). You should also prioritize all IRQs above the PendSV (write lower numbers in the respective priority registers in the NVIC). When you are ready to process the whole message, trigger the PendSV from the high-priority ISR:
*((uint32_t volatile *)0xE000ED04) = 0x10000000; // trigger PendSV
The ARM Cortex CPU will then finish your ISR and all other ISRs that possibly were preempted by it, and eventually it will tail-chain to the PendSV exception. This is where your code for parsing the message should be.
Please note that PendSV could be preempted by other ISRs. This is all fine, but you need to obviously remember to protect all shared resources by a critical section of code (briefly disabling and enabling interrupts). In ARM Cortex, you disable interrupts by executing __asm("cpsid i") and you enable interrupts by __asm("cpsie i"). (Most C compilers provide built-in intrinsic functions or macros for this purpose.)
Are you using an RTOS? Generally this type of thing would be handled by having a high priority thread that gets signaled to do some work by the interrupt.
If you're not using an RTOS, you only have a few tasks, and the work being kicked off by the interrupt isn't too resource intensive, it might be simplest having your high priority work done in the context of the interrupt handler. If those conditions don't hold, then implementing what you're talking about would be the start of a basic multitasking OS itself. That can be an interesting project in its own right, but if you're looking to just get work done, you might want to consider a simple RTOS.
Since you mentioned some specifics about the work you're doing, here's an overview of how I've handled a similar problem in the past:
For handling received data over a UART one method that I've used when dealing with a simpler system that doesn't have full support for tasking (ie., the tasks are round-robined i na simple while loop) is to have a shared queue for data that's received from the UART. When a UART interrupt fires, the data is read from the UART's RDR (Receive Data Register) and placed in the queue. The trick to deal with this in such a way that the queue pointers aren't corrupted is to carefully make the queue pointers volatile, and make certain that only the interrupt handler modifies the tail pointer and that only the 'foreground' task that's reading data off the queue modified the head pointer. A high-level overview:
producer (the UART interrupt handler):
read queue.head and queue.tail into locals;
increment the local tail pointer (not the actual queue.tail pointer). Wrap it to the start of the queue buffer if you've incremented past the end of the queue's buffer.
compare local.tail and local.head - if they're equal, the queue is full, and you'll have to do whatever error handing is appropriate.
otherwise you can write the new data to where local.tail points
only now can you set queue.tail == local.tail
return from the interrupt (or handle other UART related tasks, if appropriate, like reading from a transmit queue)
consumer (the foreground 'task')
read queue.head and queue.tail into locals;
if local.head == local.tail the queue is empty; return to let the next task do some work
read the byte pointed to by local.head
increment local.head and wrap it if necessary;
set queue.head = local.head
goto step 1
Make sure that queue.head and queue.tail are volatile (or write these bits in assembly) to make sure there are no sequencing issues.
Now just make sure that your UART received data queue is large enough that it'll hold all the bytes that could be received before the foreground task gets a chance to run. The foreground task needs to pull the data off the queue into it's own buffers to build up the messages to give to the 'message processor' task.
What you are asking for is pretty straightforward on the Cortex-M3. You need to enable the STIR register so you can trigger the low priority ISR with software. When the high-priority ISR gets done with the critical stuff, it just triggers the low priority interrupt and exits. The NVIC will then tail-chain to the low-priority handler, if there is nothing more important going on.
The "more official way" or rather the conventional method is to use a priority based preemptive multi-tasking scheduler and the 'deferred interrupt handler' pattern.
Check your processor documentation. Some processors will interrupt if you write the bit that you normally have to clear inside the interrupt. I am presently using a SiLabs c8051F344 and in the spec sheet section 9.3.1:
"Software can simulate an interrupt by setting any interrupt-pending flag to logic 1. If interrupts are enabled for the flag, an interrupt request will be generated and the CPU will vector to the ISR address associated with the interrupt-pending flag."