/* * Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * For additional information see http://www.ethernut.de/ * */ /* * $Log$ * Revision 1.8 2009/03/05 22:16:57 freckle * use __NUT_EMULATION instead of __APPLE__, __linux__, or __CYGWIN__ * * Revision 1.7 2008/07/26 09:38:02 haraldkipp * Added support for NUT_IRQMODE_NONE and NUT_IRQMODE_LEVEL. * * Revision 1.6 2006/10/08 16:48:09 haraldkipp * Documentation fixed * * Revision 1.5 2006/01/05 16:51:54 haraldkipp * NutIrqSetPriority() didn't correctly return the previous priority. This * bug has been fixed. * New function NutIrqSetMode() allows to modify the interrupt modes. * * Revision 1.4 2005/10/24 10:17:24 haraldkipp * New API functions added to create platform independant drivers. * Interrupt counting requires NUT_PERFMON to be defined. * * Revision 1.3 2005/08/02 17:46:47 haraldkipp * Major API documentation update. * * Revision 1.2 2005/07/26 16:30:58 haraldkipp * Copyright added. * Temporarily exclude NutRegisterIrqHandler() from Linux builds. * */ #include #include /*! * \addtogroup xgInterrupt */ /*@{*/ /*! * \brief Call a registered interrupt handler. */ void CallHandler(IRQ_HANDLER * irh) { #ifdef NUT_PERFMON irh->ir_count++; #endif if (irh->ir_handler) (irh->ir_handler) (irh->ir_arg); } /*! * \brief Register an interrupt handler. * * This function is typically called by device drivers, but * applications may also implement their local interrupt * handlers. * * \param irq Interrupt to be associated with this handler. * \param handler This routine will be called by Nut/OS, when the * specified interrupt occurs. * \param arg Argument to be passed to the interrupt handler. * * \return 0 on success, -1 otherwise. */ #ifndef __NUT_EMULATION__ int NutRegisterIrqHandler(IRQ_HANDLER * irq, void (*handler) (void *), void *arg) { int rc = 0; /* Initialize this interrupt. */ if (irq->ir_ctl) { rc = (irq->ir_ctl) (NUT_IRQCTL_INIT, NULL); } /* Set the interrupt handler. */ irq->ir_arg = arg; irq->ir_handler = handler; return rc; } /*! * \brief Check if the corresponding interrupt is enabled or disabled. * * \param irq Interrupt to query. * * \return 0 if disabled, 1 if enabled. */ int NutIrqStatus(IRQ_HANDLER * irq) { int rc = 0; int status = 0; if (irq->ir_ctl) { rc = (irq->ir_ctl) (NUT_IRQCTL_STATUS, &status); } if (rc != 0) { status = 0; } return status; } /*! * \brief Enable a specified interrupt. * * \param irq Interrupt to enable. * * \return 0 on success, -1 otherwise. */ int NutIrqEnable(IRQ_HANDLER * irq) { int rc = -1; if (irq->ir_ctl) { rc = (irq->ir_ctl) (NUT_IRQCTL_ENABLE, NULL); } return rc; } /*! * \brief Disable a specified interrupt. * * \param irq Interrupt to disable. * * \return 0 on success, -1 otherwise. */ int NutIrqDisable(IRQ_HANDLER * irq) { int rc = -1; if (irq->ir_ctl) { rc = (irq->ir_ctl) (NUT_IRQCTL_DISABLE, NULL); } return rc; } /*! * \brief Modify the priority level of an interrupt. * * The function returns the old priority, which makes it easy to * temporarily switch to another priority and later set back the * old one. * * \note Not all targets support dynamic interrupt prioritization. * Check the hardware data sheet for valid levels. * * \param irq Interrupt to modify. * \param level New priority level. * * \return Old priority level or -1 in case of an error. */ int NutIrqSetPriority(IRQ_HANDLER * irq, int level) { int rc = -1; if (irq->ir_ctl) { int prev; rc = (irq->ir_ctl) (NUT_IRQCTL_GETPRIO, &prev); if (rc == 0 && (rc = (irq->ir_ctl) (NUT_IRQCTL_SETPRIO, &level)) == 0) { rc = prev; } } return rc; } /*! * \brief Query the priority level of an interrupt. * * The function returns the priority * * \note Not all targets support dynamic interrupt prioritization. * Check the hardware data sheet for valid levels. * * \param irq Interrupt to query. * * \return Priority level or -1 in case of an error. */ int NutIrqGetPriority(IRQ_HANDLER * irq) { int rc = -1; if (irq->ir_ctl) { int level; rc = (irq->ir_ctl) (NUT_IRQCTL_GETPRIO, &level); if (rc == 0) { rc = level; } } return rc; } /*! * \brief Modify the interrupt mode. * * The function returns the old mode, which makes it easy to * temporarily switch to another mode and later set back the * old one. * * \note Not all targets support all modes. Check the hardware * data sheet for valid levels. * * \param irq Interrupt to modify. * \param mode New interrupt mode: * - NUT_IRQMODE_NONE No change. Used to query current mode. * - NUT_IRQMODE_LOWLEVEL Low level sensitive. * - NUT_IRQMODE_HIGHLEVEL High level sensitive. * - NUT_IRQMODE_FALLINGEDGE Negative edge triggered. * - NUT_IRQMODE_RISINGEDGE Positive edge triggered. * - NUT_IRQMODE_EDGE Triggers on any edge or active internal edge. * - NUT_IRQMODE_LEVEL Triggers on level change or active internal level. * * * \return Old mode or -1 in case of an error. */ int NutIrqSetMode(IRQ_HANDLER * irq, int mode) { int rc = -1; if (irq->ir_ctl) { int prev; rc = (irq->ir_ctl) (NUT_IRQCTL_GETMODE, &prev); if (rc == 0 && (mode == NUT_IRQMODE_NONE || (rc = (irq->ir_ctl) (NUT_IRQCTL_SETMODE, &mode)) == 0)) { rc = prev; } } return rc; } #endif /*@}*/