Elijah Stanger-Jones / mbed-dev-f303
Committer:
elijahsj
Date:
Mon Nov 09 00:02:47 2020 -0500
Revision:
1:8a094db1347f
test

Who changed what in which revision?

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