38
38
#ifndef __CTHUNK_H__
39
39
#define __CTHUNK_H__
40
40
41
- #define CTHUNK_ADDRESS 1
42
- #define CTHUNK_VARIABLES volatile uint32_t code[2 ]
43
-
44
- #if (defined(__CORTEX_M3) || defined(__CORTEX_M4) || defined(__CORTEX_M7) || defined(__CORTEX_A9) \
45
- || defined(__CORTEX_M33))
46
- /* *
47
- * CTHUNK disassembly for Cortex-M3/M4/M7/A9 (thumb2):
48
- * * adr r0, #4
49
- * * ldm r0, {r0, r1, r2, pc}
50
- *
51
- * This instruction loads the arguments for the static thunking function to r0-r2, and
52
- * branches to that function by loading its address into PC.
53
- *
54
- * This is safe for both regular calling and interrupt calling, since it only touches scratch registers
55
- * which should be saved by the caller, and are automatically saved as part of the IRQ context switch.
56
- */
57
- #define CTHUNK_ASSIGMENT do { \
58
- m_thunk.code [0 ] = 0xE890A001 ; \
59
- m_thunk.code [1 ] = 0x00008007 ; \
60
- } while (0 )
61
-
62
- #elif (defined(__CORTEX_M0PLUS) || defined(__CORTEX_M0) || defined(__CORTEX_M23))
63
- /*
64
- * CTHUNK disassembly for Cortex M0/M0+ (thumb):
65
- * * adr r0, #4
66
- * * ldm r0, {r0, r1, r2, r3}
67
- * * bx r3
68
- */
69
- #define CTHUNK_ASSIGMENT do { \
70
- m_thunk.code [0 ] = 0xC80FA001 ; \
71
- m_thunk.code [1 ] = 0x00004718 ; \
72
- } while (0 )
73
-
74
- #else
75
- #error "Target is not currently suported."
76
- #endif
77
-
78
- /* IRQ/Exception compatible thunk entry function */
79
- typedef void (*CThunkEntry)(void );
41
+ #include " CThunkBase.h"
80
42
81
43
/* *
82
44
* Class for created a pointer with data bound to it
83
45
*
84
46
* @note Synchronization level: Not protected
85
47
*/
86
48
template <class T >
87
- class CThunk {
49
+ class CThunk : public CThunkBase {
88
50
public:
89
51
typedef void (T::*CCallbackSimple)(void );
90
52
typedef void (T::*CCallback)(void *context);
@@ -101,7 +63,8 @@ class CThunk {
101
63
102
64
~CThunk ()
103
65
{
104
-
66
+ cthunk_free (_entry);
67
+ _entry = NULL ;
105
68
}
106
69
107
70
inline CThunk (T *instance, CCallbackSimple callback)
@@ -126,27 +89,30 @@ class CThunk {
126
89
127
90
inline void callback (CCallback callback)
128
91
{
129
- m_callback = callback;
92
+ _callback = callback;
130
93
}
131
94
132
95
inline void callback (CCallbackSimple callback)
133
96
{
134
- m_callback = (CCallback) callback;
97
+ _callback_simple = callback;
135
98
}
136
99
137
100
inline void context (void *context)
138
101
{
139
- m_thunk. context = ( uint32_t ) context;
102
+ _context = context;
140
103
}
141
104
142
105
inline void context (uint32_t context)
143
106
{
144
- m_thunk. context = context;
107
+ _context = ( void *) context;
145
108
}
146
109
147
110
inline uint32_t entry (void )
148
111
{
149
- return (((uint32_t )&m_thunk) | CTHUNK_ADDRESS);
112
+ if (_entry == NULL ) {
113
+ _entry = cthunk_alloc (this );
114
+ }
115
+ return (uint32_t )_entry;
150
116
}
151
117
152
118
/* get thunk entry point for connecting rhunk to an IRQ table */
@@ -168,78 +134,34 @@ class CThunk {
168
134
}
169
135
170
136
private:
171
- T *m_instance;
172
- volatile CCallback m_callback;
173
-
174
- // TODO: this needs proper fix, to refactor toolchain header file and all its use
175
- // PACKED there is not defined properly for IAR
176
- #if defined (__ICCARM__)
177
- typedef __packed struct {
178
- CTHUNK_VARIABLES;
179
- volatile uint32_t instance;
180
- volatile uint32_t context;
181
- volatile uint32_t callback;
182
- volatile uint32_t trampoline;
183
- } CThunkTrampoline;
184
- #else
185
- typedef struct {
186
- CTHUNK_VARIABLES;
187
- volatile uint32_t instance;
188
- volatile uint32_t context;
189
- volatile uint32_t callback;
190
- volatile uint32_t trampoline;
191
- } __attribute__((__packed__)) CThunkTrampoline;
192
- #endif
193
-
194
- static void trampoline (T *instance, void *context, CCallback *callback)
195
- {
196
- if (instance && *callback) {
197
- (static_cast <T *>(instance)->**callback)(context);
137
+ T *_instance;
138
+ void *_context;
139
+ union {
140
+ CCallbackSimple _callback_simple;
141
+ CCallback _callback;
142
+ };
143
+
144
+ CThunkEntry _entry;
145
+
146
+ static void trampoline (CThunkBase *base)
147
+ {
148
+ CThunk<T> *self = static_cast <CThunk<T>*>(base);
149
+ T *instance = self->_instance ;
150
+ void *context = self->_context ;
151
+ CCallback callback = self->_callback ;
152
+
153
+ if (instance && callback) {
154
+ (instance->*callback)(context);
198
155
}
199
156
}
200
157
201
- volatile CThunkTrampoline m_thunk;
202
-
203
158
inline void init (T *instance, CCallback callback, void *context)
204
159
{
205
- /* remember callback - need to add this level of redirection
206
- as pointer size for member functions differs between platforms */
207
- m_callback = callback;
208
-
209
- /* populate thunking trampoline */
210
- CTHUNK_ASSIGMENT;
211
- m_thunk.context = (uint32_t )context;
212
- m_thunk.instance = (uint32_t )instance;
213
- m_thunk.callback = (uint32_t )&m_callback;
214
- m_thunk.trampoline = (uint32_t )&trampoline;
215
-
216
- #if defined(__CORTEX_A9)
217
- /* Data cache clean */
218
- /* Cache control */
219
- {
220
- uint32_t start_addr = (uint32_t )&m_thunk & 0xFFFFFFE0 ;
221
- uint32_t end_addr = (uint32_t )&m_thunk + sizeof (m_thunk);
222
- uint32_t addr;
223
-
224
- /* Data cache clean and invalid */
225
- for (addr = start_addr; addr < end_addr; addr += 0x20 ) {
226
- L1C_CleanInvalidateDCacheMVA ((void *)addr);
227
- }
228
- /* Instruction cache invalid */
229
- L1C_InvalidateICacheAll ();
230
- MMU_InvalidateTLB ();
231
- L1C_InvalidateBTAC ();
232
- }
233
- #endif
234
- #if defined(__CORTEX_M7)
235
- /* Data cache clean and invalid */
236
- SCB_CleanInvalidateDCache ();
237
-
238
- /* Instruction cache invalid */
239
- SCB_InvalidateICache ();
240
- #endif
241
- __ISB ();
242
- __DSB ();
160
+ _instance = instance;
161
+ _context = context;
162
+ _callback = callback;
163
+ _trampoline = &trampoline;
164
+ _entry = 0 ;
243
165
}
244
166
};
245
167
0 commit comments