mbed-os

Fork of mbed-os by erkin yucel

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /* mbed Microcontroller Library
elessair 0:f269e3021894 2 * Copyright (c) 2006-2013 ARM Limited
elessair 0:f269e3021894 3 *
elessair 0:f269e3021894 4 * Licensed under the Apache License, Version 2.0 (the "License");
elessair 0:f269e3021894 5 * you may not use this file except in compliance with the License.
elessair 0:f269e3021894 6 * You may obtain a copy of the License at
elessair 0:f269e3021894 7 *
elessair 0:f269e3021894 8 * http://www.apache.org/licenses/LICENSE-2.0
elessair 0:f269e3021894 9 *
elessair 0:f269e3021894 10 * Unless required by applicable law or agreed to in writing, software
elessair 0:f269e3021894 11 * distributed under the License is distributed on an "AS IS" BASIS,
elessair 0:f269e3021894 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
elessair 0:f269e3021894 13 * See the License for the specific language governing permissions and
elessair 0:f269e3021894 14 * limitations under the License.
elessair 0:f269e3021894 15 */
elessair 0:f269e3021894 16 #ifndef MBED_INTERRUPTMANAGER_H
elessair 0:f269e3021894 17 #define MBED_INTERRUPTMANAGER_H
elessair 0:f269e3021894 18
elessair 0:f269e3021894 19 #include "cmsis.h"
elessair 0:f269e3021894 20 #include "platform/CallChain.h"
elessair 0:f269e3021894 21 #include "platform/PlatformMutex.h"
elessair 0:f269e3021894 22 #include <string.h>
elessair 0:f269e3021894 23
elessair 0:f269e3021894 24 namespace mbed {
elessair 0:f269e3021894 25 /** \addtogroup drivers */
elessair 0:f269e3021894 26 /** @{*/
elessair 0:f269e3021894 27
elessair 0:f269e3021894 28 /** Use this singleton if you need to chain interrupt handlers.
elessair 0:f269e3021894 29 *
elessair 0:f269e3021894 30 * @Note Synchronization level: Thread safe
elessair 0:f269e3021894 31 *
elessair 0:f269e3021894 32 * Example (for LPC1768):
elessair 0:f269e3021894 33 * @code
elessair 0:f269e3021894 34 * #include "InterruptManager.h"
elessair 0:f269e3021894 35 * #include "mbed.h"
elessair 0:f269e3021894 36 *
elessair 0:f269e3021894 37 * Ticker flipper;
elessair 0:f269e3021894 38 * DigitalOut led1(LED1);
elessair 0:f269e3021894 39 * DigitalOut led2(LED2);
elessair 0:f269e3021894 40 *
elessair 0:f269e3021894 41 * void flip(void) {
elessair 0:f269e3021894 42 * led1 = !led1;
elessair 0:f269e3021894 43 * }
elessair 0:f269e3021894 44 *
elessair 0:f269e3021894 45 * void handler(void) {
elessair 0:f269e3021894 46 * led2 = !led1;
elessair 0:f269e3021894 47 * }
elessair 0:f269e3021894 48 *
elessair 0:f269e3021894 49 * int main() {
elessair 0:f269e3021894 50 * led1 = led2 = 0;
elessair 0:f269e3021894 51 * flipper.attach(&flip, 1.0);
elessair 0:f269e3021894 52 * InterruptManager::get()->add_handler(handler, TIMER3_IRQn);
elessair 0:f269e3021894 53 * }
elessair 0:f269e3021894 54 * @endcode
elessair 0:f269e3021894 55 */
elessair 0:f269e3021894 56 class InterruptManager {
elessair 0:f269e3021894 57 public:
elessair 0:f269e3021894 58 /** Return the only instance of this class
elessair 0:f269e3021894 59 */
elessair 0:f269e3021894 60 static InterruptManager* get();
elessair 0:f269e3021894 61
elessair 0:f269e3021894 62 /** Destroy the current instance of the interrupt manager
elessair 0:f269e3021894 63 */
elessair 0:f269e3021894 64 static void destroy();
elessair 0:f269e3021894 65
elessair 0:f269e3021894 66 /** Add a handler for an interrupt at the end of the handler list
elessair 0:f269e3021894 67 *
elessair 0:f269e3021894 68 * @param function the handler to add
elessair 0:f269e3021894 69 * @param irq interrupt number
elessair 0:f269e3021894 70 *
elessair 0:f269e3021894 71 * @returns
elessair 0:f269e3021894 72 * The function object created for 'function'
elessair 0:f269e3021894 73 */
elessair 0:f269e3021894 74 pFunctionPointer_t add_handler(void (*function)(void), IRQn_Type irq) {
elessair 0:f269e3021894 75 // Underlying call is thread safe
elessair 0:f269e3021894 76 return add_common(function, irq);
elessair 0:f269e3021894 77 }
elessair 0:f269e3021894 78
elessair 0:f269e3021894 79 /** Add a handler for an interrupt at the beginning of the handler list
elessair 0:f269e3021894 80 *
elessair 0:f269e3021894 81 * @param function the handler to add
elessair 0:f269e3021894 82 * @param irq interrupt number
elessair 0:f269e3021894 83 *
elessair 0:f269e3021894 84 * @returns
elessair 0:f269e3021894 85 * The function object created for 'function'
elessair 0:f269e3021894 86 */
elessair 0:f269e3021894 87 pFunctionPointer_t add_handler_front(void (*function)(void), IRQn_Type irq) {
elessair 0:f269e3021894 88 // Underlying call is thread safe
elessair 0:f269e3021894 89 return add_common(function, irq, true);
elessair 0:f269e3021894 90 }
elessair 0:f269e3021894 91
elessair 0:f269e3021894 92 /** Add a handler for an interrupt at the end of the handler list
elessair 0:f269e3021894 93 *
elessair 0:f269e3021894 94 * @param tptr pointer to the object that has the handler function
elessair 0:f269e3021894 95 * @param mptr pointer to the actual handler function
elessair 0:f269e3021894 96 * @param irq interrupt number
elessair 0:f269e3021894 97 *
elessair 0:f269e3021894 98 * @returns
elessair 0:f269e3021894 99 * The function object created for 'tptr' and 'mptr'
elessair 0:f269e3021894 100 */
elessair 0:f269e3021894 101 template<typename T>
elessair 0:f269e3021894 102 pFunctionPointer_t add_handler(T* tptr, void (T::*mptr)(void), IRQn_Type irq) {
elessair 0:f269e3021894 103 // Underlying call is thread safe
elessair 0:f269e3021894 104 return add_common(tptr, mptr, irq);
elessair 0:f269e3021894 105 }
elessair 0:f269e3021894 106
elessair 0:f269e3021894 107 /** Add a handler for an interrupt at the beginning of the handler list
elessair 0:f269e3021894 108 *
elessair 0:f269e3021894 109 * @param tptr pointer to the object that has the handler function
elessair 0:f269e3021894 110 * @param mptr pointer to the actual handler function
elessair 0:f269e3021894 111 * @param irq interrupt number
elessair 0:f269e3021894 112 *
elessair 0:f269e3021894 113 * @returns
elessair 0:f269e3021894 114 * The function object created for 'tptr' and 'mptr'
elessair 0:f269e3021894 115 */
elessair 0:f269e3021894 116 template<typename T>
elessair 0:f269e3021894 117 pFunctionPointer_t add_handler_front(T* tptr, void (T::*mptr)(void), IRQn_Type irq) {
elessair 0:f269e3021894 118 // Underlying call is thread safe
elessair 0:f269e3021894 119 return add_common(tptr, mptr, irq, true);
elessair 0:f269e3021894 120 }
elessair 0:f269e3021894 121
elessair 0:f269e3021894 122 /** Remove a handler from an interrupt
elessair 0:f269e3021894 123 *
elessair 0:f269e3021894 124 * @param handler the function object for the handler to remove
elessair 0:f269e3021894 125 * @param irq the interrupt number
elessair 0:f269e3021894 126 *
elessair 0:f269e3021894 127 * @returns
elessair 0:f269e3021894 128 * true if the handler was found and removed, false otherwise
elessair 0:f269e3021894 129 */
elessair 0:f269e3021894 130 bool remove_handler(pFunctionPointer_t handler, IRQn_Type irq);
elessair 0:f269e3021894 131
elessair 0:f269e3021894 132 private:
elessair 0:f269e3021894 133 InterruptManager();
elessair 0:f269e3021894 134 ~InterruptManager();
elessair 0:f269e3021894 135
elessair 0:f269e3021894 136 void lock();
elessair 0:f269e3021894 137 void unlock();
elessair 0:f269e3021894 138
elessair 0:f269e3021894 139 // We declare the copy contructor and the assignment operator, but we don't
elessair 0:f269e3021894 140 // implement them. This way, if someone tries to copy/assign our instance,
elessair 0:f269e3021894 141 // he will get an error at compile time.
elessair 0:f269e3021894 142 InterruptManager(const InterruptManager&);
elessair 0:f269e3021894 143 InterruptManager& operator =(const InterruptManager&);
elessair 0:f269e3021894 144
elessair 0:f269e3021894 145 template<typename T>
elessair 0:f269e3021894 146 pFunctionPointer_t add_common(T *tptr, void (T::*mptr)(void), IRQn_Type irq, bool front=false) {
elessair 0:f269e3021894 147 _mutex.lock();
elessair 0:f269e3021894 148 int irq_pos = get_irq_index(irq);
elessair 0:f269e3021894 149 bool change = must_replace_vector(irq);
elessair 0:f269e3021894 150
elessair 0:f269e3021894 151 pFunctionPointer_t pf = front ? _chains[irq_pos]->add_front(tptr, mptr) : _chains[irq_pos]->add(tptr, mptr);
elessair 0:f269e3021894 152 if (change)
elessair 0:f269e3021894 153 NVIC_SetVector(irq, (uint32_t)&InterruptManager::static_irq_helper);
elessair 0:f269e3021894 154 _mutex.unlock();
elessair 0:f269e3021894 155 return pf;
elessair 0:f269e3021894 156 }
elessair 0:f269e3021894 157
elessair 0:f269e3021894 158 pFunctionPointer_t add_common(void (*function)(void), IRQn_Type irq, bool front=false);
elessair 0:f269e3021894 159 bool must_replace_vector(IRQn_Type irq);
elessair 0:f269e3021894 160 int get_irq_index(IRQn_Type irq);
elessair 0:f269e3021894 161 void irq_helper();
elessair 0:f269e3021894 162 void add_helper(void (*function)(void), IRQn_Type irq, bool front=false);
elessair 0:f269e3021894 163 static void static_irq_helper();
elessair 0:f269e3021894 164
elessair 0:f269e3021894 165 CallChain* _chains[NVIC_NUM_VECTORS];
elessair 0:f269e3021894 166 static InterruptManager* _instance;
elessair 0:f269e3021894 167 PlatformMutex _mutex;
elessair 0:f269e3021894 168 };
elessair 0:f269e3021894 169
elessair 0:f269e3021894 170 } // namespace mbed
elessair 0:f269e3021894 171
elessair 0:f269e3021894 172 #endif
elessair 0:f269e3021894 173
elessair 0:f269e3021894 174
elessair 0:f269e3021894 175 /** @}*/