-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Description
Problem description
Currently, there seems to be no architectural support for shared interrupts. As such, in the following sequence:
irq_connect_dynamic(33, INTID_33_PRIO, some_handler, some_argument);irq_connect_dynamic(33, INTID_33_PRIO, some_other_handler, some_other_argument);
some_other_handler would overwrite some_handler. Currently there seem to be 2 ways to solve this:
- Make use of the
intc_shared_irq.cinterrupt controller => doesn't scale very well, seems to require a DT node per shared IRQ. Problematic on platforms which have multiple shared IRQs (e.g: i.MX8QM which has the same INTID for groups of x channels) - Handle this yourself in your driver/application => somewhat difficult and annoying in situations such as the one described above. Needs to be done per module which uses a shared IRQ.
Proposed change
As as a way to solve the problem described above, we could add architectural support for shared interrupts. This could be achieved by simply registering a "dummy" ISR for an INTID and calling all registered ISRs for that INTID.
Detailed RFC
More specifically, if the SHARED_IRQ feature is enabled, we could overwrite z_isr_install() such that instead of registering the passed routine and argument in the ISR table, we could register our own "dummy" ISR and pass it a list of routine/arg pairs that it needs to invoke.
The following is a draft of how this could be achieved:
struct shared_irq_client {
void (*routine)(const void *arg);
const void *arg;
};
struct shared_irq_data {
bool enabled;
struct shared_irq_client clients[CONFIG_SHARED_IRQ_MAX_NUM_CLIENTS];
uint32_t client_num;
};
static struct shared_irq_data shared_irq_table[CONFIG_NUM_IRQS];
void shared_irq_isr(const void *data)
{
struct shared_irq_data *irq_data = data;
int i;
for (i = 0; i < irq_data->client_num; i++)
irq_data->clients[i].routine(irq_data->clients[i].arg);
}
/* note: this definition of z_isr_install would overwrite the definition from sw_isr_common.c */
void z_isr_install(unsigned int irq, void (*routine)(const void *), const void *param)
{
... some code goes here ...
/* note: this is only done once per INTID, upon enabling it for the first time */
_sw_isr_table[table_idx].arg = irq_data;
_sw_isr_table[table_idx].isr = shared_irq_isr;
... some code goes here ...
/* irq_data points to the entry in shared_irq_table corresponding to passed IRQ */
irq_data->clients[irq_data->client_num].routine = routine;
irq_data->clients[irq_data->client_num].arg = param;
irq_data->client_num++;
}
Dependencies
This feature would be something one can enable/disable with a configuration. As such, if CONFIG_SHARED_INTERRUPTS=y, z_isr_install would have the above definition. Otherwise, the default definition from sw_isr_common.c will be used. In theory there should be no dependencies.
Would this change be something desired by the community? If so, I can submit a PR after I have something functional.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status