Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
CThunk.h
00001 00002 /** \addtogroup platform */ 00003 /** @{*/ 00004 /* General C++ Object Thunking class 00005 * 00006 * - allows direct callbacks to non-static C++ class functions 00007 * - keeps track for the corresponding class instance 00008 * - supports an optional context parameter for the called function 00009 * - ideally suited for class object receiving interrupts (NVIC_SetVector) 00010 * 00011 * Copyright (c) 2014-2015 ARM Limited 00012 * 00013 * Licensed under the Apache License, Version 2.0 (the "License"); 00014 * you may not use this file except in compliance with the License. 00015 * You may obtain a copy of the License at 00016 * 00017 * http://www.apache.org/licenses/LICENSE-2.0 00018 * 00019 * Unless required by applicable law or agreed to in writing, software 00020 * distributed under the License is distributed on an "AS IS" BASIS, 00021 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00022 * See the License for the specific language governing permissions and 00023 * limitations under the License. 00024 */ 00025 00026 /* General C++ Object Thunking class 00027 * 00028 * - allows direct callbacks to non-static C++ class functions 00029 * - keeps track for the corresponding class instance 00030 * - supports an optional context parameter for the called function 00031 * - ideally suited for class object receiving interrupts (NVIC_SetVector) 00032 */ 00033 00034 #ifndef __CTHUNK_H__ 00035 #define __CTHUNK_H__ 00036 00037 #define CTHUNK_ADDRESS 1 00038 #define CTHUNK_VARIABLES volatile uint32_t code[2] 00039 00040 #if (defined(__CORTEX_M3) || defined(__CORTEX_M4) || defined(__CORTEX_M7) || defined(__CORTEX_A9)) 00041 /** 00042 * CTHUNK disassembly for Cortex-M3/M4/M7/A9 (thumb2): 00043 * * adr r0, #4 00044 * * ldm r0, {r0, r1, r2, pc} 00045 * 00046 * This instruction loads the arguments for the static thunking function to r0-r2, and 00047 * branches to that function by loading its address into PC. 00048 * 00049 * This is safe for both regular calling and interrupt calling, since it only touches scratch registers 00050 * which should be saved by the caller, and are automatically saved as part of the IRQ context switch. 00051 */ 00052 #define CTHUNK_ASSIGMENT do { \ 00053 m_thunk.code[0] = 0xE890A001; \ 00054 m_thunk.code[1] = 0x00008007; \ 00055 } while (0) 00056 00057 #elif (defined(__CORTEX_M0PLUS) || defined(__CORTEX_M0)) 00058 /* 00059 * CTHUNK disassembly for Cortex M0/M0+ (thumb): 00060 * * adr r0, #4 00061 * * ldm r0, {r0, r1, r2, r3} 00062 * * bx r3 00063 */ 00064 #define CTHUNK_ASSIGMENT do { \ 00065 m_thunk.code[0] = 0xC80FA001; \ 00066 m_thunk.code[1] = 0x00004718; \ 00067 } while (0) 00068 00069 #else 00070 #error "Target is not currently suported." 00071 #endif 00072 00073 /* IRQ/Exception compatible thunk entry function */ 00074 typedef void (*CThunkEntry)(void); 00075 /** @}*/ 00076 00077 /** 00078 * Class for created a pointer with data bound to it 00079 * 00080 * @note Synchronization level: Not protected 00081 * @ingroup platform 00082 */ 00083 template<class T> 00084 class CThunk 00085 { 00086 public: 00087 typedef void (T::*CCallbackSimple)(void); 00088 typedef void (T::*CCallback)(void* context); 00089 00090 inline CThunk(T *instance) 00091 { 00092 init(instance, NULL, NULL); 00093 } 00094 00095 inline CThunk(T *instance, CCallback callback) 00096 { 00097 init(instance, callback, NULL); 00098 } 00099 00100 ~CThunk() { 00101 00102 } 00103 00104 inline CThunk(T *instance, CCallbackSimple callback) 00105 { 00106 init(instance, (CCallback)callback, NULL); 00107 } 00108 00109 inline CThunk(T &instance, CCallback callback) 00110 { 00111 init(instance, callback, NULL); 00112 } 00113 00114 inline CThunk(T &instance, CCallbackSimple callback) 00115 { 00116 init(instance, (CCallback)callback, NULL); 00117 } 00118 00119 inline CThunk(T &instance, CCallback callback, void* context) 00120 { 00121 init(instance, callback, context); 00122 } 00123 00124 inline void callback(CCallback callback) 00125 { 00126 m_callback = callback; 00127 } 00128 00129 inline void callback(CCallbackSimple callback) 00130 { 00131 m_callback = (CCallback)callback; 00132 } 00133 00134 inline void context(void* context) 00135 { 00136 m_thunk.context = (uint32_t)context; 00137 } 00138 00139 inline void context(uint32_t context) 00140 { 00141 m_thunk.context = context; 00142 } 00143 00144 inline uint32_t entry(void) 00145 { 00146 return (((uint32_t)&m_thunk)|CTHUNK_ADDRESS); 00147 } 00148 00149 /* get thunk entry point for connecting rhunk to an IRQ table */ 00150 inline operator CThunkEntry(void) 00151 { 00152 return (CThunkEntry)entry(); 00153 } 00154 00155 /* get thunk entry point for connecting rhunk to an IRQ table */ 00156 inline operator uint32_t(void) 00157 { 00158 return entry(); 00159 } 00160 00161 /* simple test function */ 00162 inline void call(void) 00163 { 00164 (((CThunkEntry)(entry()))()); 00165 } 00166 00167 private: 00168 T* m_instance; 00169 volatile CCallback m_callback; 00170 00171 // TODO: this needs proper fix, to refactor toolchain header file and all its use 00172 // PACKED there is not defined properly for IAR 00173 #if defined (__ICCARM__) 00174 typedef __packed struct 00175 { 00176 CTHUNK_VARIABLES; 00177 volatile uint32_t instance; 00178 volatile uint32_t context; 00179 volatile uint32_t callback; 00180 volatile uint32_t trampoline; 00181 } CThunkTrampoline; 00182 #else 00183 typedef struct 00184 { 00185 CTHUNK_VARIABLES; 00186 volatile uint32_t instance; 00187 volatile uint32_t context; 00188 volatile uint32_t callback; 00189 volatile uint32_t trampoline; 00190 } __attribute__((__packed__)) CThunkTrampoline; 00191 #endif 00192 00193 static void trampoline(T* instance, void* context, CCallback* callback) 00194 { 00195 if(instance && *callback) { 00196 (static_cast<T*>(instance)->**callback)(context); 00197 } 00198 } 00199 00200 volatile CThunkTrampoline m_thunk; 00201 00202 inline void init(T *instance, CCallback callback, void* context) 00203 { 00204 /* remember callback - need to add this level of redirection 00205 as pointer size for member functions differs between platforms */ 00206 m_callback = callback; 00207 00208 /* populate thunking trampoline */ 00209 CTHUNK_ASSIGMENT; 00210 m_thunk.context = (uint32_t)context; 00211 m_thunk.instance = (uint32_t)instance; 00212 m_thunk.callback = (uint32_t)&m_callback; 00213 m_thunk.trampoline = (uint32_t)&trampoline; 00214 00215 #if defined(__CORTEX_A9) 00216 /* Data cache clean */ 00217 /* Cache control */ 00218 { 00219 uint32_t start_addr = (uint32_t)&m_thunk & 0xFFFFFFE0; 00220 uint32_t end_addr = (uint32_t)&m_thunk + sizeof(m_thunk); 00221 uint32_t addr; 00222 00223 /* Data cache clean and invalid */ 00224 for (addr = start_addr; addr < end_addr; addr += 0x20) { 00225 __v7_clean_inv_dcache_mva((void *)addr); 00226 } 00227 /* Instruction cache invalid */ 00228 __v7_inv_icache_all(); 00229 __ca9u_inv_tlb_all(); 00230 __v7_inv_btac(); 00231 } 00232 #endif 00233 #if defined(__CORTEX_M7) 00234 /* Data cache clean and invalid */ 00235 SCB_CleanInvalidateDCache(); 00236 00237 /* Instruction cache invalid */ 00238 SCB_InvalidateICache(); 00239 #endif 00240 __ISB(); 00241 __DSB(); 00242 } 00243 }; 00244 00245 #endif/*__CTHUNK_H__*/ 00246
Generated on Wed Nov 13 2024 03:38:35 by
1.7.2
