]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/mbed/api/InterruptManager.h
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / mbed / api / InterruptManager.h
1 #ifndef MBED_INTERRUPTMANAGER_H
2 #define MBED_INTERRUPTMANAGER_H
3
4 #include "cmsis.h"
5 #include "CallChain.h"
6 #include <string.h>
7
8 namespace mbed {
9
10 /** Use this singleton if you need to chain interrupt handlers.
11  *
12  * Example (for LPC1768):
13  * @code
14  * #include "InterruptManager.h"
15  * #include "mbed.h"
16  *
17  * Ticker flipper;
18  * DigitalOut led1(LED1);
19  * DigitalOut led2(LED2);
20  *
21  * void flip(void) {
22  *     led1 = !led1;
23  * }
24  *
25  * void handler(void) {
26  *     led2 = !led1;
27  * }
28  *
29  * int main() {
30  *     led1 = led2 = 0;
31  *     flipper.attach(&flip, 1.0);
32  *     InterruptManager::get()->add_handler(handler, TIMER3_IRQn);
33  * }
34  * @endcode
35  */
36 class InterruptManager {
37 public:
38     /** Return the only instance of this class
39      */
40     static InterruptManager* get();
41
42     /** Destroy the current instance of the interrupt manager
43      */
44     static void destroy();
45
46     /** Add a handler for an interrupt at the end of the handler list
47      *
48      *  @param function the handler to add
49      *  @param irq interrupt number
50      *
51      *  @returns
52      *  The function object created for 'function'
53      */
54     pFunctionPointer_t add_handler(void (*function)(void), IRQn_Type irq) {
55         return add_common(function, irq);
56     }
57
58     /** Add a handler for an interrupt at the beginning of the handler list
59      *
60      *  @param function the handler to add
61      *  @param irq interrupt number
62      *
63      *  @returns
64      *  The function object created for 'function'
65      */
66     pFunctionPointer_t add_handler_front(void (*function)(void), IRQn_Type irq) {
67         return add_common(function, irq, true);
68     }
69
70     /** Add a handler for an interrupt at the end of the handler list
71      *
72      *  @param tptr pointer to the object that has the handler function
73      *  @param mptr pointer to the actual handler function
74      *  @param irq interrupt number
75      *
76      *  @returns
77      *  The function object created for 'tptr' and 'mptr'
78      */
79     template<typename T>
80     pFunctionPointer_t add_handler(T* tptr, void (T::*mptr)(void), IRQn_Type irq) {
81         return add_common(tptr, mptr, irq);
82     }
83
84     /** Add a handler for an interrupt at the beginning of the handler list
85      *
86      *  @param tptr pointer to the object that has the handler function
87      *  @param mptr pointer to the actual handler function
88      *  @param irq interrupt number
89      *
90      *  @returns
91      *  The function object created for 'tptr' and 'mptr'
92      */
93     template<typename T>
94     pFunctionPointer_t add_handler_front(T* tptr, void (T::*mptr)(void), IRQn_Type irq) {
95         return add_common(tptr, mptr, irq, true);
96     }
97
98     /** Remove a handler from an interrupt
99      *
100      *  @param handler the function object for the handler to remove
101      *  @param irq the interrupt number
102      *
103      *  @returns
104      *  true if the handler was found and removed, false otherwise
105      */
106     bool remove_handler(pFunctionPointer_t handler, IRQn_Type irq);
107
108 private:
109     InterruptManager();
110     ~InterruptManager();
111
112     // We declare the copy contructor and the assignment operator, but we don't
113     // implement them. This way, if someone tries to copy/assign our instance,
114     // he will get an error at compile time.
115     InterruptManager(const InterruptManager&);
116     InterruptManager& operator =(const InterruptManager&);
117
118     template<typename T>
119     pFunctionPointer_t add_common(T *tptr, void (T::*mptr)(void), IRQn_Type irq, bool front=false) {
120         int irq_pos = get_irq_index(irq);
121         bool change = must_replace_vector(irq);
122
123         pFunctionPointer_t pf = front ? _chains[irq_pos]->add_front(tptr, mptr) : _chains[irq_pos]->add(tptr, mptr);
124         if (change)
125             NVIC_SetVector(irq, (uint32_t)&InterruptManager::static_irq_helper);
126         return pf;
127     }
128
129     pFunctionPointer_t add_common(void (*function)(void), IRQn_Type irq, bool front=false);
130     bool must_replace_vector(IRQn_Type irq);
131     int get_irq_index(IRQn_Type irq);
132     void irq_helper();
133     void add_helper(void (*function)(void), IRQn_Type irq, bool front=false);
134     static void static_irq_helper();
135
136     CallChain* _chains[NVIC_NUM_VECTORS];
137     static InterruptManager* _instance;
138 };
139
140 } // namespace mbed
141
142 #endif
143