Includes library modifications to allow access to AIN_4 (AIN_0 / 5)

Committer:
bryantaylor
Date:
Tue Sep 20 21:26:12 2016 +0000
Revision:
0:eafc3fd41f75
hackathon

Who changed what in which revision?

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