- fix F411 F334 systeminit when HSI used - portinout always read IDR regardless of port direction

Fork of mbed-src by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers InterruptManager.cpp Source File

InterruptManager.cpp

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