General thunking class to allow C-style callbacks to C++ class members - including optional parameters.
CThunk.h@5:df90d98292a6, 2014-08-20 (annotated)
- Committer:
- meriac
- Date:
- Wed Aug 20 12:18:33 2014 +0000
- Revision:
- 5:df90d98292a6
- Parent:
- 4:e4a106e8f3fe
- Child:
- 6:ef94278e2225
centralized thumb-specific code
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
meriac | 0:7de85300ea3a | 1 | /* General C++ Object Thunking class |
meriac | 0:7de85300ea3a | 2 | * |
meriac | 0:7de85300ea3a | 3 | * - allows direct callbacks to non-static C++ class functions |
meriac | 0:7de85300ea3a | 4 | * - keeps track for the corresponding class instance |
meriac | 0:7de85300ea3a | 5 | * - supports an optional context parameter for the called function |
meriac | 0:7de85300ea3a | 6 | * - ideally suited for class object receiving interrupts (NVIC_SetVector) |
meriac | 0:7de85300ea3a | 7 | * |
meriac | 0:7de85300ea3a | 8 | * Copyright (c) 2014 ARM Limited |
meriac | 0:7de85300ea3a | 9 | * |
meriac | 0:7de85300ea3a | 10 | * Licensed under the Apache License, Version 2.0 (the "License"); |
meriac | 0:7de85300ea3a | 11 | * you may not use this file except in compliance with the License. |
meriac | 0:7de85300ea3a | 12 | * You may obtain a copy of the License at |
meriac | 0:7de85300ea3a | 13 | * |
meriac | 0:7de85300ea3a | 14 | * http://www.apache.org/licenses/LICENSE-2.0 |
meriac | 0:7de85300ea3a | 15 | * |
meriac | 0:7de85300ea3a | 16 | * Unless required by applicable law or agreed to in writing, software |
meriac | 0:7de85300ea3a | 17 | * distributed under the License is distributed on an "AS IS" BASIS, |
meriac | 0:7de85300ea3a | 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
meriac | 0:7de85300ea3a | 19 | * See the License for the specific language governing permissions and |
meriac | 0:7de85300ea3a | 20 | * limitations under the License. |
meriac | 0:7de85300ea3a | 21 | */ |
meriac | 0:7de85300ea3a | 22 | |
meriac | 0:7de85300ea3a | 23 | #ifndef __CTHUNK_H__ |
meriac | 0:7de85300ea3a | 24 | #define __CTHUNK_H__ |
meriac | 0:7de85300ea3a | 25 | |
meriac | 5:df90d98292a6 | 26 | #ifdef __CORTEX_M3 |
meriac | 5:df90d98292a6 | 27 | # define CTHUNK_OPCODE 0x8007E89F; |
meriac | 5:df90d98292a6 | 28 | # define CTHUNK_ADDRESS 1 |
meriac | 5:df90d98292a6 | 29 | #else |
meriac | 5:df90d98292a6 | 30 | # error "TODO: add support for non-cortex-m3 trampoline, too" |
meriac | 5:df90d98292a6 | 31 | #endif |
meriac | 5:df90d98292a6 | 32 | |
meriac | 0:7de85300ea3a | 33 | /* IRQ/Exception compatible thunk entry function */ |
meriac | 0:7de85300ea3a | 34 | typedef void (*CThunkEntry)(void); |
meriac | 3:51023d181133 | 35 | typedef void (*CThunkCallback)(void* instance, void* context); |
meriac | 0:7de85300ea3a | 36 | |
meriac | 0:7de85300ea3a | 37 | template<class T> |
meriac | 0:7de85300ea3a | 38 | class CThunk |
meriac | 0:7de85300ea3a | 39 | { |
meriac | 0:7de85300ea3a | 40 | public: |
meriac | 0:7de85300ea3a | 41 | typedef void (T::*CCallbackSimple)(void); |
meriac | 0:7de85300ea3a | 42 | typedef void (T::*CCallback)(void* context); |
meriac | 0:7de85300ea3a | 43 | |
meriac | 1:53a00c956d82 | 44 | inline CThunk(T *instance) |
meriac | 0:7de85300ea3a | 45 | { |
meriac | 0:7de85300ea3a | 46 | init(instance, NULL, NULL); |
meriac | 0:7de85300ea3a | 47 | } |
meriac | 0:7de85300ea3a | 48 | |
meriac | 5:df90d98292a6 | 49 | inline CThunk(T *instance, CCallback callback) |
meriac | 5:df90d98292a6 | 50 | { |
meriac | 5:df90d98292a6 | 51 | init(instance, callback, NULL); |
meriac | 5:df90d98292a6 | 52 | } |
meriac | 5:df90d98292a6 | 53 | |
meriac | 5:df90d98292a6 | 54 | inline CThunk(T *instance, CCallbackSimple callback) |
meriac | 5:df90d98292a6 | 55 | { |
meriac | 5:df90d98292a6 | 56 | init(instance, (CCallback)callback, NULL); |
meriac | 5:df90d98292a6 | 57 | } |
meriac | 5:df90d98292a6 | 58 | |
meriac | 0:7de85300ea3a | 59 | inline CThunk(T &instance, CCallback callback) |
meriac | 0:7de85300ea3a | 60 | { |
meriac | 0:7de85300ea3a | 61 | init(instance, callback, NULL); |
meriac | 0:7de85300ea3a | 62 | } |
meriac | 0:7de85300ea3a | 63 | |
meriac | 0:7de85300ea3a | 64 | inline CThunk(T &instance, CCallbackSimple callback) |
meriac | 0:7de85300ea3a | 65 | { |
meriac | 0:7de85300ea3a | 66 | init(instance, (CCallback)callback, NULL); |
meriac | 0:7de85300ea3a | 67 | } |
meriac | 0:7de85300ea3a | 68 | |
meriac | 0:7de85300ea3a | 69 | inline CThunk(T &instance, CCallback callback, void* context) |
meriac | 0:7de85300ea3a | 70 | { |
meriac | 0:7de85300ea3a | 71 | init(instance, callback, context); |
meriac | 0:7de85300ea3a | 72 | } |
meriac | 0:7de85300ea3a | 73 | |
meriac | 3:51023d181133 | 74 | inline void callback(CCallback callback) |
meriac | 0:7de85300ea3a | 75 | { |
meriac | 3:51023d181133 | 76 | m_callback = callback; |
meriac | 0:7de85300ea3a | 77 | } |
meriac | 0:7de85300ea3a | 78 | |
meriac | 3:51023d181133 | 79 | inline void callback(CCallbackSimple callback) |
meriac | 0:7de85300ea3a | 80 | { |
meriac | 3:51023d181133 | 81 | m_callback = (CCallback)callback; |
meriac | 0:7de85300ea3a | 82 | } |
meriac | 0:7de85300ea3a | 83 | |
meriac | 3:51023d181133 | 84 | inline void context(void* context) |
meriac | 3:51023d181133 | 85 | { |
meriac | 3:51023d181133 | 86 | m_thunk.context = (uint32_t)context; |
meriac | 3:51023d181133 | 87 | } |
meriac | 3:51023d181133 | 88 | |
meriac | 3:51023d181133 | 89 | inline void context(uint32_t context) |
meriac | 0:7de85300ea3a | 90 | { |
meriac | 0:7de85300ea3a | 91 | m_thunk.context = context; |
meriac | 0:7de85300ea3a | 92 | } |
meriac | 0:7de85300ea3a | 93 | |
meriac | 0:7de85300ea3a | 94 | /* get thunk entry point for connecting rhunk to an IRQ table */ |
meriac | 0:7de85300ea3a | 95 | inline operator CThunkEntry(void) |
meriac | 0:7de85300ea3a | 96 | { |
meriac | 3:51023d181133 | 97 | /* TODO: check thumb */ |
meriac | 5:df90d98292a6 | 98 | return (CThunkEntry)(((uint32_t)&m_thunk)|CTHUNK_ADDRESS); |
meriac | 0:7de85300ea3a | 99 | } |
meriac | 0:7de85300ea3a | 100 | |
meriac | 0:7de85300ea3a | 101 | /* get thunk entry point for connecting rhunk to an IRQ table */ |
meriac | 0:7de85300ea3a | 102 | inline operator uint32_t(void) |
meriac | 0:7de85300ea3a | 103 | { |
meriac | 1:53a00c956d82 | 104 | return (uint32_t)&m_thunk; |
meriac | 0:7de85300ea3a | 105 | } |
meriac | 0:7de85300ea3a | 106 | |
meriac | 0:7de85300ea3a | 107 | /* simple test function */ |
meriac | 0:7de85300ea3a | 108 | inline void call(void) |
meriac | 0:7de85300ea3a | 109 | { |
meriac | 3:51023d181133 | 110 | /* TODO: check thumb */ |
meriac | 5:df90d98292a6 | 111 | ((CThunkEntry)(((uint32_t)&m_thunk)|CTHUNK_ADDRESS))(); |
meriac | 0:7de85300ea3a | 112 | } |
meriac | 0:7de85300ea3a | 113 | |
meriac | 0:7de85300ea3a | 114 | private: |
meriac | 4:e4a106e8f3fe | 115 | T* m_instance; |
meriac | 3:51023d181133 | 116 | volatile CCallback m_callback; |
meriac | 4:e4a106e8f3fe | 117 | |
meriac | 0:7de85300ea3a | 118 | typedef struct |
meriac | 0:7de85300ea3a | 119 | { |
meriac | 3:51023d181133 | 120 | volatile uint32_t code; |
meriac | 3:51023d181133 | 121 | volatile uint32_t instance; |
meriac | 3:51023d181133 | 122 | volatile uint32_t context; |
meriac | 3:51023d181133 | 123 | volatile uint32_t callback; |
meriac | 4:e4a106e8f3fe | 124 | volatile uint32_t trampoline; |
meriac | 0:7de85300ea3a | 125 | } __attribute__((packed)) CThunkTrampoline; |
meriac | 0:7de85300ea3a | 126 | |
meriac | 4:e4a106e8f3fe | 127 | static void trampoline(T* instance, void* context, CCallback* callback) |
meriac | 3:51023d181133 | 128 | { |
meriac | 4:e4a106e8f3fe | 129 | if(instance && *callback) |
meriac | 4:e4a106e8f3fe | 130 | (static_cast<T*>(instance)->**callback)(context); |
meriac | 3:51023d181133 | 131 | } |
meriac | 3:51023d181133 | 132 | |
meriac | 3:51023d181133 | 133 | volatile CThunkTrampoline m_thunk; |
meriac | 3:51023d181133 | 134 | |
meriac | 3:51023d181133 | 135 | inline void init(T *instance, CCallback callback, void* context) |
meriac | 0:7de85300ea3a | 136 | { |
meriac | 5:df90d98292a6 | 137 | /* remember callback - need to add this level of redirection |
meriac | 5:df90d98292a6 | 138 | as pointer size for member functions differs between platforms */ |
meriac | 4:e4a106e8f3fe | 139 | m_callback = callback; |
meriac | 4:e4a106e8f3fe | 140 | |
meriac | 4:e4a106e8f3fe | 141 | /* populate thunking trampoline */ |
meriac | 5:df90d98292a6 | 142 | m_thunk.code = CTHUNK_OPCODE; |
meriac | 3:51023d181133 | 143 | m_thunk.context = (uint32_t)context; |
meriac | 3:51023d181133 | 144 | m_thunk.instance = (uint32_t)instance; |
meriac | 4:e4a106e8f3fe | 145 | m_thunk.callback = (uint32_t)&m_callback; |
meriac | 4:e4a106e8f3fe | 146 | m_thunk.trampoline = (uint32_t)&trampoline; |
meriac | 4:e4a106e8f3fe | 147 | |
meriac | 3:51023d181133 | 148 | __ISB(); |
meriac | 3:51023d181133 | 149 | __DSB(); |
meriac | 0:7de85300ea3a | 150 | } |
meriac | 0:7de85300ea3a | 151 | }; |
meriac | 0:7de85300ea3a | 152 | |
meriac | 1:53a00c956d82 | 153 | #endif/*__CTHUNK_H__*/ |