mbed library sources. Supersedes mbed-src. Fixes analogIn and analogOut problems for TARGET_STM32F3. Tested on NUCLEO-F303K8, using 3 analogout and 7 analogin channels simultaneously. Added ability for STM32F334R8 and STM32F303K8 to use all three channels of DAC simultaneously. https://developer.mbed.org/users/StevieWray/code/mbed-dev/ Added ability for TARGET_STM32F3 to use more than one ADC simultaneously. https://developer.mbed.org/questions/67997/NUCLEO-F303K8ADC/
Fork of mbed-dev by
common/InterruptManager.cpp@70:b3a5af880266, 2016-02-23 (annotated)
- Committer:
- neurofun
- Date:
- Tue Feb 23 21:59:35 2016 +0000
- Revision:
- 70:b3a5af880266
- Parent:
- 0:9b334a45a8ff
Edited DAC routines to allow for the simultaneous use of three channels from two DACs as seen on the STM32F334R8 and STM32F303K8. Edited ADC routines to allow for the simultaneous use of more than one ADC.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
bogdanm | 0:9b334a45a8ff | 1 | #include "cmsis.h" |
bogdanm | 0:9b334a45a8ff | 2 | #if defined(NVIC_NUM_VECTORS) |
bogdanm | 0:9b334a45a8ff | 3 | |
bogdanm | 0:9b334a45a8ff | 4 | #include "InterruptManager.h" |
bogdanm | 0:9b334a45a8ff | 5 | #include <string.h> |
bogdanm | 0:9b334a45a8ff | 6 | |
bogdanm | 0:9b334a45a8ff | 7 | #define CHAIN_INITIAL_SIZE 4 |
bogdanm | 0:9b334a45a8ff | 8 | |
bogdanm | 0:9b334a45a8ff | 9 | namespace mbed { |
bogdanm | 0:9b334a45a8ff | 10 | |
bogdanm | 0:9b334a45a8ff | 11 | typedef void (*pvoidf)(void); |
bogdanm | 0:9b334a45a8ff | 12 | |
bogdanm | 0:9b334a45a8ff | 13 | InterruptManager* InterruptManager::_instance = (InterruptManager*)NULL; |
bogdanm | 0:9b334a45a8ff | 14 | |
bogdanm | 0:9b334a45a8ff | 15 | InterruptManager* InterruptManager::get() { |
bogdanm | 0:9b334a45a8ff | 16 | if (NULL == _instance) |
bogdanm | 0:9b334a45a8ff | 17 | _instance = new InterruptManager(); |
bogdanm | 0:9b334a45a8ff | 18 | return _instance; |
bogdanm | 0:9b334a45a8ff | 19 | } |
bogdanm | 0:9b334a45a8ff | 20 | |
bogdanm | 0:9b334a45a8ff | 21 | InterruptManager::InterruptManager() { |
bogdanm | 0:9b334a45a8ff | 22 | memset(_chains, 0, NVIC_NUM_VECTORS * sizeof(CallChain*)); |
bogdanm | 0:9b334a45a8ff | 23 | } |
bogdanm | 0:9b334a45a8ff | 24 | |
bogdanm | 0:9b334a45a8ff | 25 | void InterruptManager::destroy() { |
bogdanm | 0:9b334a45a8ff | 26 | // Not a good idea to call this unless NO interrupt at all |
bogdanm | 0:9b334a45a8ff | 27 | // is under the control of the handler; otherwise, a system crash |
bogdanm | 0:9b334a45a8ff | 28 | // is very likely to occur |
bogdanm | 0:9b334a45a8ff | 29 | if (NULL != _instance) { |
bogdanm | 0:9b334a45a8ff | 30 | delete _instance; |
bogdanm | 0:9b334a45a8ff | 31 | _instance = (InterruptManager*)NULL; |
bogdanm | 0:9b334a45a8ff | 32 | } |
bogdanm | 0:9b334a45a8ff | 33 | } |
bogdanm | 0:9b334a45a8ff | 34 | |
bogdanm | 0:9b334a45a8ff | 35 | InterruptManager::~InterruptManager() { |
bogdanm | 0:9b334a45a8ff | 36 | for(int i = 0; i < NVIC_NUM_VECTORS; i++) |
bogdanm | 0:9b334a45a8ff | 37 | if (NULL != _chains[i]) |
bogdanm | 0:9b334a45a8ff | 38 | delete _chains[i]; |
bogdanm | 0:9b334a45a8ff | 39 | } |
bogdanm | 0:9b334a45a8ff | 40 | |
bogdanm | 0:9b334a45a8ff | 41 | bool InterruptManager::must_replace_vector(IRQn_Type irq) { |
bogdanm | 0:9b334a45a8ff | 42 | int irq_pos = get_irq_index(irq); |
bogdanm | 0:9b334a45a8ff | 43 | |
bogdanm | 0:9b334a45a8ff | 44 | if (NULL == _chains[irq_pos]) { |
bogdanm | 0:9b334a45a8ff | 45 | _chains[irq_pos] = new CallChain(CHAIN_INITIAL_SIZE); |
bogdanm | 0:9b334a45a8ff | 46 | _chains[irq_pos]->add((pvoidf)NVIC_GetVector(irq)); |
bogdanm | 0:9b334a45a8ff | 47 | return true; |
bogdanm | 0:9b334a45a8ff | 48 | } |
bogdanm | 0:9b334a45a8ff | 49 | return false; |
bogdanm | 0:9b334a45a8ff | 50 | } |
bogdanm | 0:9b334a45a8ff | 51 | |
bogdanm | 0:9b334a45a8ff | 52 | pFunctionPointer_t InterruptManager::add_common(void (*function)(void), IRQn_Type irq, bool front) { |
bogdanm | 0:9b334a45a8ff | 53 | int irq_pos = get_irq_index(irq); |
bogdanm | 0:9b334a45a8ff | 54 | bool change = must_replace_vector(irq); |
bogdanm | 0:9b334a45a8ff | 55 | |
bogdanm | 0:9b334a45a8ff | 56 | pFunctionPointer_t pf = front ? _chains[irq_pos]->add_front(function) : _chains[irq_pos]->add(function); |
bogdanm | 0:9b334a45a8ff | 57 | if (change) |
bogdanm | 0:9b334a45a8ff | 58 | NVIC_SetVector(irq, (uint32_t)&InterruptManager::static_irq_helper); |
bogdanm | 0:9b334a45a8ff | 59 | return pf; |
bogdanm | 0:9b334a45a8ff | 60 | } |
bogdanm | 0:9b334a45a8ff | 61 | |
bogdanm | 0:9b334a45a8ff | 62 | bool InterruptManager::remove_handler(pFunctionPointer_t handler, IRQn_Type irq) { |
bogdanm | 0:9b334a45a8ff | 63 | int irq_pos = get_irq_index(irq); |
bogdanm | 0:9b334a45a8ff | 64 | |
bogdanm | 0:9b334a45a8ff | 65 | if (NULL == _chains[irq_pos]) |
bogdanm | 0:9b334a45a8ff | 66 | return false; |
bogdanm | 0:9b334a45a8ff | 67 | if (!_chains[irq_pos]->remove(handler)) |
bogdanm | 0:9b334a45a8ff | 68 | return false; |
bogdanm | 0:9b334a45a8ff | 69 | // If there's a single function left in the chain, swith the interrupt vector |
bogdanm | 0:9b334a45a8ff | 70 | // to call that function directly. This way we save both time and space. |
bogdanm | 0:9b334a45a8ff | 71 | if (_chains[irq_pos]->size() == 1 && NULL != _chains[irq_pos]->get(0)->get_function()) { |
bogdanm | 0:9b334a45a8ff | 72 | NVIC_SetVector(irq, (uint32_t)_chains[irq_pos]->get(0)->get_function()); |
bogdanm | 0:9b334a45a8ff | 73 | delete _chains[irq_pos]; |
bogdanm | 0:9b334a45a8ff | 74 | _chains[irq_pos] = (CallChain*) NULL; |
bogdanm | 0:9b334a45a8ff | 75 | } |
bogdanm | 0:9b334a45a8ff | 76 | return true; |
bogdanm | 0:9b334a45a8ff | 77 | } |
bogdanm | 0:9b334a45a8ff | 78 | |
bogdanm | 0:9b334a45a8ff | 79 | void InterruptManager::irq_helper() { |
bogdanm | 0:9b334a45a8ff | 80 | _chains[__get_IPSR()]->call(); |
bogdanm | 0:9b334a45a8ff | 81 | } |
bogdanm | 0:9b334a45a8ff | 82 | |
bogdanm | 0:9b334a45a8ff | 83 | int InterruptManager::get_irq_index(IRQn_Type irq) { |
bogdanm | 0:9b334a45a8ff | 84 | return (int)irq + NVIC_USER_IRQ_OFFSET; |
bogdanm | 0:9b334a45a8ff | 85 | } |
bogdanm | 0:9b334a45a8ff | 86 | |
bogdanm | 0:9b334a45a8ff | 87 | void InterruptManager::static_irq_helper() { |
bogdanm | 0:9b334a45a8ff | 88 | InterruptManager::get()->irq_helper(); |
bogdanm | 0:9b334a45a8ff | 89 | } |
bogdanm | 0:9b334a45a8ff | 90 | |
bogdanm | 0:9b334a45a8ff | 91 | } // namespace mbed |
bogdanm | 0:9b334a45a8ff | 92 | |
bogdanm | 0:9b334a45a8ff | 93 | #endif |