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