forked from apache/nuttx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
irq: irq with the same priority share the same wqueue
Signed-off-by: hujun5 <hujun5@xiaomi.com>
- Loading branch information
Showing
6 changed files
with
264 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
/**************************************************************************** | ||
* sched/irq/irq_attach_wqueue.c | ||
* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. The | ||
* ASF licenses this file to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance with the | ||
* License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
* | ||
****************************************************************************/ | ||
|
||
/**************************************************************************** | ||
* Included Files | ||
****************************************************************************/ | ||
|
||
#include <nuttx/config.h> | ||
|
||
#include <errno.h> | ||
#include <stdio.h> | ||
|
||
#include <nuttx/irq.h> | ||
#include <nuttx/wqueue.h> | ||
#include <debug.h> | ||
|
||
#include "irq/irq.h" | ||
#include "sched/sched.h" | ||
|
||
/**************************************************************************** | ||
* Privte Types | ||
****************************************************************************/ | ||
|
||
/* This is the type of the list of interrupt handlers, one for each IRQ. | ||
* This type provided all of the information necessary to irq_dispatch to | ||
* transfer control to interrupt handlers after the occurrence of an | ||
* interrupt. | ||
*/ | ||
|
||
struct irq_work_info_s | ||
{ | ||
xcpt_t handler; /* Address of the interrupt handler */ | ||
xcpt_t isrwork; /* Address of the interrupt worked handler */ | ||
FAR void *arg; /* The argument provided to the interrupt handler. */ | ||
int irq; /* Irq id */ | ||
struct work_s work; /* Interrupt work to the wq */ | ||
|
||
FAR struct kwork_wqueue_s *wqueue; /* Work queue. */ | ||
}; | ||
|
||
/**************************************************************************** | ||
* Private Data | ||
****************************************************************************/ | ||
|
||
#ifdef CONFIG_ARCH_MINIMAL_VECTORTABLE | ||
static struct irq_work_info_s | ||
g_irq_work_vector[CONFIG_ARCH_NUSER_INTERRUPTS]; | ||
#else | ||
static struct irq_work_info_s g_irq_work_vector[NR_IRQS]; | ||
#endif | ||
|
||
static mutex_t g_irq_wqueue_lock = NXMUTEX_INITIALIZER; | ||
static FAR struct kwork_wqueue_s *g_irq_wqueue[CONFIG_IRQ_NWORKS]; | ||
static int g_irq_wqueue_count = 0; | ||
|
||
/**************************************************************************** | ||
* Private Functions | ||
****************************************************************************/ | ||
|
||
static inline_function struct kwork_wqueue_s *irq_get_wqueue(int priority) | ||
{ | ||
FAR struct kwork_wqueue_s *queue; | ||
int wqueue_priority; | ||
int i; | ||
|
||
nxmutex_lock(&g_irq_wqueue_lock); | ||
for (i = 0; i < g_irq_wqueue_count; i++) | ||
{ | ||
wqueue_priority = work_queue_priority_wq(g_irq_wqueue[i]); | ||
DEBUGASSERT(wqueue_priority >= SCHED_PRIORITY_MIN && | ||
wqueue_priority <= SCHED_PRIORITY_MAX); | ||
|
||
if (wqueue_priority == priority) | ||
{ | ||
nxmutex_unlock(&g_irq_wqueue_lock); | ||
return g_irq_wqueue[i]; | ||
} | ||
} | ||
|
||
DEBUGASSERT(g_irq_wqueue_count < CONFIG_IRQ_NWORKS); | ||
|
||
queue = work_queue_create("isrwork", priority, | ||
CONFIG_IRQ_WORK_STACKSIZE, 1); | ||
|
||
g_irq_wqueue[g_irq_wqueue_count++] = queue; | ||
nxmutex_unlock(&g_irq_wqueue_lock); | ||
return queue; | ||
} | ||
|
||
/* Default interrupt handler for worked interrupts. | ||
* Useful for oneshot interrupts. | ||
*/ | ||
|
||
static void irq_work_handler(FAR void *arg) | ||
{ | ||
FAR struct irq_work_info_s *info = (FAR struct irq_work_info_s *)arg; | ||
|
||
info->isrwork(info->irq, NULL, info->arg); | ||
} | ||
|
||
static int irq_default_handler(int irq, FAR void *regs, FAR void *arg) | ||
{ | ||
FAR struct irq_work_info_s *info; | ||
int ret = IRQ_WAKE_THREAD; | ||
int ndx = IRQ_TO_NDX(irq); | ||
xcpt_t vector; | ||
|
||
if (ndx < 0) | ||
{ | ||
return ndx; | ||
} | ||
|
||
info = &g_irq_work_vector[ndx]; | ||
vector = info->handler; | ||
|
||
if (vector) | ||
{ | ||
ret = vector(irq, regs, arg); | ||
} | ||
|
||
if (ret == IRQ_WAKE_THREAD) | ||
{ | ||
work_queue_wq(info->wqueue, &info->work, irq_work_handler, info, 0); | ||
ret = OK; | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
/**************************************************************************** | ||
* Public Functions | ||
****************************************************************************/ | ||
|
||
/**************************************************************************** | ||
* Name: irq_attach_wqueue | ||
* | ||
* Description: | ||
* Configure the IRQ subsystem so that IRQ number 'irq' is dispatched to | ||
* 'wqueue' | ||
* | ||
* Input Parameters: | ||
* irq - Irq num | ||
* isr - Function to be called when the IRQ occurs, called in interrupt | ||
* context. | ||
* If isr is NULL the default handler is installed(irq_default_handler). | ||
* isrwork - called in thread context, If the isrwork is NULL, | ||
* then the ISR is being detached. | ||
* arg - privdate data | ||
* priority - isrwork pri | ||
* | ||
* Returned Value: | ||
* Zero on success; a negated errno value on failure. | ||
* | ||
****************************************************************************/ | ||
|
||
int irq_attach_wqueue(int irq, xcpt_t isr, xcpt_t isrwork, | ||
FAR void *arg, int priority) | ||
{ | ||
FAR struct irq_work_info_s *info; | ||
|
||
#if NR_IRQS > 0 | ||
int ndx; | ||
|
||
if ((unsigned)irq >= NR_IRQS) | ||
{ | ||
return -EINVAL; | ||
} | ||
|
||
ndx = IRQ_TO_NDX(irq); | ||
if (ndx < 0) | ||
{ | ||
return ndx; | ||
} | ||
|
||
/* If the isrwork is NULL, then the ISR is being detached. */ | ||
|
||
info = &g_irq_work_vector[ndx]; | ||
|
||
if (isrwork == NULL) | ||
{ | ||
irq_detach(irq); | ||
info->isrwork = NULL; | ||
info->handler = NULL; | ||
info->arg = NULL; | ||
info->wqueue = NULL; | ||
return OK; | ||
} | ||
|
||
info->isrwork = isrwork; | ||
info->handler = isr; | ||
info->arg = arg; | ||
info->irq = irq; | ||
if (info->wqueue == NULL) | ||
{ | ||
info->wqueue = irq_get_wqueue(priority); | ||
} | ||
|
||
irq_attach(irq, irq_default_handler, arg); | ||
#endif /* NR_IRQS */ | ||
|
||
return OK; | ||
} | ||
|