MCU driver/HAL for the Picocell Gateway concentrator board. The firmware implements either a USB CDC protocol or a UART protocol to bridge commands coming from host to the SX1308 SPI interface.

Committer:
dgabino
Date:
Wed Apr 11 14:42:47 2018 +0000
Revision:
0:c76361bd82e8
Initial commit

Who changed what in which revision?

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