General thunking class to allow C-style callbacks to C++ class members - including optional parameters.
CThunk.h@1:53a00c956d82, 2014-08-15 (annotated)
- Committer:
- meriac
- Date:
- Fri Aug 15 12:50:49 2014 +0000
- Revision:
- 1:53a00c956d82
- Parent:
- 0:7de85300ea3a
- Child:
- 2:3197c4a8ba85
Simplified thunking 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 | 0:7de85300ea3a | 26 | /* IRQ/Exception compatible thunk entry function */ |
meriac | 0:7de85300ea3a | 27 | typedef void (*CThunkEntry)(void); |
meriac | 0:7de85300ea3a | 28 | |
meriac | 0:7de85300ea3a | 29 | template<class T> |
meriac | 0:7de85300ea3a | 30 | class CThunk |
meriac | 0:7de85300ea3a | 31 | { |
meriac | 0:7de85300ea3a | 32 | public: |
meriac | 0:7de85300ea3a | 33 | typedef void (T::*CCallbackSimple)(void); |
meriac | 0:7de85300ea3a | 34 | typedef void (T::*CCallback)(void* context); |
meriac | 0:7de85300ea3a | 35 | |
meriac | 1:53a00c956d82 | 36 | inline CThunk(T *instance) |
meriac | 0:7de85300ea3a | 37 | { |
meriac | 1:53a00c956d82 | 38 | init(*instance, NULL, NULL); |
meriac | 0:7de85300ea3a | 39 | } |
meriac | 0:7de85300ea3a | 40 | |
meriac | 0:7de85300ea3a | 41 | inline CThunk(T &instance) |
meriac | 0:7de85300ea3a | 42 | { |
meriac | 0:7de85300ea3a | 43 | init(instance, NULL, NULL); |
meriac | 0:7de85300ea3a | 44 | } |
meriac | 0:7de85300ea3a | 45 | |
meriac | 0:7de85300ea3a | 46 | inline CThunk(T &instance, CCallback callback) |
meriac | 0:7de85300ea3a | 47 | { |
meriac | 0:7de85300ea3a | 48 | init(instance, callback, NULL); |
meriac | 0:7de85300ea3a | 49 | } |
meriac | 0:7de85300ea3a | 50 | |
meriac | 0:7de85300ea3a | 51 | inline CThunk(T &instance, CCallbackSimple callback) |
meriac | 0:7de85300ea3a | 52 | { |
meriac | 0:7de85300ea3a | 53 | init(instance, (CCallback)callback, NULL); |
meriac | 0:7de85300ea3a | 54 | } |
meriac | 0:7de85300ea3a | 55 | |
meriac | 0:7de85300ea3a | 56 | inline CThunk(T &instance, CCallback callback, void* context) |
meriac | 0:7de85300ea3a | 57 | { |
meriac | 0:7de85300ea3a | 58 | init(instance, callback, context); |
meriac | 0:7de85300ea3a | 59 | } |
meriac | 0:7de85300ea3a | 60 | |
meriac | 0:7de85300ea3a | 61 | inline CThunk& operator=(T &instance) |
meriac | 0:7de85300ea3a | 62 | { |
meriac | 0:7de85300ea3a | 63 | m_thunk.instance = &instance; |
meriac | 0:7de85300ea3a | 64 | return *this; |
meriac | 0:7de85300ea3a | 65 | } |
meriac | 0:7de85300ea3a | 66 | |
meriac | 0:7de85300ea3a | 67 | inline CThunk& operator=(CCallback callback) |
meriac | 0:7de85300ea3a | 68 | { |
meriac | 0:7de85300ea3a | 69 | m_thunk.callback = callback; |
meriac | 0:7de85300ea3a | 70 | return *this; |
meriac | 0:7de85300ea3a | 71 | } |
meriac | 0:7de85300ea3a | 72 | |
meriac | 0:7de85300ea3a | 73 | inline CThunk& operator=(CCallbackSimple callback) |
meriac | 0:7de85300ea3a | 74 | { |
meriac | 0:7de85300ea3a | 75 | m_thunk.callback = (CCallback)callback; |
meriac | 0:7de85300ea3a | 76 | return *this; |
meriac | 0:7de85300ea3a | 77 | } |
meriac | 0:7de85300ea3a | 78 | |
meriac | 0:7de85300ea3a | 79 | inline CThunk& operator=(void* context) |
meriac | 0:7de85300ea3a | 80 | { |
meriac | 0:7de85300ea3a | 81 | m_thunk.context = context; |
meriac | 0:7de85300ea3a | 82 | return *this; |
meriac | 0:7de85300ea3a | 83 | } |
meriac | 0:7de85300ea3a | 84 | |
meriac | 0:7de85300ea3a | 85 | inline CThunk& operator=(uint32_t context) |
meriac | 0:7de85300ea3a | 86 | { |
meriac | 0:7de85300ea3a | 87 | m_thunk.context = (void*)context; |
meriac | 0:7de85300ea3a | 88 | return *this; |
meriac | 0:7de85300ea3a | 89 | } |
meriac | 0:7de85300ea3a | 90 | |
meriac | 0:7de85300ea3a | 91 | /* get thunk entry point for connecting rhunk to an IRQ table */ |
meriac | 0:7de85300ea3a | 92 | inline operator CThunkEntry(void) |
meriac | 0:7de85300ea3a | 93 | { |
meriac | 1:53a00c956d82 | 94 | return (CThunkEntry)&m_thunk; |
meriac | 0:7de85300ea3a | 95 | } |
meriac | 0:7de85300ea3a | 96 | |
meriac | 0:7de85300ea3a | 97 | /* get thunk entry point for connecting rhunk to an IRQ table */ |
meriac | 0:7de85300ea3a | 98 | inline operator uint32_t(void) |
meriac | 0:7de85300ea3a | 99 | { |
meriac | 1:53a00c956d82 | 100 | return (uint32_t)&m_thunk; |
meriac | 0:7de85300ea3a | 101 | } |
meriac | 0:7de85300ea3a | 102 | |
meriac | 0:7de85300ea3a | 103 | /* simple test function */ |
meriac | 0:7de85300ea3a | 104 | inline void call(void) |
meriac | 0:7de85300ea3a | 105 | { |
meriac | 1:53a00c956d82 | 106 | ((CThunkEntry)&m_thunk)(); |
meriac | 0:7de85300ea3a | 107 | } |
meriac | 0:7de85300ea3a | 108 | |
meriac | 0:7de85300ea3a | 109 | private: |
meriac | 0:7de85300ea3a | 110 | typedef struct |
meriac | 0:7de85300ea3a | 111 | { |
meriac | 1:53a00c956d82 | 112 | uint32_t code; |
meriac | 0:7de85300ea3a | 113 | T* instance; |
meriac | 0:7de85300ea3a | 114 | void* context; |
meriac | 0:7de85300ea3a | 115 | CCallback callback; |
meriac | 0:7de85300ea3a | 116 | } __attribute__((packed)) CThunkTrampoline; |
meriac | 0:7de85300ea3a | 117 | |
meriac | 0:7de85300ea3a | 118 | CThunkTrampoline m_thunk; |
meriac | 0:7de85300ea3a | 119 | |
meriac | 0:7de85300ea3a | 120 | inline void init(T &instance, CCallback callback, void* context) |
meriac | 0:7de85300ea3a | 121 | { |
meriac | 1:53a00c956d82 | 122 | #ifdef __thumb2__ |
meriac | 1:53a00c956d82 | 123 | m_thunk.code = 0x8003E89F; |
meriac | 1:53a00c956d82 | 124 | #else |
meriac | 1:53a00c956d82 | 125 | #error "TODO: add support for non-cortex-m3 trampoline, too" |
meriac | 1:53a00c956d82 | 126 | #endif |
meriac | 0:7de85300ea3a | 127 | m_thunk.instance = &instance; |
meriac | 0:7de85300ea3a | 128 | m_thunk.context = context; |
meriac | 0:7de85300ea3a | 129 | m_thunk.callback = callback; |
meriac | 0:7de85300ea3a | 130 | } |
meriac | 0:7de85300ea3a | 131 | }; |
meriac | 0:7de85300ea3a | 132 | |
meriac | 1:53a00c956d82 | 133 | #endif/*__CTHUNK_H__*/ |