2 #if defined(NVIC_NUM_VECTORS)
4 #include "InterruptManager.h"
7 #define CHAIN_INITIAL_SIZE 4
11 typedef void (*pvoidf
)(void);
13 InterruptManager
* InterruptManager::_instance
= (InterruptManager
*)NULL
;
15 InterruptManager
* InterruptManager::get() {
16 if (NULL
== _instance
)
17 _instance
= new InterruptManager();
21 InterruptManager::InterruptManager() {
22 memset(_chains
, 0, NVIC_NUM_VECTORS
* sizeof(CallChain
*));
25 void InterruptManager::destroy() {
26 // Not a good idea to call this unless NO interrupt at all
27 // is under the control of the handler; otherwise, a system crash
28 // is very likely to occur
29 if (NULL
!= _instance
) {
31 _instance
= (InterruptManager
*)NULL
;
35 InterruptManager::~InterruptManager() {
36 for(int i
= 0; i
< NVIC_NUM_VECTORS
; i
++)
37 if (NULL
!= _chains
[i
])
41 bool InterruptManager::must_replace_vector(IRQn_Type irq
) {
42 int irq_pos
= get_irq_index(irq
);
44 if (NULL
== _chains
[irq_pos
]) {
45 _chains
[irq_pos
] = new CallChain(CHAIN_INITIAL_SIZE
);
46 _chains
[irq_pos
]->add((pvoidf
)NVIC_GetVector(irq
));
52 pFunctionPointer_t
InterruptManager::add_common(void (*function
)(void), IRQn_Type irq
, bool front
) {
53 int irq_pos
= get_irq_index(irq
);
54 bool change
= must_replace_vector(irq
);
56 pFunctionPointer_t pf
= front
? _chains
[irq_pos
]->add_front(function
) : _chains
[irq_pos
]->add(function
);
58 NVIC_SetVector(irq
, (uint32_t)&InterruptManager::static_irq_helper
);
62 bool InterruptManager::remove_handler(pFunctionPointer_t handler
, IRQn_Type irq
) {
63 int irq_pos
= get_irq_index(irq
);
65 if (NULL
== _chains
[irq_pos
])
67 if (!_chains
[irq_pos
]->remove(handler
))
69 // If there's a single function left in the chain, swith the interrupt vector
70 // to call that function directly. This way we save both time and space.
71 if (_chains
[irq_pos
]->size() == 1 && NULL
!= _chains
[irq_pos
]->get(0)->get_function()) {
72 NVIC_SetVector(irq
, (uint32_t)_chains
[irq_pos
]->get(0)->get_function());
73 delete _chains
[irq_pos
];
74 _chains
[irq_pos
] = (CallChain
*) NULL
;
79 void InterruptManager::irq_helper() {
80 _chains
[__get_IPSR()]->call();
83 int InterruptManager::get_irq_index(IRQn_Type irq
) {
84 return (int)irq
+ NVIC_USER_IRQ_OFFSET
;
87 void InterruptManager::static_irq_helper() {
88 InterruptManager::get()->irq_helper();