Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers InterruptManager.cpp Source File

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 // Suppress deprecation warnings since this whole
00020 // class is deprecated already
00021 #include "mbed_toolchain.h"
00022 #undef MBED_DEPRECATED_SINCE
00023 #define MBED_DEPRECATED_SINCE(...)
00024 
00025 #include "drivers/InterruptManager.h"
00026 #include "platform/mbed_critical.h"
00027 #include <string.h>
00028 
00029 #define CHAIN_INITIAL_SIZE    4
00030 
00031 namespace mbed {
00032 
00033 typedef void (*pvoidf)(void);
00034 
00035 InterruptManager *InterruptManager::_instance = (InterruptManager *)NULL;
00036 
00037 InterruptManager *InterruptManager::get()
00038 {
00039 
00040     if (NULL == _instance) {
00041         InterruptManager *temp = new InterruptManager();
00042 
00043         // Atomically set _instance
00044         core_util_critical_section_enter();
00045         if (NULL == _instance) {
00046             _instance = temp;
00047         }
00048         core_util_critical_section_exit();
00049 
00050         // Another thread got there first so delete ours
00051         if (temp != _instance) {
00052             delete temp;
00053         }
00054 
00055     }
00056     return _instance;
00057 }
00058 
00059 InterruptManager::InterruptManager()
00060 {
00061     // No mutex needed in constructor
00062     memset(_chains, 0, NVIC_NUM_VECTORS * sizeof(CallChain *));
00063 }
00064 
00065 void InterruptManager::destroy()
00066 {
00067     // Not a good idea to call this unless NO interrupt at all
00068     // is under the control of the handler; otherwise, a system crash
00069     // is very likely to occur
00070     if (NULL != _instance) {
00071         delete _instance;
00072         _instance = (InterruptManager *)NULL;
00073     }
00074 }
00075 
00076 InterruptManager::~InterruptManager()
00077 {
00078     for (int i = 0; i < NVIC_NUM_VECTORS; i++)
00079         if (NULL != _chains[i]) {
00080             delete _chains[i];
00081         }
00082 }
00083 
00084 bool InterruptManager::must_replace_vector(IRQn_Type irq)
00085 {
00086     lock();
00087 
00088     int ret = false;
00089     int irq_pos = get_irq_index(irq);
00090     if (NULL == _chains[irq_pos]) {
00091         _chains[irq_pos] = new CallChain(CHAIN_INITIAL_SIZE);
00092         _chains[irq_pos]->add((pvoidf)NVIC_GetVector(irq));
00093         ret = true;
00094     }
00095     unlock();
00096     return ret;
00097 }
00098 
00099 pFunctionPointer_t InterruptManager::add_common(void (*function)(void), IRQn_Type irq, bool front)
00100 {
00101     lock();
00102     int irq_pos = get_irq_index(irq);
00103     bool change = must_replace_vector(irq);
00104 
00105     pFunctionPointer_t pf = front ? _chains[irq_pos]->add_front(function) : _chains[irq_pos]->add(function);
00106     if (change) {
00107         NVIC_SetVector(irq, (uint32_t)&InterruptManager::static_irq_helper);
00108     }
00109     unlock();
00110     return pf;
00111 }
00112 
00113 bool InterruptManager::remove_handler(pFunctionPointer_t handler, IRQn_Type irq)
00114 {
00115     int irq_pos = get_irq_index(irq);
00116     bool ret = false;
00117 
00118     lock();
00119     if (_chains[irq_pos] != NULL) {
00120         if (_chains[irq_pos]->remove(handler)) {
00121             ret = true;
00122         }
00123     }
00124     unlock();
00125 
00126     return ret;
00127 }
00128 
00129 void InterruptManager::irq_helper()
00130 {
00131     _chains[__get_IPSR()]->call();
00132 }
00133 
00134 int InterruptManager::get_irq_index(IRQn_Type irq)
00135 {
00136     // Pure function - no lock needed
00137     return (int)irq + NVIC_USER_IRQ_OFFSET;
00138 }
00139 
00140 void InterruptManager::static_irq_helper()
00141 {
00142     InterruptManager::get()->irq_helper();
00143 }
00144 
00145 void InterruptManager::lock()
00146 {
00147     _mutex.lock();
00148 }
00149 
00150 void InterruptManager::unlock()
00151 {
00152     _mutex.unlock();
00153 }
00154 
00155 } // namespace mbed
00156 
00157 #endif