PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)
Embed:
(wiki syntax)
Show/hide line numbers
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 21:03:50 by 1.7.2