mbed library for slider v2

Dependents:   kl46z_slider_v2

Committer:
mturner5
Date:
Wed Sep 14 07:04:27 2016 +0000
Revision:
0:b7116bd48af6
Tried to use the timer.

Who changed what in which revision?

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