What is the difference between using "EXTI_IRQHandler" and "EXTI_Callback"? - c

I am using HAL library for my project with STM32 microcontroller.
In the sample code provided by STM, they use HAL_GPIO_EXTI_Callback for a push button interrupt. However, I learned in class that we need to use the IRQHandler to handle the interrupt.
So my question is when we use HAL_GPIO_EXTI_Callback and HAL_GPIO_EXTI_IRQHandler to handle interrupt?

In ST's example projects, there are several function calls for a single interrupt:
the interrupt handler itself is called EXTI15_10_Handler. It is the function whose address is specified in the vector table. It is the generic handler for the interrupt line EXTI15_10 and by default it is "routed" to a default function doing nothing. As it is a weak symbol you can redefine it as you want.
if you are using EXTI15_10 interrupt line with standard GPIOs, EXTI15_10_Handler should call HAL_GPIO_EXTI_IRQHandler. This is a function provided by the HAL.
the latter function is clearing the IT flag and then calls HAL_GPIO_EXTI_Callback, which is also a weak function that is doing nothing by default. This is the function that you need to implement to process your GPIO.

Related

tx_semaphore inside a Interrupt

I want to read out RS232 data periodically. I have created an interrupt for this purpose. However, my RS232 functions need semaphores. I found out that I cannot execute a TX(Thread X) function in the interrupt. What do I have to do to make my TX function work inside the interrupt?
If your RTOS provides a way to do it, then use that. If not, then here's some other options:
Disable the specific interrupt from the background program during variable access.
In case interrupts aren't interruptible on your MCU, you could implement a "poor man's mutex" described here: https://electronics.stackexchange.com/questions/409545/using-volatile-in-embedded-c-development/409570#409570
Use inline assembler and ensure reads/writes are done in a single instruction.
There's also a very bad idea/last resort, and that is to toggle the global interrupt mask.
First, make sure you are calling _tx_thread_context_save and _tx_thread_context_restore at the beginning and end of your ISR, respectively. See here for more information: https://learn.microsoft.com/en-us/azure/rtos/threadx/chapter3#isr-template
Second, you cannot create a semaphore in an interrupt, so make sure you create it elsewhere.

How can I determin if execution takes place in thread mode or if an exception is active? (ARMv7-A architecture)

I am using FreeRTOS on an ARM Cortex A9 CPU und I'm desperately trying to find out if it is possible to determin if the processor is executing a normal thread or an interrupt service routine. It is implemented in V7-a architecture.
I found some promising reference hinting the ICSR register (-> VECTACTIVE bits), but this only exist in the cortex M family. Is there a comparable register in the A family as well? I tried to read out the processor modes in the current processor status register (CPSR), but when read during an ISR I saw that the mode bits indicate supervisor mode rather than IRQ or FIQ mode.
Looks a lot like there is no way to determine in which state the processor is, but I wanted to ask anyway, maybe I missed something...
The processor has a pl390 General Interrupt Controller. Maybe it is possible to determine the if an interrupt has been triggered by reading some of it's registers?
If anybody can give me a clue I would be very greatfull!
Edit1:
The IRQ Handler of FreeRTOS switches the processor to Superviser mode:
And subsequently switches back to system mode:
Can I just check if the processor is in supervisor mode and assume that this means that the execution takes place in an ISR, or are there other situations where the kernel may switches to supervisor mode, without being in an ISR?
Edit2:
On request I'll add an overal background description of the solution that I want to achieve in the first place, by solving the problem of knowing the current execution context.
I'm writing a set of libraries for the CortexA9 and FreeRTOS that will access periphery. Amongst others I want to implement a library for the available HW timer from the processor's periphery.
In order to secure the access to the HW and to avoid multiple tasks trying to access the HW resource simultaneously I added Mutex Semaphores to the timer library implementation. The first thing the lib function does on call is to try to gain the Mutex. If it fails the function returns an error, otherwise it continouses its execution.
Lets focus on the function that starts the timer:
static ret_val_e TmrStart(tmr_ctrl_t * pCtrl)
{
ret_val_e retVal = RET_ERR_DEF;
BaseType_t retVal_os = pdFAIL;
XTtcPs * pHwTmrInstance = (XTtcPs *) pCtrl->pHwTmrInstance;
//Check status of driver
if(pCtrl == NULL)
{
return RET_ERR_TMR_CTRL_REF;
}else if(!pCtrl->bInitialized )
{
return RET_ERR_TMR_UNINITIALIZED;
}else
{
retVal_os = xSemaphoreTake(pCtrl->osSemMux_Tmr, INSTANCE_BUSY_ACCESS_DELAY_TICKS);
if(retVal_os != pdPASS)
{
return RET_ERR_OS_SEM_MUX;
}
}
//This function starts the timer
XTtcPs_Start(pHwTmrInstance);
(...)
Sometimes it can be helpful to start the timer directly inside an ISR. The problem that appears is that while the rest of function would support it, the SemaphoreTake() call MUST be changed to SemaphoreTakeFromISR() - moreover no wait ticks are supported when called from ISR in order to avoid a blocking ISR.
In order to achieve code that is suitable for both execution modes (thread mode and IRQ mode) we would need to change the function to first check the execution state and based on that invokes either SemaphoreTake() or SemaphoreTakeFromISR() before proceeding to access the HW.
That's the context of my question. As mentioned in the comments I do not want to implement this by adding a parameter that must be supplied by the user on every call which tells the function if it's been called from a thread or an ISR, as I want to keep the API as slim as possible.
I could take FreeRTOS approch and implement a copy of the TmrStart() function with the name TmrStartFromISR() which contains the the ISR specific calls to FreeRTOS's system resources. But I rather avoid that either as duplicating all my functions makes the code overall harder to maintain.
So determining the execution state by reading out some processor registers would be the only way that I can think of. But apparently the A9 does not supply this information easily unfortunately, unlike the M3 for example.
Another approch that just came to my mind could be to set a global variable in the assembler code of FreeRTOS that handles exeptions. In the portSAVE_CONTEXT it could be set and in the portRESTORE_CONTEXT it could be reset.
The downside of this solution is that the library then would not work with the official A9 port of FreeRTOS which does not sound good either. Moreover you could get problems with race conditions if the variable is changed right after it has been checked by the lib function, but I guess this would also be a problem when reading the state from a processor registers directly... Probably one would need to enclose this check in a critical section that prevents interrupts for a short period of time.
If somebody sees some other solutions that I did not think of please do not hesitate to bring them up.
Also please feel free to discuss the solutions I brought up so far.
I'd just like to find the best way to do it.
Thanks!
On a Cortex-A processor, when an interrupt handler is triggered, the processor enters IRQ mode, with interrupts disabled. This is reflected in the state field of CPSR. IRQ mode is not suitable to receive nested interrupts, because if a second interrupt happened, the return address for the first interrupt would be overwritten. So, if an interrupt handler ever needs to re-enable interrupts, it must switch to supervisor mode first.
Generally, one of the first thing that an operating system's interrupt handler does is to switch to supervisor mode. By the time the code reaches a particular driver, the processor is in supervisor mode. So the behavior you're observing is perfectly normal.
A FreeRTOS interrupt handler is a C function. It runs with interrupts enabled, in supervisor mode. If you want to know whether your code is running in the context of an interrupt handler, never call the interrupt handler function directly, and when it calls auxiliary functions that care, pass a variable that indicates who the caller is.
void code_that_wants_to_know_who_called_it(int context) {
if (context != 0)
// called from an interrupt handler
else
// called from outside an interrupt handler
}
void my_handler1(void) {
code_that_wants_to_know_who_called_it(1);
}
void my_handler2(void) {
code_that_wants_to_know_who_called_it(1);
}
int main(void) {
Install_Interrupt(EVENT1, my_handler1);
Install_Interrupt(EVENT2, my_handler1);
code_that_wants_to_know_who_called_it(0);
}

FreeRTOS Systick Handler

I'm studying the FreeRTOS scheduler (port.c) and have a question about Systick handler. I understand xPortSysTickHandler() is supposed to be called at RTOS ticks, but I don't see where it gets specified by saying xPortSysTickHandler() is the Systick timer interrupt callback function.
Especially, I didn't see that in vPortSetupTimerInterrupt(), which seems a bit strange to me since this function does configure, such as load register value, of the timer.
Does it gets specified as the callback somewhere else? Or is there something I'm missing?
Thanks!
It is installed directly into the interrupt vector table. If the vector table uses CMSIS names for the handlers then you can map the CMSIS name to the name of the FreeRTOS systick handler in FreeRTOSConfig.h, as per the FAQ - see the red "special note to ARM Cortex-M users" here: https://www.freertos.org/FAQHelp.html

What is the use of callback function in peripheral driver?

I am reading a book on writing embedded system peripheral drivers and the author wrote a C callback function which i really don't understand and want to know the use of it, is it related to interrupts handling?
The function prototype is as following:
void Spi_CallbackRegister(SpiCallback_t Function, TYPE (*CallbackFunction)(type));
Short Answer: Callback function are function pointers with which you invoke them, when a specific event occurs.
Let us say you have an IO device like ethernet (MAC) device. Driver for such device will always be waiting for an events to occur, these events are either hardware or software interrupts, example:
A new packet has arrived.
A packet is going to dispatch.
Initiate packet transfer from device FIFO to host memory (DMA).
A protocol state has changed/etc.
To handle various interrupt(s) type you need a specific function for each of them, these functions are called Interrupt Service Routine(ISR) or Interrupt handler or a callback function. When an event is mapped to a function, it stores its pointer and thats why the term callback the function.

Difference between request_irq and __interrupt

From what I read both are used to register interrupt handlers. I saw lots of request_irq calls in kernel code but not even one __interrupt call. Is __interrupt some way to register a handler from user space?
request_irq is essentially a wrapper call to request_threaded_irq, which allocates the IRQ resources and enables the IRQ. That's paraphrased from the comment block in kernel/irq/manage.c, Line #1239.
Basically, you want to use request_irq if you need to setup interrupt handling for a device of some kind. Make sure that whatever subsystem you are working in doesn't already provide a wrapper for request_irq, too. I.e., if you are working on a device driver, consider using the devm_* family of calls to auto-manage the minutiae, like freeing unused variables and such. See devm_request_threaded_irq at Line #29 in kernel/irq/devres.c for a better explanation. Its equivalent call (and the one you would most likely use) is devm_request_irq.
As far as I remember __interrupt() is used to declare a function as ISR in userspace. I am not sure where I have this from but I'll come back to you as soon as I found the spot.

Resources