mbed library sources

Dependents:   PA_Boost_test

Fork of mbed-src by mbed official

Committer:
bogdanm
Date:
Wed Aug 07 16:43:59 2013 +0300
Revision:
15:4892fe388435
Child:
221:8276e3a4886f
Added LPC4088 target and interrupt chaining code

Who changed what in which revision?

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