WORKS

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Committer:
cyberjoey
Date:
Sat Oct 22 01:31:58 2016 +0000
Revision:
9:6bb35cef007d
Parent:
1:55a6170b404f
WORKING

Who changed what in which revision?

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