Can I use free_irq in a software interrupt context? - c

The kernel documentation says about free_irq the following :
This function must not be called from interrupt context.
Does it include software interrupts?
How can I free an IRQ in a software IRQ function?
Thanks for your help,

Yes, that rule includes softirq context. The fact that you think you need to call free_irq() from softirq context is an indication that your design is a bit out of the ordinary -- in normal cases, free_irq() is used when a device being shut down, which is almost always from process context.
However if you really need to do it, the thing to do would be to defer it to process context via schedule_work() or some similar workqueue function. Of course you can't wait in your softirq for that deferred work to complete, so you'll have to defer any other work that comes after freeing the IRQ also.
It might be possible to give a better answer if you gave a bit more information about why you're trying to call free_irq() from interrupt context.

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.

pvPortMalloc and vPortFree Usage (freeRTOS Heap4.c) in Baremetal STM32F4x

I have had a good experience in programming bare metal stm32f4x; however, i tried to shift my code to freeRTOS and for that i first wanted to see if i can use Heap4.c for memory allocation instead of standard C malloc and free calls to better manage the memory etc.
However, what I observed is that using these calls disables my interrupts and never turns them back on. Hence, anything which makes use of interrupts is not working; everything else, which has nothing to do with interrupts is working ok. Not even Systick timer interrupt handler is being triggered.
So, the question is that, how can we make use of pvPortMalloc and vPortFree with bare metal code considering that all other peripherals do make use of their interrupts and SysTick is basically used for simple time delays etc. When using these calls, I could not see any prints happening inside systick as there was no systick handler being called.
Here I would like to point out that I am not calling pvPortMalloc or vPortFree in any interrupt context at all. So, that is totally safe and nothing to worry about that.
I have read through few discussions and if i understand correctly, then any call to FreeRTOS scheduler to suspend tasks etc does not impact as there will be no tasks at all. So, I expect this heap4.c port to work just fine with bare metal as well as long as we stay away from using them within ISR context; but apparently it just disables interrupts and seem to never turn them back on.
I hope to have the opinion of experts here on using pvPortMalloc and vPortFree in bare metal instead of using freeRTOS.
Best regards,
Junaid
I think if you replace the xTaskSuspendAll() and xTaskResumeAll() to simply disable / enable interrupts it should work fine. In fact if your interrupts are not using the allocated memory you might not even need to do this, you could simply comment them out. Suspend and Resume are quite complex functions that can attempt to yield control to other tasks if required.
I suspect the reason interrupts are not getting re-enabled is that either taskEXIT_CRITICAL() is not defined correctly (portENABLE_INTERRUPTS) or the uxCriticalNesting is greater than one when truing to re-enable interrupts (enter critical called more times than exit critical).
However you will probably find the standard malloc and free are better if you are not using FreeRTOS.

Why does the Linux kernel enable interrupts in preempt_schedule_irq?

I'm reading Linux source code to learn how scheduling works. I learn that in a preemptible kernel (CONFIG_PREEMPT is set), there is a chance for preemption after returning to kernel-space from interrupt handler by calling preempt_schedule_irq.
However, I also find the following code snippet in preempt_schedule_irq
do {
preempt_disable();
local_irq_enable(); //why enable interrupt here?
__schedule(true); //interrupt would be disabled inside it
local_irq_disable();
sched_preempt_enable_no_resched();
} while (need_resched());
There is a local_irq_enable() call inside it and this kind of confuses me. Why do we need to enable interrupt here since at the start of __schedule it would disabled again?.
My humble guess is that this gives a chance to processes with higher priority to be scheduled first. However, it doesn't make sense because the preemption is already disabled in preempt_schedule_irq, even if there is an interrupt, there would not be a preemption reschedule.
So what on earth is the point in preempting the scheduling procedure here? I think I must have missed something but I don't figure out.
Short answer: Because interrupts should be enabled as much as possible, only disabled to protect minimal critical sections. Arbitrarily extending the disabling beyond your critical section into non-critical sections of functions you're calling because you're assuming that at some point that function will disable them, is bad design.
Why doesn't __schedule() disable interrupts as it's very first instruction? Because it doesn't need to, the code at the start of __schedule() isn't a critical section so explicitly disabling interrupts before it would be a waste. The writer of __schedule() went out of their way to maximize the time when interrupts can be handled, why ignore that opportunity by not enabling interrupts?
Also, you have no guarantees about what __schedule() might do in the future. Since the start of __schedule() isn't a critical section, you have no guarantees that more stuff won't be added before the interrupt disabling. Remember, the person who's going to be making changes to __schedule() shouldn't have to consider that one of the callers decided to leave their interrupts disabled relying on the fact that __schedule() turns them off pretty soon anyway. __schedule() has no regard at all about interrupt status when it's called.
You should disable/enable interrupts around the critical sections of your code, not rely on the inner mechanics of some other function you're calling and hoping it doesn't change.
If you look through the history of the scheduler, you'll see that the code preceding the interrupt disabling has changed over time. Digging through the commits you see that the "sti" to enable interrupts was present since the very first commit to implement preemption in the kernel going back all the way to 2.5: https://github.com/schwabe/tglx-history/blob/ec332cd30cf1ccde914a87330ff66744414c8d24/arch/i386/kernel/entry.S#L235

Preemption in FreeRTOS

I am starting to use FreeRTOS and I would like a interrupt to preempt whatever task was about to run and run the task I need to run critically.
Is there a way to do this in FreeRTOS? (Is this achieved through task priority?)
NO! Both the above answers are DANGEROUS.
Do NOT use taskENTER_CRITICAL() or taskEXIT_CRITICAL() inside an ISR - it is unusual to need a critical section in an ISR but if you do then use taskENTER_CRITICAL_FROM_ISR()/taskEXIT_CRITICAL_FROM_ISR(). (possible the AVR32 port is an exception to that rule?)
Do NOT use xTaskResumeFromISR() to synchronise a task with an interrupt. The link already posted to the documentation for that function even says this.
If my understanding of your question is correct you want the ability to have an interrupt unblock a task, and then if that task is the highest priority task in that is able to run, have the interrupt return directly to the unblocked task. If my understanding is right then there is an example of how to do that in an efficient way on the following page: http://www.freertos.org/RTOS_Task_Notification_As_Counting_Semaphore.html
The short answer would be: Yes, this is achieved through task priority.
The FreeRTOS kernel will consider swapping in any task in ready-state after an ISR has completed so it would preempt the current running task if a higher priority task is now ready.
It should be mentioned that this is really only true if the handler is called through FreeRTOS. On a Cortex-A processor there is a common IRQ entry-point in the IRQ or FIQ exception handler which is most likely handled by FreeRTOS or otherwise by an IRQ dispatcher which is easily wrapped by FreeRTOS, usually by a function in the port-layer called vApplicationIRQHandler().
On a Cortex-M this is not necessarily the case as the vector is usually manipulated by the vendor's MCU API. On a Cortex-M I'd safe-guard against this using portYIELD_FROM_ISR() in the ISR which should be implemented to provide the kernel with an opportunity to perform a context switch.
You can use xTaskResumeFromISR to do this.
There is a number of conditions to be met for the yielded task not to be interrupted by other tasks (like it's priority must be high enough) and a number of other conditions to be met to ensure that no interrupt can go un-serviced (like the yielded task must guarantee to be done before the next interrupt)
1. enable preemption:
This is very simple to do.
All the configuration options of FreeRTOS are under "FreeRTOSConfig.h"
#define configUSE_PREEMPTION 1
You can set this to 1 to use the preemptive RTOS scheduler, or 0 to use the cooperative RTOS scheduler.
Check this link for more info
2. Use critical section inside ISR
void taskENTER_CRITICAL( void );
//action
void taskEXIT_CRITICAL( void );
RTOS wont do anythis extra inside this critical part
ref: here

Capture hrtimer interrupts with linux kernel module .. possible?

I would like to be able to 'capture' an hrtimer interrupt with a linux kernel module and replay the interrupt at a later period in time. Any thoughts on how to go about doing this?
Use case: A program that calls sleep(1). My module will grab the hrtimer interrupt when it fires after 1 second, wait for 'x' amount of time, then re-fire the interrupt, waking the process.
Note: I do not want to hook the sleep system call.
Thanks!
Quite honestly, writing a Linux kernel module just to modify the behavior of sleep() for a single application sounds like overkill.
For most cases you should be able to use a preloadable shared object to intercept/override the sleep() function family with your own implementations. The application will call your implementation and your code may then call the real function with a modified parameter list.
This method is much simpler and less intrusive than anything involving kernel programming, although it will not work if your application is statically linked or if it uses direct system calls instead of library functions.

Resources