This fork captures the mbed lib v125 for ease of integration into older projects.

Fork of mbed-dev by mbed official

Committer:
apluscw
Date:
Fri Jul 20 21:24:42 2018 +0000
Revision:
187:92cbb9eec47b
Mbed library with source code from mbed lib v125. Posted to ease integration with some older projects.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
apluscw 187:92cbb9eec47b 1 #include "cmsis.h"
apluscw 187:92cbb9eec47b 2 #if defined(NVIC_NUM_VECTORS)
apluscw 187:92cbb9eec47b 3
apluscw 187:92cbb9eec47b 4 #include "InterruptManager.h"
apluscw 187:92cbb9eec47b 5 #include "critical.h"
apluscw 187:92cbb9eec47b 6 #include <string.h>
apluscw 187:92cbb9eec47b 7
apluscw 187:92cbb9eec47b 8 #define CHAIN_INITIAL_SIZE 4
apluscw 187:92cbb9eec47b 9
apluscw 187:92cbb9eec47b 10 namespace mbed {
apluscw 187:92cbb9eec47b 11
apluscw 187:92cbb9eec47b 12 typedef void (*pvoidf)(void);
apluscw 187:92cbb9eec47b 13
apluscw 187:92cbb9eec47b 14 InterruptManager* InterruptManager::_instance = (InterruptManager*)NULL;
apluscw 187:92cbb9eec47b 15
apluscw 187:92cbb9eec47b 16 InterruptManager* InterruptManager::get() {
apluscw 187:92cbb9eec47b 17
apluscw 187:92cbb9eec47b 18 if (NULL == _instance) {
apluscw 187:92cbb9eec47b 19 InterruptManager* temp = new InterruptManager();
apluscw 187:92cbb9eec47b 20
apluscw 187:92cbb9eec47b 21 // Atomically set _instance
apluscw 187:92cbb9eec47b 22 core_util_critical_section_enter();
apluscw 187:92cbb9eec47b 23 if (NULL == _instance) {
apluscw 187:92cbb9eec47b 24 _instance = temp;
apluscw 187:92cbb9eec47b 25 }
apluscw 187:92cbb9eec47b 26 core_util_critical_section_exit();
apluscw 187:92cbb9eec47b 27
apluscw 187:92cbb9eec47b 28 // Another thread got there first so delete ours
apluscw 187:92cbb9eec47b 29 if (temp != _instance) {
apluscw 187:92cbb9eec47b 30 delete temp;
apluscw 187:92cbb9eec47b 31 }
apluscw 187:92cbb9eec47b 32
apluscw 187:92cbb9eec47b 33 }
apluscw 187:92cbb9eec47b 34 return _instance;
apluscw 187:92cbb9eec47b 35 }
apluscw 187:92cbb9eec47b 36
apluscw 187:92cbb9eec47b 37 InterruptManager::InterruptManager() {
apluscw 187:92cbb9eec47b 38 // No mutex needed in constructor
apluscw 187:92cbb9eec47b 39 memset(_chains, 0, NVIC_NUM_VECTORS * sizeof(CallChain*));
apluscw 187:92cbb9eec47b 40 }
apluscw 187:92cbb9eec47b 41
apluscw 187:92cbb9eec47b 42 void InterruptManager::destroy() {
apluscw 187:92cbb9eec47b 43 // Not a good idea to call this unless NO interrupt at all
apluscw 187:92cbb9eec47b 44 // is under the control of the handler; otherwise, a system crash
apluscw 187:92cbb9eec47b 45 // is very likely to occur
apluscw 187:92cbb9eec47b 46 if (NULL != _instance) {
apluscw 187:92cbb9eec47b 47 delete _instance;
apluscw 187:92cbb9eec47b 48 _instance = (InterruptManager*)NULL;
apluscw 187:92cbb9eec47b 49 }
apluscw 187:92cbb9eec47b 50 }
apluscw 187:92cbb9eec47b 51
apluscw 187:92cbb9eec47b 52 InterruptManager::~InterruptManager() {
apluscw 187:92cbb9eec47b 53 for(int i = 0; i < NVIC_NUM_VECTORS; i++)
apluscw 187:92cbb9eec47b 54 if (NULL != _chains[i])
apluscw 187:92cbb9eec47b 55 delete _chains[i];
apluscw 187:92cbb9eec47b 56 }
apluscw 187:92cbb9eec47b 57
apluscw 187:92cbb9eec47b 58 bool InterruptManager::must_replace_vector(IRQn_Type irq) {
apluscw 187:92cbb9eec47b 59 lock();
apluscw 187:92cbb9eec47b 60
apluscw 187:92cbb9eec47b 61 int ret = false;
apluscw 187:92cbb9eec47b 62 int irq_pos = get_irq_index(irq);
apluscw 187:92cbb9eec47b 63 if (NULL == _chains[irq_pos]) {
apluscw 187:92cbb9eec47b 64 _chains[irq_pos] = new CallChain(CHAIN_INITIAL_SIZE);
apluscw 187:92cbb9eec47b 65 _chains[irq_pos]->add((pvoidf)NVIC_GetVector(irq));
apluscw 187:92cbb9eec47b 66 ret = true;
apluscw 187:92cbb9eec47b 67 }
apluscw 187:92cbb9eec47b 68 unlock();
apluscw 187:92cbb9eec47b 69 return ret;
apluscw 187:92cbb9eec47b 70 }
apluscw 187:92cbb9eec47b 71
apluscw 187:92cbb9eec47b 72 pFunctionPointer_t InterruptManager::add_common(void (*function)(void), IRQn_Type irq, bool front) {
apluscw 187:92cbb9eec47b 73 lock();
apluscw 187:92cbb9eec47b 74 int irq_pos = get_irq_index(irq);
apluscw 187:92cbb9eec47b 75 bool change = must_replace_vector(irq);
apluscw 187:92cbb9eec47b 76
apluscw 187:92cbb9eec47b 77 pFunctionPointer_t pf = front ? _chains[irq_pos]->add_front(function) : _chains[irq_pos]->add(function);
apluscw 187:92cbb9eec47b 78 if (change)
apluscw 187:92cbb9eec47b 79 NVIC_SetVector(irq, (uint32_t)&InterruptManager::static_irq_helper);
apluscw 187:92cbb9eec47b 80 unlock();
apluscw 187:92cbb9eec47b 81 return pf;
apluscw 187:92cbb9eec47b 82 }
apluscw 187:92cbb9eec47b 83
apluscw 187:92cbb9eec47b 84 bool InterruptManager::remove_handler(pFunctionPointer_t handler, IRQn_Type irq) {
apluscw 187:92cbb9eec47b 85 int irq_pos = get_irq_index(irq);
apluscw 187:92cbb9eec47b 86 bool ret = false;
apluscw 187:92cbb9eec47b 87
apluscw 187:92cbb9eec47b 88 lock();
apluscw 187:92cbb9eec47b 89 if (_chains[irq_pos] != NULL) {
apluscw 187:92cbb9eec47b 90 if (_chains[irq_pos]->remove(handler)) {
apluscw 187:92cbb9eec47b 91 ret = true;
apluscw 187:92cbb9eec47b 92 }
apluscw 187:92cbb9eec47b 93 }
apluscw 187:92cbb9eec47b 94 unlock();
apluscw 187:92cbb9eec47b 95
apluscw 187:92cbb9eec47b 96 return ret;
apluscw 187:92cbb9eec47b 97 }
apluscw 187:92cbb9eec47b 98
apluscw 187:92cbb9eec47b 99 void InterruptManager::irq_helper() {
apluscw 187:92cbb9eec47b 100 _chains[__get_IPSR()]->call();
apluscw 187:92cbb9eec47b 101 }
apluscw 187:92cbb9eec47b 102
apluscw 187:92cbb9eec47b 103 int InterruptManager::get_irq_index(IRQn_Type irq) {
apluscw 187:92cbb9eec47b 104 // Pure function - no lock needed
apluscw 187:92cbb9eec47b 105 return (int)irq + NVIC_USER_IRQ_OFFSET;
apluscw 187:92cbb9eec47b 106 }
apluscw 187:92cbb9eec47b 107
apluscw 187:92cbb9eec47b 108 void InterruptManager::static_irq_helper() {
apluscw 187:92cbb9eec47b 109 InterruptManager::get()->irq_helper();
apluscw 187:92cbb9eec47b 110 }
apluscw 187:92cbb9eec47b 111
apluscw 187:92cbb9eec47b 112 void InterruptManager::lock() {
apluscw 187:92cbb9eec47b 113 _mutex.lock();
apluscw 187:92cbb9eec47b 114 }
apluscw 187:92cbb9eec47b 115
apluscw 187:92cbb9eec47b 116 void InterruptManager::unlock() {
apluscw 187:92cbb9eec47b 117 _mutex.unlock();
apluscw 187:92cbb9eec47b 118 }
apluscw 187:92cbb9eec47b 119
apluscw 187:92cbb9eec47b 120 } // namespace mbed
apluscw 187:92cbb9eec47b 121
apluscw 187:92cbb9eec47b 122 #endif