From 0b172387146e2394f4bf67b6c7de77756e4d5575 Mon Sep 17 00:00:00 2001 From: raiden00pl Date: Sun, 5 Nov 2023 10:15:43 +0100 Subject: [PATCH] Documentation: migrate "Per-Thread Interrupt Controls" from wiki link: https://cwiki.apache.org/confluence/display/NUTTX/Per-Thread+Interrupt+Controls --- Documentation/implementation/index.rst | 1 + .../implementation/interrupt_controls.rst | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 Documentation/implementation/interrupt_controls.rst diff --git a/Documentation/implementation/index.rst b/Documentation/implementation/index.rst index f1aac1feb4c..35442d724e6 100644 --- a/Documentation/implementation/index.rst +++ b/Documentation/implementation/index.rst @@ -8,3 +8,4 @@ Implementation Details processes_vs_tasks.rst critical_sections.rst + interrupt_controls.rst diff --git a/Documentation/implementation/interrupt_controls.rst b/Documentation/implementation/interrupt_controls.rst new file mode 100644 index 00000000000..0ec92a771d0 --- /dev/null +++ b/Documentation/implementation/interrupt_controls.rst @@ -0,0 +1,45 @@ +============================= +Per-Thread Interrupt Controls +============================= + +Using NuttX, you will find that the interrupts enabled/disabled state is not a +global property. You can not just turn interrupts off and on for all tasks. +Rather, enabling and disabling interrupts effects only while the single task +that is controlling the interrupts runs. Consider the following sequence: + +.. code-block:: C + + irqstate_t flags; + + flags = irqsave(); /* Disable interrupts */ + sleep(5); /* Sleep for 5 seconds */ + irqrestore(flags); /* Re-enable interrupts */ + +What happens while the task sleeps? Does that mean that interrupts will be +disabled for five seconds? No, interrupts will (probably) be re-enabled while +the task is sleeping. How does this work? + +It is really very simple. Each time a context switches occurs, a set of +registers are saved for the task that is being suspended. Then those registers +are restored from the previously saved registers for a next task that will run. +This is why we often describe a context switch as just setjmp/longjmp on steroids: +A context switch works just like setjmp (save a set of registers) and longjmp +(restore a set of registers), except that more registers are saved and restored. + + +For the the ARMv7-M, as an example, you can see the set of registers that are +stored in ``arch/arm/include/armv7-m/irq.h`` + +Among those registers are saved and restore are the register(s) that determine if +interrupts are enable or not. For the ARMv7-M family that is either the ``PRIMASK`` +register or the ``BASEPRI`` registers. So if a task disables interrupts then suspends, +the current value of ``PRIMASK``/``BASEPRI`` register is saved and replaced with the +stored value of the ``PRIMASK``/``BASEPRI`` register for the next task that will run, +thus re-enabling interrupts while the rist task is suspended. + +So interrupt enabled/disable is a per-thread property, not a global property. +If you have been working with bare metal systems for a long time, this might seem +foreign to you. + +By the way, locking the scheduler via ``sched_lock()`` behaves in this same way +(but the mechanism is a little different).