This is the final version of Mini Gateway for Automation and Security desgined for Renesas GR Peach Design Contest

Dependencies:   GR-PEACH_video GraphicsFramework HTTPServer R_BSP mbed-rpc mbed-rtos Socket lwip-eth lwip-sys lwip FATFileSystem

Fork of mbed-os-example-mbed5-blinky by mbed-os-examples

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 #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