Rtos API example

Committer:
marcozecchini
Date:
Sat Feb 23 12:13:36 2019 +0000
Revision:
0:9fca2b23d0ba
final commit

Who changed what in which revision?

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