BBR 1 Ebene

Committer:
borlanic
Date:
Mon May 14 11:29:06 2018 +0000
Revision:
0:fbdae7e6d805
BBR

Who changed what in which revision?

UserRevisionLine numberNew contents of line
borlanic 0:fbdae7e6d805 1
borlanic 0:fbdae7e6d805 2 /** \addtogroup platform */
borlanic 0:fbdae7e6d805 3 /** @{*/
borlanic 0:fbdae7e6d805 4 /**
borlanic 0:fbdae7e6d805 5 * \defgroup platform_CThunk CThunk class
borlanic 0:fbdae7e6d805 6 * @{
borlanic 0:fbdae7e6d805 7 */
borlanic 0:fbdae7e6d805 8 /* General C++ Object Thunking class
borlanic 0:fbdae7e6d805 9 *
borlanic 0:fbdae7e6d805 10 * - allows direct callbacks to non-static C++ class functions
borlanic 0:fbdae7e6d805 11 * - keeps track for the corresponding class instance
borlanic 0:fbdae7e6d805 12 * - supports an optional context parameter for the called function
borlanic 0:fbdae7e6d805 13 * - ideally suited for class object receiving interrupts (NVIC_SetVector)
borlanic 0:fbdae7e6d805 14 *
borlanic 0:fbdae7e6d805 15 * Copyright (c) 2014-2015 ARM Limited
borlanic 0:fbdae7e6d805 16 *
borlanic 0:fbdae7e6d805 17 * Licensed under the Apache License, Version 2.0 (the "License");
borlanic 0:fbdae7e6d805 18 * you may not use this file except in compliance with the License.
borlanic 0:fbdae7e6d805 19 * You may obtain a copy of the License at
borlanic 0:fbdae7e6d805 20 *
borlanic 0:fbdae7e6d805 21 * http://www.apache.org/licenses/LICENSE-2.0
borlanic 0:fbdae7e6d805 22 *
borlanic 0:fbdae7e6d805 23 * Unless required by applicable law or agreed to in writing, software
borlanic 0:fbdae7e6d805 24 * distributed under the License is distributed on an "AS IS" BASIS,
borlanic 0:fbdae7e6d805 25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
borlanic 0:fbdae7e6d805 26 * See the License for the specific language governing permissions and
borlanic 0:fbdae7e6d805 27 * limitations under the License.
borlanic 0:fbdae7e6d805 28 */
borlanic 0:fbdae7e6d805 29
borlanic 0:fbdae7e6d805 30 /* General C++ Object Thunking class
borlanic 0:fbdae7e6d805 31 *
borlanic 0:fbdae7e6d805 32 * - allows direct callbacks to non-static C++ class functions
borlanic 0:fbdae7e6d805 33 * - keeps track for the corresponding class instance
borlanic 0:fbdae7e6d805 34 * - supports an optional context parameter for the called function
borlanic 0:fbdae7e6d805 35 * - ideally suited for class object receiving interrupts (NVIC_SetVector)
borlanic 0:fbdae7e6d805 36 */
borlanic 0:fbdae7e6d805 37
borlanic 0:fbdae7e6d805 38 #ifndef __CTHUNK_H__
borlanic 0:fbdae7e6d805 39 #define __CTHUNK_H__
borlanic 0:fbdae7e6d805 40
borlanic 0:fbdae7e6d805 41 #define CTHUNK_ADDRESS 1
borlanic 0:fbdae7e6d805 42 #define CTHUNK_VARIABLES volatile uint32_t code[2]
borlanic 0:fbdae7e6d805 43
borlanic 0:fbdae7e6d805 44 #if (defined(__CORTEX_M3) || defined(__CORTEX_M4) || defined(__CORTEX_M7) || defined(__CORTEX_A9) \
borlanic 0:fbdae7e6d805 45 || defined(__CORTEX_M33))
borlanic 0:fbdae7e6d805 46 /**
borlanic 0:fbdae7e6d805 47 * CTHUNK disassembly for Cortex-M3/M4/M7/A9 (thumb2):
borlanic 0:fbdae7e6d805 48 * * adr r0, #4
borlanic 0:fbdae7e6d805 49 * * ldm r0, {r0, r1, r2, pc}
borlanic 0:fbdae7e6d805 50 *
borlanic 0:fbdae7e6d805 51 * This instruction loads the arguments for the static thunking function to r0-r2, and
borlanic 0:fbdae7e6d805 52 * branches to that function by loading its address into PC.
borlanic 0:fbdae7e6d805 53 *
borlanic 0:fbdae7e6d805 54 * This is safe for both regular calling and interrupt calling, since it only touches scratch registers
borlanic 0:fbdae7e6d805 55 * which should be saved by the caller, and are automatically saved as part of the IRQ context switch.
borlanic 0:fbdae7e6d805 56 */
borlanic 0:fbdae7e6d805 57 #define CTHUNK_ASSIGMENT do { \
borlanic 0:fbdae7e6d805 58 m_thunk.code[0] = 0xE890A001; \
borlanic 0:fbdae7e6d805 59 m_thunk.code[1] = 0x00008007; \
borlanic 0:fbdae7e6d805 60 } while (0)
borlanic 0:fbdae7e6d805 61
borlanic 0:fbdae7e6d805 62 #elif (defined(__CORTEX_M0PLUS) || defined(__CORTEX_M0) || defined(__CORTEX_M23))
borlanic 0:fbdae7e6d805 63 /*
borlanic 0:fbdae7e6d805 64 * CTHUNK disassembly for Cortex M0/M0+ (thumb):
borlanic 0:fbdae7e6d805 65 * * adr r0, #4
borlanic 0:fbdae7e6d805 66 * * ldm r0, {r0, r1, r2, r3}
borlanic 0:fbdae7e6d805 67 * * bx r3
borlanic 0:fbdae7e6d805 68 */
borlanic 0:fbdae7e6d805 69 #define CTHUNK_ASSIGMENT do { \
borlanic 0:fbdae7e6d805 70 m_thunk.code[0] = 0xC80FA001; \
borlanic 0:fbdae7e6d805 71 m_thunk.code[1] = 0x00004718; \
borlanic 0:fbdae7e6d805 72 } while (0)
borlanic 0:fbdae7e6d805 73
borlanic 0:fbdae7e6d805 74 #else
borlanic 0:fbdae7e6d805 75 #error "Target is not currently suported."
borlanic 0:fbdae7e6d805 76 #endif
borlanic 0:fbdae7e6d805 77
borlanic 0:fbdae7e6d805 78 /* IRQ/Exception compatible thunk entry function */
borlanic 0:fbdae7e6d805 79 typedef void (*CThunkEntry)(void);
borlanic 0:fbdae7e6d805 80
borlanic 0:fbdae7e6d805 81 /**
borlanic 0:fbdae7e6d805 82 * Class for created a pointer with data bound to it
borlanic 0:fbdae7e6d805 83 *
borlanic 0:fbdae7e6d805 84 * @note Synchronization level: Not protected
borlanic 0:fbdae7e6d805 85 */
borlanic 0:fbdae7e6d805 86 template<class T>
borlanic 0:fbdae7e6d805 87 class CThunk
borlanic 0:fbdae7e6d805 88 {
borlanic 0:fbdae7e6d805 89 public:
borlanic 0:fbdae7e6d805 90 typedef void (T::*CCallbackSimple)(void);
borlanic 0:fbdae7e6d805 91 typedef void (T::*CCallback)(void* context);
borlanic 0:fbdae7e6d805 92
borlanic 0:fbdae7e6d805 93 inline CThunk(T *instance)
borlanic 0:fbdae7e6d805 94 {
borlanic 0:fbdae7e6d805 95 init(instance, NULL, NULL);
borlanic 0:fbdae7e6d805 96 }
borlanic 0:fbdae7e6d805 97
borlanic 0:fbdae7e6d805 98 inline CThunk(T *instance, CCallback callback)
borlanic 0:fbdae7e6d805 99 {
borlanic 0:fbdae7e6d805 100 init(instance, callback, NULL);
borlanic 0:fbdae7e6d805 101 }
borlanic 0:fbdae7e6d805 102
borlanic 0:fbdae7e6d805 103 ~CThunk() {
borlanic 0:fbdae7e6d805 104
borlanic 0:fbdae7e6d805 105 }
borlanic 0:fbdae7e6d805 106
borlanic 0:fbdae7e6d805 107 inline CThunk(T *instance, CCallbackSimple callback)
borlanic 0:fbdae7e6d805 108 {
borlanic 0:fbdae7e6d805 109 init(instance, (CCallback)callback, NULL);
borlanic 0:fbdae7e6d805 110 }
borlanic 0:fbdae7e6d805 111
borlanic 0:fbdae7e6d805 112 inline CThunk(T &instance, CCallback callback)
borlanic 0:fbdae7e6d805 113 {
borlanic 0:fbdae7e6d805 114 init(instance, callback, NULL);
borlanic 0:fbdae7e6d805 115 }
borlanic 0:fbdae7e6d805 116
borlanic 0:fbdae7e6d805 117 inline CThunk(T &instance, CCallbackSimple callback)
borlanic 0:fbdae7e6d805 118 {
borlanic 0:fbdae7e6d805 119 init(instance, (CCallback)callback, NULL);
borlanic 0:fbdae7e6d805 120 }
borlanic 0:fbdae7e6d805 121
borlanic 0:fbdae7e6d805 122 inline CThunk(T &instance, CCallback callback, void* context)
borlanic 0:fbdae7e6d805 123 {
borlanic 0:fbdae7e6d805 124 init(instance, callback, context);
borlanic 0:fbdae7e6d805 125 }
borlanic 0:fbdae7e6d805 126
borlanic 0:fbdae7e6d805 127 inline void callback(CCallback callback)
borlanic 0:fbdae7e6d805 128 {
borlanic 0:fbdae7e6d805 129 m_callback = callback;
borlanic 0:fbdae7e6d805 130 }
borlanic 0:fbdae7e6d805 131
borlanic 0:fbdae7e6d805 132 inline void callback(CCallbackSimple callback)
borlanic 0:fbdae7e6d805 133 {
borlanic 0:fbdae7e6d805 134 m_callback = (CCallback)callback;
borlanic 0:fbdae7e6d805 135 }
borlanic 0:fbdae7e6d805 136
borlanic 0:fbdae7e6d805 137 inline void context(void* context)
borlanic 0:fbdae7e6d805 138 {
borlanic 0:fbdae7e6d805 139 m_thunk.context = (uint32_t)context;
borlanic 0:fbdae7e6d805 140 }
borlanic 0:fbdae7e6d805 141
borlanic 0:fbdae7e6d805 142 inline void context(uint32_t context)
borlanic 0:fbdae7e6d805 143 {
borlanic 0:fbdae7e6d805 144 m_thunk.context = context;
borlanic 0:fbdae7e6d805 145 }
borlanic 0:fbdae7e6d805 146
borlanic 0:fbdae7e6d805 147 inline uint32_t entry(void)
borlanic 0:fbdae7e6d805 148 {
borlanic 0:fbdae7e6d805 149 return (((uint32_t)&m_thunk)|CTHUNK_ADDRESS);
borlanic 0:fbdae7e6d805 150 }
borlanic 0:fbdae7e6d805 151
borlanic 0:fbdae7e6d805 152 /* get thunk entry point for connecting rhunk to an IRQ table */
borlanic 0:fbdae7e6d805 153 inline operator CThunkEntry(void)
borlanic 0:fbdae7e6d805 154 {
borlanic 0:fbdae7e6d805 155 return (CThunkEntry)entry();
borlanic 0:fbdae7e6d805 156 }
borlanic 0:fbdae7e6d805 157
borlanic 0:fbdae7e6d805 158 /* get thunk entry point for connecting rhunk to an IRQ table */
borlanic 0:fbdae7e6d805 159 inline operator uint32_t(void)
borlanic 0:fbdae7e6d805 160 {
borlanic 0:fbdae7e6d805 161 return entry();
borlanic 0:fbdae7e6d805 162 }
borlanic 0:fbdae7e6d805 163
borlanic 0:fbdae7e6d805 164 /* simple test function */
borlanic 0:fbdae7e6d805 165 inline void call(void)
borlanic 0:fbdae7e6d805 166 {
borlanic 0:fbdae7e6d805 167 (((CThunkEntry)(entry()))());
borlanic 0:fbdae7e6d805 168 }
borlanic 0:fbdae7e6d805 169
borlanic 0:fbdae7e6d805 170 private:
borlanic 0:fbdae7e6d805 171 T* m_instance;
borlanic 0:fbdae7e6d805 172 volatile CCallback m_callback;
borlanic 0:fbdae7e6d805 173
borlanic 0:fbdae7e6d805 174 // TODO: this needs proper fix, to refactor toolchain header file and all its use
borlanic 0:fbdae7e6d805 175 // PACKED there is not defined properly for IAR
borlanic 0:fbdae7e6d805 176 #if defined (__ICCARM__)
borlanic 0:fbdae7e6d805 177 typedef __packed struct
borlanic 0:fbdae7e6d805 178 {
borlanic 0:fbdae7e6d805 179 CTHUNK_VARIABLES;
borlanic 0:fbdae7e6d805 180 volatile uint32_t instance;
borlanic 0:fbdae7e6d805 181 volatile uint32_t context;
borlanic 0:fbdae7e6d805 182 volatile uint32_t callback;
borlanic 0:fbdae7e6d805 183 volatile uint32_t trampoline;
borlanic 0:fbdae7e6d805 184 } CThunkTrampoline;
borlanic 0:fbdae7e6d805 185 #else
borlanic 0:fbdae7e6d805 186 typedef struct
borlanic 0:fbdae7e6d805 187 {
borlanic 0:fbdae7e6d805 188 CTHUNK_VARIABLES;
borlanic 0:fbdae7e6d805 189 volatile uint32_t instance;
borlanic 0:fbdae7e6d805 190 volatile uint32_t context;
borlanic 0:fbdae7e6d805 191 volatile uint32_t callback;
borlanic 0:fbdae7e6d805 192 volatile uint32_t trampoline;
borlanic 0:fbdae7e6d805 193 } __attribute__((__packed__)) CThunkTrampoline;
borlanic 0:fbdae7e6d805 194 #endif
borlanic 0:fbdae7e6d805 195
borlanic 0:fbdae7e6d805 196 static void trampoline(T* instance, void* context, CCallback* callback)
borlanic 0:fbdae7e6d805 197 {
borlanic 0:fbdae7e6d805 198 if(instance && *callback) {
borlanic 0:fbdae7e6d805 199 (static_cast<T*>(instance)->**callback)(context);
borlanic 0:fbdae7e6d805 200 }
borlanic 0:fbdae7e6d805 201 }
borlanic 0:fbdae7e6d805 202
borlanic 0:fbdae7e6d805 203 volatile CThunkTrampoline m_thunk;
borlanic 0:fbdae7e6d805 204
borlanic 0:fbdae7e6d805 205 inline void init(T *instance, CCallback callback, void* context)
borlanic 0:fbdae7e6d805 206 {
borlanic 0:fbdae7e6d805 207 /* remember callback - need to add this level of redirection
borlanic 0:fbdae7e6d805 208 as pointer size for member functions differs between platforms */
borlanic 0:fbdae7e6d805 209 m_callback = callback;
borlanic 0:fbdae7e6d805 210
borlanic 0:fbdae7e6d805 211 /* populate thunking trampoline */
borlanic 0:fbdae7e6d805 212 CTHUNK_ASSIGMENT;
borlanic 0:fbdae7e6d805 213 m_thunk.context = (uint32_t)context;
borlanic 0:fbdae7e6d805 214 m_thunk.instance = (uint32_t)instance;
borlanic 0:fbdae7e6d805 215 m_thunk.callback = (uint32_t)&m_callback;
borlanic 0:fbdae7e6d805 216 m_thunk.trampoline = (uint32_t)&trampoline;
borlanic 0:fbdae7e6d805 217
borlanic 0:fbdae7e6d805 218 #if defined(__CORTEX_A9)
borlanic 0:fbdae7e6d805 219 /* Data cache clean */
borlanic 0:fbdae7e6d805 220 /* Cache control */
borlanic 0:fbdae7e6d805 221 {
borlanic 0:fbdae7e6d805 222 uint32_t start_addr = (uint32_t)&m_thunk & 0xFFFFFFE0;
borlanic 0:fbdae7e6d805 223 uint32_t end_addr = (uint32_t)&m_thunk + sizeof(m_thunk);
borlanic 0:fbdae7e6d805 224 uint32_t addr;
borlanic 0:fbdae7e6d805 225
borlanic 0:fbdae7e6d805 226 /* Data cache clean and invalid */
borlanic 0:fbdae7e6d805 227 for (addr = start_addr; addr < end_addr; addr += 0x20) {
borlanic 0:fbdae7e6d805 228 L1C_CleanInvalidateDCacheMVA((void *)addr);
borlanic 0:fbdae7e6d805 229 }
borlanic 0:fbdae7e6d805 230 /* Instruction cache invalid */
borlanic 0:fbdae7e6d805 231 L1C_InvalidateICacheAll();
borlanic 0:fbdae7e6d805 232 MMU_InvalidateTLB();
borlanic 0:fbdae7e6d805 233 L1C_InvalidateBTAC();
borlanic 0:fbdae7e6d805 234 }
borlanic 0:fbdae7e6d805 235 #endif
borlanic 0:fbdae7e6d805 236 #if defined(__CORTEX_M7)
borlanic 0:fbdae7e6d805 237 /* Data cache clean and invalid */
borlanic 0:fbdae7e6d805 238 SCB_CleanInvalidateDCache();
borlanic 0:fbdae7e6d805 239
borlanic 0:fbdae7e6d805 240 /* Instruction cache invalid */
borlanic 0:fbdae7e6d805 241 SCB_InvalidateICache();
borlanic 0:fbdae7e6d805 242 #endif
borlanic 0:fbdae7e6d805 243 __ISB();
borlanic 0:fbdae7e6d805 244 __DSB();
borlanic 0:fbdae7e6d805 245 }
borlanic 0:fbdae7e6d805 246 };
borlanic 0:fbdae7e6d805 247
borlanic 0:fbdae7e6d805 248 /**@}*/
borlanic 0:fbdae7e6d805 249
borlanic 0:fbdae7e6d805 250 /**@}*/
borlanic 0:fbdae7e6d805 251
borlanic 0:fbdae7e6d805 252 #endif/*__CTHUNK_H__*/
borlanic 0:fbdae7e6d805 253