General thunking class to allow C-style callbacks to C++ class members - including optional parameters.

Dependents:   cthunk_example

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?

UserRevisionLine numberNew 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__*/