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

Dependents:   cthunk_example

Committer:
meriac
Date:
Wed Aug 20 10:44:31 2014 +0000
Revision:
4:e4a106e8f3fe
Parent:
3:51023d181133
Child:
5:df90d98292a6
re-added instance callback to 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 3:51023d181133 28 typedef void (*CThunkCallback)(void* instance, void* context);
meriac 0:7de85300ea3a 29
meriac 0:7de85300ea3a 30 template<class T>
meriac 0:7de85300ea3a 31 class CThunk
meriac 0:7de85300ea3a 32 {
meriac 0:7de85300ea3a 33 public:
meriac 0:7de85300ea3a 34 typedef void (T::*CCallbackSimple)(void);
meriac 0:7de85300ea3a 35 typedef void (T::*CCallback)(void* context);
meriac 0:7de85300ea3a 36
meriac 1:53a00c956d82 37 inline CThunk(T *instance)
meriac 0:7de85300ea3a 38 {
meriac 0:7de85300ea3a 39 init(instance, NULL, NULL);
meriac 0:7de85300ea3a 40 }
meriac 0:7de85300ea3a 41
meriac 0:7de85300ea3a 42 inline CThunk(T &instance, CCallback callback)
meriac 0:7de85300ea3a 43 {
meriac 0:7de85300ea3a 44 init(instance, callback, NULL);
meriac 0:7de85300ea3a 45 }
meriac 0:7de85300ea3a 46
meriac 0:7de85300ea3a 47 inline CThunk(T &instance, CCallbackSimple callback)
meriac 0:7de85300ea3a 48 {
meriac 0:7de85300ea3a 49 init(instance, (CCallback)callback, NULL);
meriac 0:7de85300ea3a 50 }
meriac 0:7de85300ea3a 51
meriac 0:7de85300ea3a 52 inline CThunk(T &instance, CCallback callback, void* context)
meriac 0:7de85300ea3a 53 {
meriac 0:7de85300ea3a 54 init(instance, callback, context);
meriac 0:7de85300ea3a 55 }
meriac 0:7de85300ea3a 56
meriac 3:51023d181133 57 inline void callback(CCallback callback)
meriac 0:7de85300ea3a 58 {
meriac 3:51023d181133 59 m_callback = callback;
meriac 0:7de85300ea3a 60 }
meriac 0:7de85300ea3a 61
meriac 3:51023d181133 62 inline void callback(CCallbackSimple callback)
meriac 0:7de85300ea3a 63 {
meriac 3:51023d181133 64 m_callback = (CCallback)callback;
meriac 0:7de85300ea3a 65 }
meriac 0:7de85300ea3a 66
meriac 3:51023d181133 67 inline void context(void* context)
meriac 3:51023d181133 68 {
meriac 3:51023d181133 69 m_thunk.context = (uint32_t)context;
meriac 3:51023d181133 70 }
meriac 3:51023d181133 71
meriac 3:51023d181133 72 inline void context(uint32_t context)
meriac 0:7de85300ea3a 73 {
meriac 0:7de85300ea3a 74 m_thunk.context = context;
meriac 0:7de85300ea3a 75 }
meriac 0:7de85300ea3a 76
meriac 0:7de85300ea3a 77 /* get thunk entry point for connecting rhunk to an IRQ table */
meriac 0:7de85300ea3a 78 inline operator CThunkEntry(void)
meriac 0:7de85300ea3a 79 {
meriac 3:51023d181133 80 /* TODO: check thumb */
meriac 3:51023d181133 81 return (CThunkEntry)(((uint32_t)&m_thunk)|1);
meriac 0:7de85300ea3a 82 }
meriac 0:7de85300ea3a 83
meriac 0:7de85300ea3a 84 /* get thunk entry point for connecting rhunk to an IRQ table */
meriac 0:7de85300ea3a 85 inline operator uint32_t(void)
meriac 0:7de85300ea3a 86 {
meriac 1:53a00c956d82 87 return (uint32_t)&m_thunk;
meriac 0:7de85300ea3a 88 }
meriac 0:7de85300ea3a 89
meriac 0:7de85300ea3a 90 /* simple test function */
meriac 0:7de85300ea3a 91 inline void call(void)
meriac 0:7de85300ea3a 92 {
meriac 3:51023d181133 93 /* TODO: check thumb */
meriac 3:51023d181133 94 ((CThunkEntry)(((uint32_t)&m_thunk)|1))();
meriac 0:7de85300ea3a 95 }
meriac 0:7de85300ea3a 96
meriac 0:7de85300ea3a 97 private:
meriac 4:e4a106e8f3fe 98 T* m_instance;
meriac 3:51023d181133 99 volatile CCallback m_callback;
meriac 4:e4a106e8f3fe 100
meriac 0:7de85300ea3a 101 typedef struct
meriac 0:7de85300ea3a 102 {
meriac 3:51023d181133 103 volatile uint32_t code;
meriac 3:51023d181133 104 volatile uint32_t instance;
meriac 3:51023d181133 105 volatile uint32_t context;
meriac 3:51023d181133 106 volatile uint32_t callback;
meriac 4:e4a106e8f3fe 107 volatile uint32_t trampoline;
meriac 0:7de85300ea3a 108 } __attribute__((packed)) CThunkTrampoline;
meriac 0:7de85300ea3a 109
meriac 4:e4a106e8f3fe 110 static void trampoline(T* instance, void* context, CCallback* callback)
meriac 3:51023d181133 111 {
meriac 4:e4a106e8f3fe 112 if(instance && *callback)
meriac 4:e4a106e8f3fe 113 (static_cast<T*>(instance)->**callback)(context);
meriac 3:51023d181133 114 }
meriac 3:51023d181133 115
meriac 3:51023d181133 116 volatile CThunkTrampoline m_thunk;
meriac 3:51023d181133 117
meriac 3:51023d181133 118 inline void init(T *instance, CCallback callback, void* context)
meriac 0:7de85300ea3a 119 {
meriac 2:3197c4a8ba85 120 #ifdef __CORTEX_M3
meriac 4:e4a106e8f3fe 121 m_thunk.code = 0x8007E89F;
meriac 1:53a00c956d82 122 #else
meriac 1:53a00c956d82 123 #error "TODO: add support for non-cortex-m3 trampoline, too"
meriac 1:53a00c956d82 124 #endif
meriac 4:e4a106e8f3fe 125 m_callback = callback;
meriac 4:e4a106e8f3fe 126
meriac 4:e4a106e8f3fe 127 /* populate thunking trampoline */
meriac 3:51023d181133 128 m_thunk.context = (uint32_t)context;
meriac 3:51023d181133 129 m_thunk.instance = (uint32_t)instance;
meriac 4:e4a106e8f3fe 130 m_thunk.callback = (uint32_t)&m_callback;
meriac 4:e4a106e8f3fe 131 m_thunk.trampoline = (uint32_t)&trampoline;
meriac 4:e4a106e8f3fe 132
meriac 3:51023d181133 133 __ISB();
meriac 3:51023d181133 134 __DSB();
meriac 0:7de85300ea3a 135 }
meriac 0:7de85300ea3a 136 };
meriac 0:7de85300ea3a 137
meriac 1:53a00c956d82 138 #endif/*__CTHUNK_H__*/