Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
InterruptManager.cpp
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 #include "cmsis.h" 00017 #if defined(NVIC_NUM_VECTORS) 00018 00019 #include "drivers/InterruptManager.h" 00020 #include "platform/critical.h" 00021 #include <string.h> 00022 00023 #define CHAIN_INITIAL_SIZE 4 00024 00025 namespace mbed { 00026 00027 typedef void (*pvoidf)(void); 00028 00029 InterruptManager* InterruptManager::_instance = (InterruptManager*)NULL; 00030 00031 InterruptManager* InterruptManager::get() { 00032 00033 if (NULL == _instance) { 00034 InterruptManager* temp = new InterruptManager(); 00035 00036 // Atomically set _instance 00037 core_util_critical_section_enter(); 00038 if (NULL == _instance) { 00039 _instance = temp; 00040 } 00041 core_util_critical_section_exit(); 00042 00043 // Another thread got there first so delete ours 00044 if (temp != _instance) { 00045 delete temp; 00046 } 00047 00048 } 00049 return _instance; 00050 } 00051 00052 InterruptManager::InterruptManager() { 00053 // No mutex needed in constructor 00054 memset(_chains, 0, NVIC_NUM_VECTORS * sizeof(CallChain*)); 00055 } 00056 00057 void InterruptManager::destroy() { 00058 // Not a good idea to call this unless NO interrupt at all 00059 // is under the control of the handler; otherwise, a system crash 00060 // is very likely to occur 00061 if (NULL != _instance) { 00062 delete _instance; 00063 _instance = (InterruptManager*)NULL; 00064 } 00065 } 00066 00067 InterruptManager::~InterruptManager() { 00068 for(int i = 0; i < NVIC_NUM_VECTORS; i++) 00069 if (NULL != _chains[i]) 00070 delete _chains[i]; 00071 } 00072 00073 bool InterruptManager::must_replace_vector(IRQn_Type irq) { 00074 lock(); 00075 00076 int ret = false; 00077 int irq_pos = get_irq_index(irq); 00078 if (NULL == _chains[irq_pos]) { 00079 _chains[irq_pos] = new CallChain(CHAIN_INITIAL_SIZE); 00080 _chains[irq_pos]->add((pvoidf)NVIC_GetVector(irq)); 00081 ret = true; 00082 } 00083 unlock(); 00084 return ret; 00085 } 00086 00087 pFunctionPointer_t InterruptManager::add_common(void (*function)(void), IRQn_Type irq, bool front) { 00088 lock(); 00089 int irq_pos = get_irq_index(irq); 00090 bool change = must_replace_vector(irq); 00091 00092 pFunctionPointer_t pf = front ? _chains[irq_pos]->add_front(function) : _chains[irq_pos]->add(function); 00093 if (change) 00094 NVIC_SetVector(irq, (uint32_t)&InterruptManager::static_irq_helper); 00095 unlock(); 00096 return pf; 00097 } 00098 00099 bool InterruptManager::remove_handler(pFunctionPointer_t handler, IRQn_Type irq) { 00100 int irq_pos = get_irq_index(irq); 00101 bool ret = false; 00102 00103 lock(); 00104 if (_chains[irq_pos] != NULL) { 00105 if (_chains[irq_pos]->remove(handler)) { 00106 ret = true; 00107 } 00108 } 00109 unlock(); 00110 00111 return ret; 00112 } 00113 00114 void InterruptManager::irq_helper() { 00115 _chains[__get_IPSR()]->call(); 00116 } 00117 00118 int InterruptManager::get_irq_index(IRQn_Type irq) { 00119 // Pure function - no lock needed 00120 return (int)irq + NVIC_USER_IRQ_OFFSET; 00121 } 00122 00123 void InterruptManager::static_irq_helper() { 00124 InterruptManager::get()->irq_helper(); 00125 } 00126 00127 void InterruptManager::lock() { 00128 _mutex.lock(); 00129 } 00130 00131 void InterruptManager::unlock() { 00132 _mutex.unlock(); 00133 } 00134 00135 } // namespace mbed 00136 00137 #endif
Generated on Tue Jul 12 2022 10:59:56 by
