mbed SDK library sources

Fork of mbed-src by mbed official

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Tue Feb 11 15:00:06 2014 +0000
Revision:
89:9655231f5786
Parent:
15:4892fe388435
Synchronized with git revision 17499c34d273f02497e0706d3abc516b12f3fc62

Full URL: https://github.com/mbedmicro/mbed/commit/17499c34d273f02497e0706d3abc516b12f3fc62/

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