1232

Committer:
ganlikun
Date:
Mon Oct 24 15:19:39 2022 +0000
Revision:
0:06036f8bee2d
11

Who changed what in which revision?

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