temp

Dependencies:   mbed SDFileSystem MS5607 ADXL345_I2C FATFileSystem

Committer:
IKobayashi
Date:
Mon Mar 16 23:37:42 2020 +0900
Revision:
0:c88c3b616c00
copy

Who changed what in which revision?

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