IOTON Technology / mbed-ton

Fork of mbed-dev by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers InterruptManager.h Source File

InterruptManager.h

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #ifndef MBED_INTERRUPTMANAGER_H
00017 #define MBED_INTERRUPTMANAGER_H
00018 
00019 #include "cmsis.h"
00020 #include "platform/CallChain.h"
00021 #include "platform/PlatformMutex.h"
00022 #include <string.h>
00023 
00024 namespace mbed {
00025 /** \addtogroup drivers */
00026 
00027 /** Use this singleton if you need to chain interrupt handlers.
00028  *
00029  * @note Synchronization level: Thread safe
00030  *
00031  * Example (for LPC1768):
00032  * @code
00033  * #include "InterruptManager.h"
00034  * #include "mbed.h"
00035  *
00036  * Ticker flipper;
00037  * DigitalOut led1(LED1);
00038  * DigitalOut led2(LED2);
00039  *
00040  * void flip(void) {
00041  *     led1 = !led1;
00042  * }
00043  *
00044  * void handler(void) {
00045  *     led2 = !led1;
00046  * }
00047  *
00048  * int main() {
00049  *     led1 = led2 = 0;
00050  *     flipper.attach(&flip, 1.0);
00051  *     InterruptManager::get()->add_handler(handler, TIMER3_IRQn);
00052  * }
00053  * @endcode
00054  * @ingroup drivers
00055  */
00056 class InterruptManager {
00057 public:
00058     /** Get the instance of InterruptManager Class
00059      *
00060      *  @return the only instance of this class
00061      */
00062     static InterruptManager* get();
00063 
00064     /** Destroy the current instance of the interrupt manager
00065      */
00066     static void destroy();
00067 
00068     /** Add a handler for an interrupt at the end of the handler list
00069      *
00070      *  @param function the handler to add
00071      *  @param irq interrupt number
00072      *
00073      *  @returns
00074      *  The function object created for 'function'
00075      */
00076     pFunctionPointer_t add_handler(void (*function)(void), IRQn_Type irq) {
00077         // Underlying call is thread safe
00078         return add_common(function, irq);
00079     }
00080 
00081     /** Add a handler for an interrupt at the beginning of the handler list
00082      *
00083      *  @param function the handler to add
00084      *  @param irq interrupt number
00085      *
00086      *  @returns
00087      *  The function object created for 'function'
00088      */
00089     pFunctionPointer_t add_handler_front(void (*function)(void), IRQn_Type irq) {
00090         // Underlying call is thread safe
00091         return add_common(function, irq, true);
00092     }
00093 
00094     /** Add a handler for an interrupt at the end of the handler list
00095      *
00096      *  @param tptr pointer to the object that has the handler function
00097      *  @param mptr pointer to the actual handler function
00098      *  @param irq interrupt number
00099      *
00100      *  @returns
00101      *  The function object created for 'tptr' and 'mptr'
00102      */
00103     template<typename T>
00104     pFunctionPointer_t add_handler(T* tptr, void (T::*mptr)(void), IRQn_Type irq) {
00105         // Underlying call is thread safe
00106         return add_common(tptr, mptr, irq);
00107     }
00108 
00109     /** Add a handler for an interrupt at the beginning of the handler list
00110      *
00111      *  @param tptr pointer to the object that has the handler function
00112      *  @param mptr pointer to the actual handler function
00113      *  @param irq interrupt number
00114      *
00115      *  @returns
00116      *  The function object created for 'tptr' and 'mptr'
00117      */
00118     template<typename T>
00119     pFunctionPointer_t add_handler_front(T* tptr, void (T::*mptr)(void), IRQn_Type irq) {
00120         // Underlying call is thread safe
00121         return add_common(tptr, mptr, irq, true);
00122     }
00123 
00124     /** Remove a handler from an interrupt
00125      *
00126      *  @param handler the function object for the handler to remove
00127      *  @param irq the interrupt number
00128      *
00129      *  @returns
00130      *  true if the handler was found and removed, false otherwise
00131      */
00132     bool remove_handler(pFunctionPointer_t handler, IRQn_Type irq);
00133 
00134 private:
00135     InterruptManager();
00136     ~InterruptManager();
00137 
00138     void lock();
00139     void unlock();
00140 
00141     // We declare the copy contructor and the assignment operator, but we don't
00142     // implement them. This way, if someone tries to copy/assign our instance,
00143     // he will get an error at compile time.
00144     InterruptManager(const InterruptManager&);
00145     InterruptManager& operator =(const InterruptManager&);
00146 
00147     template<typename T>
00148     pFunctionPointer_t add_common(T *tptr, void (T::*mptr)(void), IRQn_Type irq, bool front=false) {
00149         _mutex.lock();
00150         int irq_pos = get_irq_index(irq);
00151         bool change = must_replace_vector(irq);
00152 
00153         pFunctionPointer_t pf = front ? _chains[irq_pos]->add_front(tptr, mptr) : _chains[irq_pos]->add(tptr, mptr);
00154         if (change)
00155             NVIC_SetVector(irq, (uint32_t)&InterruptManager::static_irq_helper);
00156         _mutex.unlock();
00157         return pf;
00158     }
00159 
00160     pFunctionPointer_t add_common(void (*function)(void), IRQn_Type irq, bool front=false);
00161     bool must_replace_vector(IRQn_Type irq);
00162     int get_irq_index(IRQn_Type irq);
00163     void irq_helper();
00164     void add_helper(void (*function)(void), IRQn_Type irq, bool front=false);
00165     static void static_irq_helper();
00166 
00167     CallChain* _chains[NVIC_NUM_VECTORS];
00168     static InterruptManager* _instance;
00169     PlatformMutex _mutex;
00170 };
00171 
00172 } // namespace mbed
00173 
00174 #endif