diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-12-30 14:56:37 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-12-30 14:56:37 -0600 |
commit | 443549cbbe6fdd0f169f02f3593eec4d35bc9ae6 (patch) | |
tree | a6b01b48af0a68708c1a81bbba8060a77b2f797c /nuttx/drivers | |
parent | 36a4d40cbbcc2ae5089efc2554f50f29cee7abbc (diff) | |
download | nuttx-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.c | 264 |
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: |