mbed library sources. Supersedes mbed-src.

Fork of mbed by teralytic

Committer:
rodriguise
Date:
Mon Oct 17 18:47:01 2016 +0000
Revision:
148:4802eb17e82b
Parent:
144:ef7eb2e8f9f7
backup

Who changed what in which revision?

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