[En-Nut-Discussion] Fwd: Not fixed!!!: Re: confirmed!!! Re: NutOS 4.4.0 on ARM7: possibly bug in NutEnterCritical / NutExitCritical
duane ellis
ethernut at duaneellis.com
Sat Feb 23 02:35:52 CET 2008
Alain M. wrote:
> Saving interrupt state is not allways an academic question, it is
> important if-and-only-if you don't know if you are running with
> interrupts enabled or not. As has been said, in ISR it is not nassary to
> call ENTER_CRITICAL_SECTION and there is nothing to restore.
You are not considering the case of nested multiple-priority interrupts
common on all ARM cpus.
If Ethernut does not support this, then you are correct.
If Ethernut will some day support this, it will return and bite you.
During a nested IRQ, it would be valid for the CPU irqs to initially be
disabled.
During the course of the IRQ - let the IRQ handler decide if it should
re-enable IRQs
so that other - high priority IRQs can pre-empt.
> and if you
> *know* that IRQ is disabled (true most of the time) you don't need to
> save anything, simple disable()/enable() functions are *much better*.
>
You have the wrong idea, you should have "disable()/restore()".
Consider the following example - be it anywhere, does not need to be
inside an IRQ.
I call enter_critical() - aka: disable_IRQ()
I do stuff.
I call library function to manage my FIFO que, or Linked List.
Library function is GENERIC.
Library calls enter_critical() - aka: disable_IRQ()
Library performs the dirty work for me.
Library calls exit_critical() - aka: enable_IRQ() <--
Bugs start here
Library returns.
I do not know IRQs are enabled.
I do "other critical stuff" - I thought IRQs are disabled.
I call exit_critical() - aka: enable_IRQ()
> B) write a state-saving macro. This is complicated as can be seen in the
> long thread about this topic.
>
This is the best solution. Want proof?
Look at how Linux does this.
http://www.promethos.org/lxr/http/ident?v=2.6.14;i=local_irq_save
Those guys are smart. Learn from them.
They also pass a "cpu_irq_t" parameter to the save/restore macro/functions.
For ARM - disable_irq_CPU( save_here )
In ARM/GCC, it is a 3 opcode-inline-assembly function.
In THUMB/GCC - it is a thumb-arm subroutine call to a 4
-arm-opcode- function.
(1) move CPSR to register.
(2) OR bit into register.
(3) copy register to CPSR
(4) for thumb - a RETURN instruction.
For ARM - restore_irq_CPU( old_value )
In ARM/GCC is a 1 opcode-inline-assembly function.
In THUMB/GCC - it is a thumb-arm subroutine to a a 2
arm-opcode-functions.
(1) Move "old-value" to CPSR
(2) for thumb - a RETURN instruction.
-Duane.
More information about the En-Nut-Discussion
mailing list