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.
Fork of mbed-dev by
InterruptManager.cpp
00001 #include "cmsis.h" 00002 #if defined(NVIC_NUM_VECTORS) 00003 00004 #include "InterruptManager.h" 00005 #include <string.h> 00006 00007 #define CHAIN_INITIAL_SIZE 4 00008 00009 namespace mbed { 00010 00011 typedef void (*pvoidf)(void); 00012 00013 InterruptManager* InterruptManager::_instance = (InterruptManager*)NULL; 00014 00015 InterruptManager* InterruptManager::get() { 00016 if (NULL == _instance) 00017 _instance = new InterruptManager(); 00018 return _instance; 00019 } 00020 00021 InterruptManager::InterruptManager() { 00022 memset(_chains, 0, NVIC_NUM_VECTORS * sizeof(CallChain*)); 00023 } 00024 00025 void InterruptManager::destroy() { 00026 // Not a good idea to call this unless NO interrupt at all 00027 // is under the control of the handler; otherwise, a system crash 00028 // is very likely to occur 00029 if (NULL != _instance) { 00030 delete _instance; 00031 _instance = (InterruptManager*)NULL; 00032 } 00033 } 00034 00035 InterruptManager::~InterruptManager() { 00036 for(int i = 0; i < NVIC_NUM_VECTORS; i++) 00037 if (NULL != _chains[i]) 00038 delete _chains[i]; 00039 } 00040 00041 bool InterruptManager::must_replace_vector(IRQn_Type irq) { 00042 int irq_pos = get_irq_index(irq); 00043 00044 if (NULL == _chains[irq_pos]) { 00045 _chains[irq_pos] = new CallChain(CHAIN_INITIAL_SIZE); 00046 _chains[irq_pos]->add((pvoidf)NVIC_GetVector(irq)); 00047 return true; 00048 } 00049 return false; 00050 } 00051 00052 pFunctionPointer_t InterruptManager::add_common(void (*function)(void), IRQn_Type irq, bool front) { 00053 int irq_pos = get_irq_index(irq); 00054 bool change = must_replace_vector(irq); 00055 00056 pFunctionPointer_t pf = front ? _chains[irq_pos]->add_front(function) : _chains[irq_pos]->add(function); 00057 if (change) 00058 NVIC_SetVector(irq, (uint32_t)&InterruptManager::static_irq_helper); 00059 return pf; 00060 } 00061 00062 bool InterruptManager::remove_handler(pFunctionPointer_t handler, IRQn_Type irq) { 00063 int irq_pos = get_irq_index(irq); 00064 00065 if (NULL == _chains[irq_pos]) 00066 return false; 00067 if (!_chains[irq_pos]->remove(handler)) 00068 return false; 00069 // If there's a single function left in the chain, swith the interrupt vector 00070 // to call that function directly. This way we save both time and space. 00071 if (_chains[irq_pos]->size() == 1 && NULL != _chains[irq_pos]->get(0)->get_function()) { 00072 NVIC_SetVector(irq, (uint32_t)_chains[irq_pos]->get(0)->get_function()); 00073 delete _chains[irq_pos]; 00074 _chains[irq_pos] = (CallChain*) NULL; 00075 } 00076 return true; 00077 } 00078 00079 void InterruptManager::irq_helper() { 00080 _chains[__get_IPSR()]->call(); 00081 } 00082 00083 int InterruptManager::get_irq_index(IRQn_Type irq) { 00084 return (int)irq + NVIC_USER_IRQ_OFFSET; 00085 } 00086 00087 void InterruptManager::static_irq_helper() { 00088 InterruptManager::get()->irq_helper(); 00089 } 00090 00091 } // namespace mbed 00092 00093 #endif
Generated on Tue Jul 12 2022 18:56:14 by
