Home Alert System

Dependencies:   PWM_Tone_Library DHT

Committer:
aziz111
Date:
Fri Mar 08 17:15:02 2019 +0000
Revision:
5:569a4894abc1
Parent:
3:78f223d34f36
Final

Who changed what in which revision?

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