test test test

Dependencies:   mbed

Committer:
mohamedmoawya
Date:
Mon May 25 19:06:11 2020 +0000
Revision:
0:e4c5e6ec922e
snake game tteest

Who changed what in which revision?

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