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