MCU driver/HAL for the Picocell Gateway concentrator board. The firmware implements either a USB CDC protocol or a UART protocol to bridge commands coming from host to the SX1308 SPI interface.

Committer:
dgabino
Date:
Wed Apr 11 14:42:47 2018 +0000
Revision:
0:c76361bd82e8
Initial commit

Who changed what in which revision?

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