RFC: Extension to External Interrupt API


Chettimada, Vinayak Kariappa
 

Hi,

Welcome your valuable comments on the proposed extension to External Interrupt API.

*irq_enable_keep*
https://gerrit.zephyrproject.org/r/#/c/4676/1
https://gerrit.zephyrproject.org/r/#/c/4677/1

*irq_is_enabled*
https://gerrit.zephyrproject.org/r/#/c/4678/1
https://gerrit.zephyrproject.org/r/#/c/4679/1

*irq_pending_set*
https://gerrit.zephyrproject.org/r/#/c/4662/3
https://gerrit.zephyrproject.org/r/#/c/4663/3

*irq_pending_clear*
https://gerrit.zephyrproject.org/r/#/c/4680/1
https://gerrit.zephyrproject.org/r/#/c/4681/1

*irq_is_priority_equal*
https://gerrit.zephyrproject.org/r/#/c/4682/2
https://gerrit.zephyrproject.org/r/#/c/4683/2

I have had a barebone execution architecture in the contributed BLE controller code,
consisting of thread mode, ISR and work on ARM architectures. 'work' is an offloaded
function to another or same ISR priority (usually to a s/w interrupt).

To further a close integration of the controller, the above extension to external
interrupt APIs is desired.

Thanks in advance.

Regards,
Vinayak


Andy Ross
 

Vinayak Kariappa Chettimada wrote:
Welcome your valuable comments on the proposed extension to External
Interrupt API.
As has been mentioned in gerrit, there is worry about the portability
of a lot of this, which is a mostly 1:1 transcription of an ARM
feature as I understand it.

In particular irq_pending_set() seems to be pretty non-standard. Not
all architectures have a visible system-wide interrupt latch (x86
does, but only for external hardware interrupts), and AFAIK only ARM
allows it to be written (x86 can synchronously trigger an interrupt,
which isn't quite the same thing).

Do you have ideas on how this would be implemented for the other
architectures in Zephyr? If we can't have it as a general API, I'm
not really sure I see the value for having it in-tree. All of what
you're doing can (and, I gather, is) doable for specific hardware on a
per-app basis anyway, right?

Honestly it seems like what you have with the BLE work is tied very
closely to your hardware environment, and might need to be generalized
a bit. Can you explain what exactly you need from these features that
you can't get with Zephyr in other ways now? I mean, if your goal
with irq_pending_set() is to just have another interrupt handler
called after the current one completes, can't you implement that with
a function call at the bottom of the ISR? :)

Andy


Benjamin Walsh <benjamin.walsh@...>
 

On Fri, Sep 16, 2016 at 08:38:35AM -0700, Andy Ross wrote:
Vinayak Kariappa Chettimada wrote:
Welcome your valuable comments on the proposed extension to External
Interrupt API.
As has been mentioned in gerrit, there is worry about the portability
of a lot of this, which is a mostly 1:1 transcription of an ARM
feature as I understand it.

In particular irq_pending_set() seems to be pretty non-standard. Not
all architectures have a visible system-wide interrupt latch (x86
does, but only for external hardware interrupts), and AFAIK only ARM
allows it to be written (x86 can synchronously trigger an interrupt,
which isn't quite the same thing).

Do you have ideas on how this would be implemented for the other
architectures in Zephyr? If we can't have it as a general API, I'm
not really sure I see the value for having it in-tree. All of what
you're doing can (and, I gather, is) doable for specific hardware on a
per-app basis anyway, right?

Honestly it seems like what you have with the BLE work is tied very
closely to your hardware environment, and might need to be generalized
a bit. Can you explain what exactly you need from these features that
you can't get with Zephyr in other ways now? I mean, if your goal
with irq_pending_set() is to just have another interrupt handler
called after the current one completes, can't you implement that with
a function call at the bottom of the ISR? :)
IIUC, he wants to queue work in another interrupt of the same priority,
serve the other interrupts of same priority that are already pending,
and then only execute the work he's queued. Kinda some sort of
cooperative yielding, but at interrupt level. This is exactly how fibers
(cooperative threads) are scheduled in Zephyr BTW. What he's not getting
if was to queue work to fibers instead, is that when his delayed work
would run would be depending on what work is already being done in a
fiber when he handles his interrupt and what other interrupts of lower
priority might be pending.


Andy Ross
 

Benjamin Walsh wrote:
IIUC, he wants to queue work in another interrupt of the same priority,
serve the other interrupts of same priority that are already pending,
and then only execute the work he's queued. Kinda some sort of
cooperative yielding, but at interrupt level. This is exactly how fibers
(cooperative threads) are scheduled in Zephyr BTW. What he's not getting
if was to queue work to fibers instead, is that when his delayed work
would run would be depending on what work is already being done in a
fiber when he handles his interrupt and what other interrupts of lower
priority might be pending.
Does that work? Are pended ARM interrupts really "queued" like that?
If you have multiple pending interrupts of the same priority I'd have
to believe the order of delivery would be arbitrary and
hardware-dependent (i.e. whatever fixed precedence the hardware
designers picked in a mux somewhere).

If that works, then I agree this sounds cool. But my suspicion is
that the only promise you get with this irq_pend_set() implementation
is that the IRQ will run at its fixed priority sometime after your
call completes and before ISRs of lower priority or user code get to
run. And if *that's* true then you should be able to just test for
the pending state of those other known IRQs* at the end of your
function and call the one of your choice to get the same
behavior. No?

Andy

* Not ones higher than the current handler, which by definition aren't
pending. And not ones lower than the target which wouldn't run
anyway. That's going to be a small, tractable list. And
importantly one accessible to application code in Zephyr without
exposing ARM's writable interrupt pending bits.


Benjamin Walsh <benjamin.walsh@...>
 

On Fri, Sep 16, 2016 at 09:06:13AM -0700, Andy Ross wrote:
Benjamin Walsh wrote:
IIUC, he wants to queue work in another interrupt of the same priority,
serve the other interrupts of same priority that are already pending,
and then only execute the work he's queued. Kinda some sort of
cooperative yielding, but at interrupt level. This is exactly how fibers
(cooperative threads) are scheduled in Zephyr BTW. What he's not getting
if was to queue work to fibers instead, is that when his delayed work
would run would be depending on what work is already being done in a
fiber when he handles his interrupt and what other interrupts of lower
priority might be pending.
Does that work? Are pended ARM interrupts really "queued" like that?
If you have multiple pending interrupts of the same priority I'd have
to believe the order of delivery would be arbitrary and
hardware-dependent (i.e. whatever fixed precedence the hardware
designers picked in a mux somewhere).

If that works, then I agree this sounds cool. But my suspicion is
IIRC, you can have sub-priorities on Cortex-M.

Actually:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABHGEAJ.html

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihehdge.html

However, IIRC as well, Zephyr programs the interrupt priorities with 0
subgroups, so that would not work. We could have a config option that
asks for the number of subgroups though, not hard to add.

Isn't x86 able to do that as well, in the IDT in each 16-vector block,
based on the vector position within the block ?

that the only promise you get with this irq_pend_set() implementation
is that the IRQ will run at its fixed priority sometime after your
call completes and before ISRs of lower priority or user code get to
run. And if *that's* true then you should be able to just test for
the pending state of those other known IRQs* at the end of your
function and call the one of your choice to get the same
behavior. No?

Andy

* Not ones higher than the current handler, which by definition aren't
pending. And not ones lower than the target which wouldn't run
anyway. That's going to be a small, tractable list. And
importantly one accessible to application code in Zephyr without
exposing ARM's writable interrupt pending bits.


Boie, Andrew P
 

On Fri, 2016-09-16 at 04:52 +0000, Vinayak Kariappa Chettimada wrote:
Hi,

Welcome your valuable comments on the proposed extension to External
Interrupt API.

*irq_enable_keep*
https://gerrit.zephyrproject.org/r/#/c/4676/1
https://gerrit.zephyrproject.org/r/#/c/4677/1
Fine w/this.

*irq_is_enabled*
https://gerrit.zephyrproject.org/r/#/c/4678/1
https://gerrit.zephyrproject.org/r/#/c/4679/1
OK with this, what's the use-case though?

*irq_pending_set*
https://gerrit.zephyrproject.org/r/#/c/4662/3
https://gerrit.zephyrproject.org/r/#/c/4663/3
NACK. This isn't easily portable to other arches. You brought this up
as a candidate to replace irq_offload(), but irq_offload() only exists
as a debug feature, so that we can run some unit tests in IRQ context.
Advanced stuff like your needs, do this in your application.

*irq_pending_clear*
https://gerrit.zephyrproject.org/r/#/c/4680/1
https://gerrit.zephyrproject.org/r/#/c/4681/1
Fine w/this.

*irq_is_priority_equal*
https://gerrit.zephyrproject.org/r/#/c/4682/2
https://gerrit.zephyrproject.org/r/#/c/4683/2
NACK, for the same reasons as irq_pending_set().

Andrew


Benjamin Walsh <benjamin.walsh@...>
 

On Fri, Sep 16, 2016 at 12:20:56PM -0400, Benjamin Walsh wrote:
On Fri, Sep 16, 2016 at 09:06:13AM -0700, Andy Ross wrote:
Benjamin Walsh wrote:
IIUC, he wants to queue work in another interrupt of the same priority,
serve the other interrupts of same priority that are already pending,
and then only execute the work he's queued. Kinda some sort of
cooperative yielding, but at interrupt level. This is exactly how fibers
(cooperative threads) are scheduled in Zephyr BTW. What he's not getting
if was to queue work to fibers instead, is that when his delayed work
would run would be depending on what work is already being done in a
fiber when he handles his interrupt and what other interrupts of lower
priority might be pending.
Does that work? Are pended ARM interrupts really "queued" like that?
If you have multiple pending interrupts of the same priority I'd have
to believe the order of delivery would be arbitrary and
hardware-dependent (i.e. whatever fixed precedence the hardware
designers picked in a mux somewhere).

If that works, then I agree this sounds cool. But my suspicion is
IIRC, you can have sub-priorities on Cortex-M.

Actually:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABHGEAJ.html

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihehdge.html

However, IIRC as well, Zephyr programs the interrupt priorities with 0
subgroups, so that would not work. We could have a config option that
asks for the number of subgroups though, not hard to add.

Isn't x86 able to do that as well, in the IDT in each 16-vector block,
based on the vector position within the block ?
Nevermind, INTx is a synchronous trap, doesn't work.


Maureen Helm
 

-----Original Message-----
From: Benjamin Walsh [mailto:benjamin.walsh(a)windriver.com]
Sent: Friday, September 16, 2016 11:21 AM
To: Andy Ross <andrew.j.ross(a)intel.com>
Cc: Vinayak Kariappa Chettimada
<vinayak.kariappa.chettimada(a)nordicsemi.no>;
devel(a)lists.zephyrproject.org; Benjamin Walsh
<benjamin.walsh(a)windriver.com>
Subject: [devel] Re: Re: RFC: Extension to External Interrupt API

On Fri, Sep 16, 2016 at 09:06:13AM -0700, Andy Ross wrote:
Benjamin Walsh wrote:
IIUC, he wants to queue work in another interrupt of the same
priority, serve the other interrupts of same priority that are
already pending, and then only execute the work he's queued. Kinda
some sort of cooperative yielding, but at interrupt level. This is
exactly how fibers (cooperative threads) are scheduled in Zephyr
BTW. What he's not getting if was to queue work to fibers instead,
is that when his delayed work would run would be depending on what
work is already being done in a fiber when he handles his interrupt
and what other interrupts of lower priority might be pending.
Does that work? Are pended ARM interrupts really "queued" like that?
If you have multiple pending interrupts of the same priority I'd have
to believe the order of delivery would be arbitrary and
hardware-dependent (i.e. whatever fixed precedence the hardware
designers picked in a mux somewhere).

If that works, then I agree this sounds cool. But my suspicion is
IIRC, you can have sub-priorities on Cortex-M.

Actually:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BAB
HGEAJ.html

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihe
hdge.html

However, IIRC as well, Zephyr programs the interrupt priorities with 0
subgroups, so that would not work. We could have a config option that asks for
the number of subgroups though, not hard to add.
Agreed. I think subgroups could make that work, but I don't think you have many options when there are only a few priority bits implemented. On the nrf52 you've only got 3 bits implemented, 2 priorities are reserved for the kernel, so I think you can only use one bit for subpriority.

Isn't x86 able to do that as well, in the IDT in each 16-vector block, based on the
vector position within the block ?

that the only promise you get with this irq_pend_set() implementation
is that the IRQ will run at its fixed priority sometime after your
call completes and before ISRs of lower priority or user code get to
run. And if *that's* true then you should be able to just test for
the pending state of those other known IRQs* at the end of your
function and call the one of your choice to get the same behavior.
No?

Andy

* Not ones higher than the current handler, which by definition aren't
pending. And not ones lower than the target which wouldn't run
anyway. That's going to be a small, tractable list. And
importantly one accessible to application code in Zephyr without
exposing ARM's writable interrupt pending bits.


Chettimada, Vinayak Kariappa
 

Do you have ideas on how this would be implemented for the other
architectures in Zephyr? If we can't have it as a general API, I'm
not really sure I see the value for having it in-tree. All of what
you're doing can (and, I gather, is) doable for specific hardware on a
per-app basis anyway, right?
Yes, for now from the Zephyr source, there is so much duplication, I can do the same thing :-). for example:
drivers/interrupt_controller/exti_stm32.c
drivers/interrupt_controller/arcv2_irq_unit.c
drivers/interrupt_controller/ioapic_intr.c
drivers/interrupt_controller/loapic_intr.c
...

Everything is so wrong or missing for ARM, NVIC should truely be an interrupt_controller driver in Zephyr. May be that is how I should implement for ARM then, may be inconsistent based on NVIC as I see it is so now in the drivers/interrupt_controller for others!. This will make a subsystem like a BLE controller a portability nightmare, unless there is an interrupt controller driver model, is there one? irq.h is the closest i could find.

Honestly it seems like what you have with the BLE work is tied very
closely to your hardware environment, and might need to be generalized
a bit. Can you explain what exactly you need from these features that
you can't get with Zephyr in other ways now? I mean, if your goal
with irq_pending_set() is to just have another interrupt handler
called after the current one completes, can't you implement that with
a function call at the bottom of the ISR? :)
I am trying to generalise. I need a bottom-half, a routine that is scheduled by the top half to be executed later, at a safer time. irq_offload in Zephyr sense, but I really want is Tasklets.

-Vinayak


Chettimada, Vinayak Kariappa
 


OK with this, what's the use-case though?
I am implementing a "work" (tasklet in Linux terms), a "work", being a function/routine, is invoked as a direct call i.e. if the caller is in the same priority as the ISR and the software interrupt (my "work" group) that would have been offloaded to (if were at another priority) is enabled. Hence, the need for irq_is_enabled().
In theory, each h/w interrupt can have separate/own bottom-half "work" group (ISR). Why, to have priority levels for the bottom-halves.


NACK. This isn't easily portable to other arches. You brought this up
as a candidate to replace irq_offload(), but irq_offload() only exists
as a debug feature, so that we can run some unit tests in IRQ context.
Advanced stuff like your needs, do this in your application.


Fine w/this.


NACK, for the same reasons as irq_pending_set().

Andrew
As explained above. Seemed like I was thinking or was inspired by Tasklet, definitely solving my design needs. Some day a device/subsystem will look for a similar solution.

Thinking aloud:
1. driver/interrupt_controller needs unification.
2. Introduce "work" feature now in BLE controller in a separate patch.

-Vinayak


Andy Ross
 

Vinayak Kariappa Chettimada wrote:
I am implementing a "work" (tasklet in Linux terms), a "work", being
a function/routine, is invoked as a direct call i.e. if the caller
is in the same priority as the ISR and the software interrupt (my
"work" group) that would have been offloaded to (if were at another
priority) is enabled. Hence, the need for irq_is_enabled().

In theory, each h/w interrupt can have separate/own bottom-half
"work" group (ISR). Why, to have priority levels for the
bottom-halves.
Yeah, this got some water-cooler attention last week. So it seems
what you're really asking for is an interrupt bottom half framework
for zephyr. So you can have your fiber scheduled alongside the
hardware interrupts when needed.

And (Ben needs to jump in here, I'm no expert) it seems like we have
most of what is needed already in the fiber scheduler. All that I can
see we'd need is:

1. Map the available hardware interrupt priorities to the top N fiber
priorities.

2. Mask off equal and lower interrupt priorities during the execution
of a fiber at those levels. This may be tricky to specify on all
architectures, and may involve some of them running "bottom half"
fibers with interrupts disabled. It might plausibly break some
assumptions in existing code that has an "in an ISR" notion (the
definition of "ISR" gets fuzzy).

3. Arrange to have the exit code for every ISR call _Swap() to
reschedule instead of returning directly to the interrupted task.
This would have some code size cost (maybe a tiny stub to wrap the
user-defined ISRs), though not huge.

But at that point, you don't need to muck with architecture-specific
interrupts to get what you want. You just wake up your work fiber(s)
from your existing ISRs with whatever IPC mechanism you want (give a
semaphore, write a command to a fifo, whatever) and they get scheduled
at the IRQ-scale priority you want.

What did I miss?

Andy


Boie, Andrew P
 

On Sat, 2016-09-17 at 04:13 +0000, Vinayak Kariappa Chettimada wrote:
Everything is so wrong or missing for ARM, NVIC should truely be an
interrupt_controller driver in Zephyr.
Historical note: originally, any given arch had just one interrupt
controller implementation written (APIC for x86, NVIC for ARM, etc) so
it was not separated out and was tightly coupled with the arch/*/core
code. Adding a layer of abstraction here has been done iteratively but
could still use more work. 

May be that is how I should implement for ARM then, may be
inconsistent based on NVIC as I see it is so now in the
drivers/interrupt_controller for others!. This will make a subsystem
like a BLE controller a portability nightmare, unless there is an
interrupt controller driver model, is there one?  irq.h is the
closest i could find.
irq.h is the external interrupt interface for applications.

On x86, we have an abstraction layer for interrupt controllers (which
is still x86-specific). See include/arch/x86/irq_controller.h. This
interface is private to the kernel, only arch/x86/core code uses it.

If we expect to support additional interrupt controllers on ARM, it may
be worthwhile to implement a similar interface for ARM.

I am trying to generalise. I need a bottom-half, a routine that is
scheduled by the top half to be executed later, at a safer time.
irq_offload in Zephyr sense, but I really want is Tasklets.
I suspect there are simpler approaches, I would really look into having
your ISR pend a fiber to do the bottom half work. In another mail Andy
gave some more detail.

Andrew


Boie, Andrew P
 

On Fri, 2016-09-16 at 04:52 +0000, Vinayak Kariappa Chettimada wrote:
Hi,

Welcome your valuable comments on the proposed extension to External
Interrupt API.

*irq_enable_keep*
https://gerrit.zephyrproject.org/r/#/c/4676/1
https://gerrit.zephyrproject.org/r/#/c/4677/1
Originally Vinayak sent a patch to change ARM's irq_enable() not to
unpend any pending interrupts when enabling the channel. It was -1 as
we didn't want to change the semantics of the kernel API to preserve
compatibility.

However, on further inspection of other arches, this behavior seems to
be peculiar to ARM.

On x86, for example, enabling an IRQ in the IOAPIC or MVIC just clears
the IOAPIC_INT_MASK (bit 16) in the appropriate IOREDTBL entry. It
doesn't clear pending interrupts on that line. Indeed, if it did, the
rate-limiting in the IPM console driver wouldn't work.

On ARC, similarly it puts the IRQ line into the _ARC_V2_IRQ_SELECT
register, and then writes to the _ARC_V2_IRQ_ENABLE register to
enable/disable it. I don't see anything in the datasheet that un-pends
any pending interrupts.

I think at this point we could consider ARM's behavior of clearing
pending interrupts on irq_enable() a bug and we should change it,
making irq_enable_keep() unnecessary. Does this sound good to everyone?

Andrew


Iván Briano <ivan.briano at intel.com...>
 

On Mon, 19 Sep 2016 19:07:12 +0000, Boie, Andrew P wrote:
On Fri, 2016-09-16 at 04:52 +0000, Vinayak Kariappa Chettimada wrote:
Hi,

Welcome your valuable comments on the proposed extension to External
Interrupt API.

*irq_enable_keep*
https://gerrit.zephyrproject.org/r/#/c/4676/1
https://gerrit.zephyrproject.org/r/#/c/4677/1
Originally Vinayak sent a patch to change ARM's irq_enable() not to
unpend any pending interrupts when enabling the channel. It was -1 as
we didn't want to change the semantics of the kernel API to preserve
compatibility.

However, on further inspection of other arches, this behavior seems to
be peculiar to ARM.

On x86, for example, enabling an IRQ in the IOAPIC or MVIC just clears
the IOAPIC_INT_MASK (bit 16) in the appropriate IOREDTBL entry. It
doesn't clear pending interrupts on that line. Indeed, if it did, the
rate-limiting in the IPM console driver wouldn't work.

On ARC, similarly it puts the IRQ line into the _ARC_V2_IRQ_SELECT
register, and then writes to the _ARC_V2_IRQ_ENABLE register to
enable/disable it. I don't see anything in the datasheet that un-pends
any pending interrupts.

I think at this point we could consider ARM's behavior of clearing
pending interrupts on irq_enable() a bug and we should change it,
making irq_enable_keep() unnecessary. Does this sound good to everyone?
Sounds reasonable to me.


Benjamin Walsh <benjamin.walsh@...>
 

On Mon, Sep 19, 2016 at 04:34:07PM -0300, Iván Briano wrote:
On Mon, 19 Sep 2016 19:07:12 +0000, Boie, Andrew P wrote:
On Fri, 2016-09-16 at 04:52 +0000, Vinayak Kariappa Chettimada wrote:
Hi,

Welcome your valuable comments on the proposed extension to External
Interrupt API.

*irq_enable_keep*
https://gerrit.zephyrproject.org/r/#/c/4676/1
https://gerrit.zephyrproject.org/r/#/c/4677/1
Originally Vinayak sent a patch to change ARM's irq_enable() not to
unpend any pending interrupts when enabling the channel. It was -1 as
we didn't want to change the semantics of the kernel API to preserve
compatibility.

However, on further inspection of other arches, this behavior seems to
be peculiar to ARM.

On x86, for example, enabling an IRQ in the IOAPIC or MVIC just clears
the IOAPIC_INT_MASK (bit 16) in the appropriate IOREDTBL entry. It
doesn't clear pending interrupts on that line. Indeed, if it did, the
rate-limiting in the IPM console driver wouldn't work.

On ARC, similarly it puts the IRQ line into the _ARC_V2_IRQ_SELECT
register, and then writes to the _ARC_V2_IRQ_ENABLE register to
enable/disable it. I don't see anything in the datasheet that un-pends
any pending interrupts.

I think at this point we could consider ARM's behavior of clearing
pending interrupts on irq_enable() a bug and we should change it,
making irq_enable_keep() unnecessary. Does this sound good to everyone?
Sounds reasonable to me.
Put like that, it's probably the right thing to do.


Benjamin Walsh <benjamin.walsh@...>
 

On Mon, Sep 19, 2016 at 08:31:28AM -0700, Andy Ross wrote:
Vinayak Kariappa Chettimada wrote:
I am implementing a "work" (tasklet in Linux terms), a "work", being
a function/routine, is invoked as a direct call i.e. if the caller
is in the same priority as the ISR and the software interrupt (my
"work" group) that would have been offloaded to (if were at another
priority) is enabled. Hence, the need for irq_is_enabled().

In theory, each h/w interrupt can have separate/own bottom-half
"work" group (ISR). Why, to have priority levels for the
bottom-halves.
Yeah, this got some water-cooler attention last week. So it seems
what you're really asking for is an interrupt bottom half framework
for zephyr. So you can have your fiber scheduled alongside the
hardware interrupts when needed.

And (Ben needs to jump in here, I'm no expert) it seems like we have
most of what is needed already in the fiber scheduler. All that I can
see we'd need is:

1. Map the available hardware interrupt priorities to the top N fiber
priorities.

2. Mask off equal and lower interrupt priorities during the execution
of a fiber at those levels. This may be tricky to specify on all
architectures, and may involve some of them running "bottom half"
fibers with interrupts disabled. It might plausibly break some
assumptions in existing code that has an "in an ISR" notion (the
definition of "ISR" gets fuzzy).

3. Arrange to have the exit code for every ISR call _Swap() to
reschedule instead of returning directly to the interrupted task.
This would have some code size cost (maybe a tiny stub to wrap the
user-defined ISRs), though not huge.

But at that point, you don't need to muck with architecture-specific
interrupts to get what you want. You just wake up your work fiber(s)
from your existing ISRs with whatever IPC mechanism you want (give a
semaphore, write a command to a fifo, whatever) and they get scheduled
at the IRQ-scale priority you want.
The thing is that, if we do that, these bottom-half fibers do not behave
like fibers at all. Fibers are not preemptible, except by ISRs, so the
only concurrency you have to be careful of when you write fiber code is
if you touch data that is also touched by ISRs. A data structure can be
shared between fibers without any mutual exclusion, except if a fiber
can sleep while manipulating such data.

If we start having fibers being able to preempt other fibers, this
breaks the model. It doesn't mean that we cannot have something
different than fibers that run at a higher priority than them. At that
point, fibers then have to be careful of data touched by bottom-halves
as well, but that is not much different than ISRs. But I don't think
that bottom halves should be called 'fibers' (or coop threads in the
unified kernel).

That said, I think it would still be a good idea to implement
bottom-halves.


Chettimada, Vinayak Kariappa
 

Hi Andrew,

If we expect to support additional interrupt controllers on ARM, it may
be worthwhile to implement a similar interface for ARM.


I suspect there are simpler approaches, I would really look into having
your ISR pend a fiber to do the bottom half work. In another mail Andy
gave some more detail.

Andrew
I am addressing two of styles in my code:
1. bottom-halves for ISR.
2. atomic access to peripheral only in its ISR.

For example, oscillator calibration, which is something an application can start/stop while another timer internal to clock peripheral too would do periodically/automatically. To solve race-conditions, application would just pend the clock IRQ (just like an internally timer would), the ISR being single context operating on the peripheral mitigates any race-condition and reduces latencies on ISR triggered by internal timer.

Yes, I will give a try on using fiber for both. Only issue I see is, I need to allocate program stack for each independently fibers, where as an ISR or bottom-half would share the ISR program stack.

-Vinayak


Chettimada, Vinayak Kariappa
 

Hi Ben,

That said, I think it would still be a good idea to implement
bottom-halves.
I will "+1", "+2" is I could, for bottom-halves and for a design that uses an ISR's program stack.

- Vinayak


Chettimada, Vinayak Kariappa
 

Hi Andrew,

I think at this point we could consider ARM's behavior of clearing
pending interrupts on irq_enable() a bug and we should change it,
making irq_enable_keep() unnecessary. Does this sound good to everyone?

Andrew
Good with me. I will update the irq_enable_keep change to the original fix of irq_enable.
This means, I can abandon the irq_pending_clear as well, as this is interrupt_controller domain (I created this patch on request, for the missing clear in the _keep interface).

Summary so far:
1. Fix irq_enable (irq_enable_keep has been "-1"-ed).
2. Add the irq_is_enabled in irq.h (already "+2"-ed).

Consensus required on:
1. Drop the irq_pending_set/clear, as this is interrupt_controller domain/model.

Action to myself:
1. Try out fibers where ever feasible as bottom-halves (atleast in BLE controller design)
2. Analyse if fibers makes sense as peripheral IRQ offloading, latency, and RAM usage.

-Vinayak


Maureen Helm
 

-----Original Message-----
From: Benjamin Walsh [mailto:benjamin.walsh(a)windriver.com]
Sent: Monday, September 19, 2016 3:31 PM
To: Iván Briano <ivan.briano(a)intel.com>
Cc: vinayak.kariappa.chettimada(a)nordicsemi.no; Boie, Andrew P
<andrew.p.boie(a)intel.com>; devel(a)lists.zephyrproject.org
Subject: [devel] Re: Re: Re: RFC: Extension to External Interrupt API

On Mon, Sep 19, 2016 at 04:34:07PM -0300, Iván Briano wrote:
On Mon, 19 Sep 2016 19:07:12 +0000, Boie, Andrew P wrote:
On Fri, 2016-09-16 at 04:52 +0000, Vinayak Kariappa Chettimada wrote:
Hi,

Welcome your valuable comments on the proposed extension to
External Interrupt API.

*irq_enable_keep*
https://gerrit.zephyrproject.org/r/#/c/4676/1
https://gerrit.zephyrproject.org/r/#/c/4677/1
Originally Vinayak sent a patch to change ARM's irq_enable() not to
unpend any pending interrupts when enabling the channel. It was -1
as we didn't want to change the semantics of the kernel API to
preserve compatibility.

However, on further inspection of other arches, this behavior seems
to be peculiar to ARM.

On x86, for example, enabling an IRQ in the IOAPIC or MVIC just
clears the IOAPIC_INT_MASK (bit 16) in the appropriate IOREDTBL
entry. It doesn't clear pending interrupts on that line. Indeed, if
it did, the rate-limiting in the IPM console driver wouldn't work.

On ARC, similarly it puts the IRQ line into the _ARC_V2_IRQ_SELECT
register, and then writes to the _ARC_V2_IRQ_ENABLE register to
enable/disable it. I don't see anything in the datasheet that
un-pends any pending interrupts.

I think at this point we could consider ARM's behavior of clearing
pending interrupts on irq_enable() a bug and we should change it,
making irq_enable_keep() unnecessary. Does this sound good to
everyone?

Sounds reasonable to me.
Put like that, it's probably the right thing to do.
Sounds ok to me. Thanks for digging into the other arches Andrew.