Preliminary main mbed library for nexpaq development

Committer:
nexpaq
Date:
Fri Nov 04 20:27:58 2016 +0000
Revision:
0:6c56fb4bc5f0
Moving to library for sharing updates

Who changed what in which revision?

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