mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Committer:
be_bryan
Date:
Mon Dec 11 17:54:04 2017 +0000
Revision:
0:b74591d5ab33
motor ++

Who changed what in which revision?

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