Includes library modifications to allow access to AIN_4 (AIN_0 / 5)

Committer:
bryantaylor
Date:
Tue Sep 20 21:26:12 2016 +0000
Revision:
0:eafc3fd41f75
hackathon

Who changed what in which revision?

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