customized mbed library sources for nrf51822

Dependents:   Grove_Node Potentiometer BLE_Beacon I2C_Scanner

Committer:
yihui
Date:
Tue Nov 04 07:38:53 2014 +0000
Revision:
0:700cadd8b708
customized mbed-src library for nrf51822

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 0:700cadd8b708 1 #include "InterruptManager.h"
yihui 0:700cadd8b708 2 #include <string.h>
yihui 0:700cadd8b708 3
yihui 0:700cadd8b708 4 #define CHAIN_INITIAL_SIZE 4
yihui 0:700cadd8b708 5
yihui 0:700cadd8b708 6 namespace mbed {
yihui 0:700cadd8b708 7
yihui 0:700cadd8b708 8 typedef void (*pvoidf)(void);
yihui 0:700cadd8b708 9
yihui 0:700cadd8b708 10 InterruptManager* InterruptManager::_instance = (InterruptManager*)NULL;
yihui 0:700cadd8b708 11
yihui 0:700cadd8b708 12 InterruptManager* InterruptManager::get() {
yihui 0:700cadd8b708 13 if (NULL == _instance)
yihui 0:700cadd8b708 14 _instance = new InterruptManager();
yihui 0:700cadd8b708 15 return _instance;
yihui 0:700cadd8b708 16 }
yihui 0:700cadd8b708 17
yihui 0:700cadd8b708 18 InterruptManager::InterruptManager() {
yihui 0:700cadd8b708 19 memset(_chains, 0, NVIC_NUM_VECTORS * sizeof(CallChain*));
yihui 0:700cadd8b708 20 }
yihui 0:700cadd8b708 21
yihui 0:700cadd8b708 22 void InterruptManager::destroy() {
yihui 0:700cadd8b708 23 // Not a good idea to call this unless NO interrupt at all
yihui 0:700cadd8b708 24 // is under the control of the handler; otherwise, a system crash
yihui 0:700cadd8b708 25 // is very likely to occur
yihui 0:700cadd8b708 26 if (NULL != _instance) {
yihui 0:700cadd8b708 27 delete _instance;
yihui 0:700cadd8b708 28 _instance = (InterruptManager*)NULL;
yihui 0:700cadd8b708 29 }
yihui 0:700cadd8b708 30 }
yihui 0:700cadd8b708 31
yihui 0:700cadd8b708 32 InterruptManager::~InterruptManager() {
yihui 0:700cadd8b708 33 for(int i = 0; i < NVIC_NUM_VECTORS; i++)
yihui 0:700cadd8b708 34 if (NULL != _chains[i])
yihui 0:700cadd8b708 35 delete _chains[i];
yihui 0:700cadd8b708 36 }
yihui 0:700cadd8b708 37
yihui 0:700cadd8b708 38 bool InterruptManager::must_replace_vector(IRQn_Type irq) {
yihui 0:700cadd8b708 39 int irq_pos = get_irq_index(irq);
yihui 0:700cadd8b708 40
yihui 0:700cadd8b708 41 if (NULL == _chains[irq_pos]) {
yihui 0:700cadd8b708 42 _chains[irq_pos] = new CallChain(CHAIN_INITIAL_SIZE);
yihui 0:700cadd8b708 43 _chains[irq_pos]->add((pvoidf)NVIC_GetVector(irq));
yihui 0:700cadd8b708 44 return true;
yihui 0:700cadd8b708 45 }
yihui 0:700cadd8b708 46 return false;
yihui 0:700cadd8b708 47 }
yihui 0:700cadd8b708 48
yihui 0:700cadd8b708 49 pFunctionPointer_t InterruptManager::add_common(void (*function)(void), IRQn_Type irq, bool front) {
yihui 0:700cadd8b708 50 int irq_pos = get_irq_index(irq);
yihui 0:700cadd8b708 51 bool change = must_replace_vector(irq);
yihui 0:700cadd8b708 52
yihui 0:700cadd8b708 53 pFunctionPointer_t pf = front ? _chains[irq_pos]->add_front(function) : _chains[irq_pos]->add(function);
yihui 0:700cadd8b708 54 if (change)
yihui 0:700cadd8b708 55 NVIC_SetVector(irq, (uint32_t)&InterruptManager::static_irq_helper);
yihui 0:700cadd8b708 56 return pf;
yihui 0:700cadd8b708 57 }
yihui 0:700cadd8b708 58
yihui 0:700cadd8b708 59 bool InterruptManager::remove_handler(pFunctionPointer_t handler, IRQn_Type irq) {
yihui 0:700cadd8b708 60 int irq_pos = get_irq_index(irq);
yihui 0:700cadd8b708 61
yihui 0:700cadd8b708 62 if (NULL == _chains[irq_pos])
yihui 0:700cadd8b708 63 return false;
yihui 0:700cadd8b708 64 if (!_chains[irq_pos]->remove(handler))
yihui 0:700cadd8b708 65 return false;
yihui 0:700cadd8b708 66 // If there's a single function left in the chain, swith the interrupt vector
yihui 0:700cadd8b708 67 // to call that function directly. This way we save both time and space.
yihui 0:700cadd8b708 68 if (_chains[irq_pos]->size() == 1 && NULL != _chains[irq_pos]->get(0)->get_function()) {
yihui 0:700cadd8b708 69 NVIC_SetVector(irq, (uint32_t)_chains[irq_pos]->get(0)->get_function());
yihui 0:700cadd8b708 70 delete _chains[irq_pos];
yihui 0:700cadd8b708 71 _chains[irq_pos] = (CallChain*) NULL;
yihui 0:700cadd8b708 72 }
yihui 0:700cadd8b708 73 return true;
yihui 0:700cadd8b708 74 }
yihui 0:700cadd8b708 75
yihui 0:700cadd8b708 76 void InterruptManager::irq_helper() {
yihui 0:700cadd8b708 77 _chains[__get_IPSR()]->call();
yihui 0:700cadd8b708 78 }
yihui 0:700cadd8b708 79
yihui 0:700cadd8b708 80 int InterruptManager::get_irq_index(IRQn_Type irq) {
yihui 0:700cadd8b708 81 return (int)irq + NVIC_USER_IRQ_OFFSET;
yihui 0:700cadd8b708 82 }
yihui 0:700cadd8b708 83
yihui 0:700cadd8b708 84 void InterruptManager::static_irq_helper() {
yihui 0:700cadd8b708 85 InterruptManager::get()->irq_helper();
yihui 0:700cadd8b708 86 }
yihui 0:700cadd8b708 87
yihui 0:700cadd8b708 88 } // namespace mbed
yihui 0:700cadd8b708 89