summaryrefslogtreecommitdiff
path: root/nuttx/drivers
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-12-30 14:56:37 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-12-30 14:56:37 -0600
commit443549cbbe6fdd0f169f02f3593eec4d35bc9ae6 (patch)
treea6b01b48af0a68708c1a81bbba8060a77b2f797c /nuttx/drivers
parent36a4d40cbbcc2ae5089efc2554f50f29cee7abbc (diff)
downloadnuttx-443549cbbe6fdd0f169f02f3593eec4d35bc9ae6.tar.gz
nuttx-443549cbbe6fdd0f169f02f3593eec4d35bc9ae6.tar.bz2
nuttx-443549cbbe6fdd0f169f02f3593eec4d35bc9ae6.zip
drivers/net/skeleton.c: Add outline for support with CONFIG_NET_NOINTS
Diffstat (limited to 'nuttx/drivers')
-rw-r--r--nuttx/drivers/net/skeleton.c264
1 files changed, 243 insertions, 21 deletions
diff --git a/nuttx/drivers/net/skeleton.c b/nuttx/drivers/net/skeleton.c
index 061e8df3d..060ab185f 100644
--- a/nuttx/drivers/net/skeleton.c
+++ b/nuttx/drivers/net/skeleton.c
@@ -55,9 +55,20 @@
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
+#ifndef CONFIG_NET_NOINTS
+# include <nuttx/wqueue.h>
+#endif
+
/****************************************************************************
- * Definitions
+ * Pre-processor Definitions
****************************************************************************/
+/* If processing is not done at the interrupt level, then high priority
+ * work queue support is required.
+ */
+
+#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_HPWORK)
+# error High priority work queue support is required
+#endif
/* CONFIG_skeleton_NINTERFACES determines the number of physical interfaces
* that will be supported.
@@ -93,6 +104,9 @@ struct skel_driver_s
bool sk_bifup; /* true:ifup false:ifdown */
WDOG_ID sk_txpoll; /* TX poll timer */
WDOG_ID sk_txtimeout; /* TX timeout timer */
+#ifdef CONFIG_NET_NOINTS
+ struct work_s work; /* For deferring work to the work queue */
+#endif
/* This holds the information visible to uIP/NuttX */
@@ -118,11 +132,24 @@ static int skel_txpoll(struct net_driver_s *dev);
static void skel_receive(FAR struct skel_driver_s *skel);
static void skel_txdone(FAR struct skel_driver_s *skel);
+static inline void skel_interrupt_process(FAR struct skel_driver_s *skel);
+#ifdef CONFIG_NET_NOINTS
+static void skel_interrupt_work(FAR void *arg);
+#endif
static int skel_interrupt(int irq, FAR void *context);
/* Watchdog timer expirations */
+static inline void skel_poll_process(FAR struct skel_driver_s *skel);
+#ifdef CONFIG_NET_NOINTS
+static void skel_poll_work(FAR void *arg);
+#endif
static void skel_polltimer(int argc, uint32_t arg, ...);
+
+static inline void skel_txtimeout_process(FAR struct skel_driver_s *skel);
+#ifdef CONFIG_NET_NOINTS
+static void skel_txtimeout_work(FAR void *arg);
+#endif
static void skel_txtimeout(int argc, uint32_t arg, ...);
/* NuttX callback functions */
@@ -327,26 +354,25 @@ static void skel_txdone(FAR struct skel_driver_s *skel)
}
/****************************************************************************
- * Function: skel_interrupt
+ * Function: skel_interrupt_process
*
* Description:
- * Hardware interrupt handler
+ * Interrupt processing. This may be performed either within the interrupt
+ * handler or on the worker thread, depending upon the configuration
*
* Parameters:
- * irq - Number of the IRQ that generated the interrupt
- * context - Interrupt register state save info (architecture-specific)
+ * skel - Reference to the driver state structure
*
* Returned Value:
- * OK on success
+ * None
*
* Assumptions:
+ * Ethernet interrupts are disabled
*
****************************************************************************/
-static int skel_interrupt(int irq, FAR void *context)
+static inline void skel_interrupt_process(FAR struct skel_driver_s *skel)
{
- register FAR struct skel_driver_s *skel = &g_skel[0];
-
/* Get and clear interrupt status bits */
/* Handle interrupts according to status bit settings */
@@ -357,24 +383,92 @@ static int skel_interrupt(int irq, FAR void *context)
/* Check if a packet transmission just completed. If so, call skel_txdone.
* This may disable further Tx interrupts if there are no pending
- * tansmissions.
+ * transmissions.
*/
skel_txdone(skel);
+}
+
+/****************************************************************************
+ * Function: skel_interrupt_work
+ *
+ * Description:
+ * Perform interrupt related work from the worker thread
+ *
+ * Parameters:
+ * arg - The argument passed when work_queue() as called.
+ *
+ * Returned Value:
+ * OK on success
+ *
+ * Assumptions:
+ * Ethernet interrupts are disabled
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_NOINTS
+static void skel_interrupt_work(FAR void *arg)
+{
+ FAR struct skel_driver_s *skel = ( FAR struct skel_driver_s *)arg;
+
+ /* Process pending Ethernet interrupts */
+
+ skel_interrupt_process(skel);
+
+ /* TODO: Re-enable Ethernet interrupts */
+}
+#endif
+
+/****************************************************************************
+ * Function: skel_interrupt
+ *
+ * Description:
+ * Hardware interrupt handler
+ *
+ * Parameters:
+ * irq - Number of the IRQ that generated the interrupt
+ * context - Interrupt register state save info (architecture-specific)
+ *
+ * Returned Value:
+ * OK on success
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int skel_interrupt(int irq, FAR void *context)
+{
+ FAR struct skel_driver_s *skel = &g_skel[0];
+
+#ifdef CONFIG_NET_NOINTS
+ /* TODO: Disable further Ethernet interrupts */
+
+ /* Schedule to perform the interrupt processing on the worker thread.
+ * TODO: Assure that no timeouts can occur.
+ */
+
+ DEBUGASSERT(work_available(&skel->work);
+ work_queue(HPWORK, &skel->work, skel_interrupt_work, skel, 0);
+#else
+ /* Process the interrupt now */
+
+ skel_interrupt_process(skel);
+#endif
return OK;
}
/****************************************************************************
- * Function: skel_txtimeout
+ * Function: skel_txtimeout_process
*
* Description:
- * Our TX watchdog timed out. Called from the timer interrupt handler.
- * The last TX never completed. Reset the hardware and start again.
+ * Process a TX timeout. Called from the either the watchdog timer
+ * expiration logic or from the worker thread, depeding upon the
+ * configuration. The timeout means that the last TX never completed.
+ * Reset the hardware and start again.
*
* Parameters:
- * argc - The number of available arguments
- * arg - The first argument
+ * skel - Reference to the driver state structure
*
* Returned Value:
* None
@@ -384,10 +478,8 @@ static int skel_interrupt(int irq, FAR void *context)
*
****************************************************************************/
-static void skel_txtimeout(int argc, uint32_t arg, ...)
+static inline void skel_txtimeout_process(FAR struct skel_driver_s *skel)
{
- FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)arg;
-
/* Increment statistics and dump debug info */
/* Then reset the hardware */
@@ -398,10 +490,39 @@ static void skel_txtimeout(int argc, uint32_t arg, ...)
}
/****************************************************************************
- * Function: skel_polltimer
+ * Function: skel_txtimeout_work
*
* Description:
- * Periodic timer handler. Called from the timer interrupt handler.
+ * Perform TX timeout related work from the worker thread
+ *
+ * Parameters:
+ * arg - The argument passed when work_queue() as called.
+ *
+ * Returned Value:
+ * OK on success
+ *
+ * Assumptions:
+ * Ethernet interrupts are disabled
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_NOINTS
+static void skel_txtimeout_work(FAR void *arg)
+{
+ FAR struct skel_driver_s *skel = ( FAR struct skel_driver_s *)arg;
+
+ /* Process pending Ethernet interrupts */
+
+ skel_txtimetout_process(skel);
+}
+#endif
+
+/****************************************************************************
+ * Function: skel_txtimeout
+ *
+ * Description:
+ * Our TX watchdog timed out. Called from the timer interrupt handler.
+ * The last TX never completed. Reset the hardware and start again.
*
* Parameters:
* argc - The number of available arguments
@@ -415,10 +536,45 @@ static void skel_txtimeout(int argc, uint32_t arg, ...)
*
****************************************************************************/
-static void skel_polltimer(int argc, uint32_t arg, ...)
+static void skel_txtimeout(int argc, uint32_t arg, ...)
{
FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)arg;
+#ifdef CONFIG_NET_NOINTS
+ /* TODO: Disable further Ethernet interrupts */
+
+ /* Schedule to perform the TX timeout processing on the worker thread.
+ * TODO: Assure that no there is not pending interrupt or poll work.
+ */
+
+ DEBUGASSERT(work_available(&skel->work);
+ work_queue(HPWORK, &skel->work, skel_txtimeout_work, skel, 0);
+#else
+ /* Process the interrupt now */
+
+ skel_txtimeout_process(skel);
+#endif
+}
+
+/****************************************************************************
+ * Function: skel_poll_process
+ *
+ * Description:
+ * Perform the periodic poll. This may be called either from watchdog
+ * timer logic or from the worker thread, depending upon the configuration.
+ *
+ * Parameters:
+ * skel - Reference to the driver state structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static inline void skel_poll_process(FAR struct skel_driver_s *skel)
+{
/* Check if there is room in the send another TX packet. We cannot perform
* the TX poll if he are unable to accept another packet for transmission.
*/
@@ -436,6 +592,72 @@ static void skel_polltimer(int argc, uint32_t arg, ...)
}
/****************************************************************************
+ * Function: skel_poll_work
+ *
+ * Description:
+ * Perform periodic polling from the worker thread
+ *
+ * Parameters:
+ * arg - The argument passed when work_queue() as called.
+ *
+ * Returned Value:
+ * OK on success
+ *
+ * Assumptions:
+ * Ethernet interrupts are disabled
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_NOINTS
+static void skel_poll_work(FAR void *arg)
+{
+ FAR struct skel_driver_s *skel = ( FAR struct skel_driver_s *)arg;
+
+ /* Perform the poll */
+
+ skel_poll_process(skel);
+}
+#endif
+
+/****************************************************************************
+ * Function: skel_polltimer
+ *
+ * Description:
+ * Periodic timer handler. Called from the timer interrupt handler.
+ *
+ * Parameters:
+ * argc - The number of available arguments
+ * arg - The first argument
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Global interrupts are disabled by the watchdog logic.
+ *
+ ****************************************************************************/
+
+static void skel_polltimer(int argc, uint32_t arg, ...)
+{
+ FAR struct skel_driver_s *skel = (FAR struct skel_driver_s *)arg;
+
+#ifdef CONFIG_NET_NOINTS
+ /* Schedule to perform the interrupt processing on the worker thread.
+ * TODO: Make sure that there can be no pending interrupt work.
+ */
+
+ DEBUGASSERT(work_available(&skel->work);
+ work_queue(HPWORK, &skel->work, skel_poll_work, skel, 0);
+#else
+ /* Process the interrupt now */
+
+ skel_poll_process(skel);
+#endif
+
+ return OK;
+}
+
+/****************************************************************************
* Function: skel_ifup
*
* Description: