mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by mbed official

Committer:
StevieWray
Date:
Wed Sep 28 08:45:18 2016 +0000
Revision:
148:e70627d019e9
Parent:
144:ef7eb2e8f9f7
Fixed DAC output on STM32F3 boards to allow 3 outputs

Who changed what in which revision?

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