Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers uvisor_exports.h Source File

uvisor_exports.h

00001 /*
00002  * Copyright (c) 2013-2015, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 #ifndef __UVISOR_API_UVISOR_EXPORTS_H__
00018 #define __UVISOR_API_UVISOR_EXPORTS_H__
00019 
00020 #include <stdint.h>
00021 #include <stddef.h>
00022 
00023 /* maximum number of boxes allowed: 1 is the minimum (unprivileged box) */
00024 #define UVISOR_MAX_BOXES 5U
00025 
00026 #define UVISOR_WAIT_FOREVER (0xFFFFFFFFUL)
00027 
00028 /* extern keyword */
00029 #ifdef  __cplusplus
00030 #define UVISOR_EXTERN extern "C"
00031 #else
00032 #define UVISOR_EXTERN extern
00033 #endif/*__CPP__*/
00034 
00035 /** Extern C block macros
00036  *
00037  * Use these macros to disable name mangling in C++. Use these macros instead
00038  * of UVISOR_EXTERN when you also need to initialize the object. C++ compilers
00039  * warn when initializing an object declared as `extern`. Use of these macros
00040  * enables the defining of global non-name-mangled symbols in C++ without
00041  * affecting C code (which doesn't ever name mangle).  */
00042 #ifdef  __cplusplus
00043 #define UVISOR_EXTERN_C_BEGIN extern "C" {
00044 #define UVISOR_EXTERN_C_END }
00045 #else
00046 #define UVISOR_EXTERN_C_BEGIN
00047 #define UVISOR_EXTERN_C_END
00048 #endif
00049 
00050 /* asm keyword */
00051 #ifndef asm
00052 #define asm __asm__
00053 #endif
00054 
00055 /* Shared compiler attributes */
00056 #if defined(__ICCARM__)
00057 #define UVISOR_ALIGN(x)    __align(x)
00058 #define UVISOR_FORCEINLINE inline
00059 #define UVISOR_PACKED      __packed
00060 #define UVISOR_WEAK        __weak
00061 #define UVISOR_NORETURN    __noreturn
00062 #define UVISOR_RAMFUNC     __ramfunc
00063 #define UVISOR_DEPRECATED
00064 #else
00065 #define UVISOR_ALIGN(x)    __attribute__((aligned(x)))
00066 #define UVISOR_FORCEINLINE inline __attribute__((always_inline))
00067 #define UVISOR_PACKED      __attribute__((packed))
00068 #define UVISOR_WEAK        __attribute__((weak))
00069 #define UVISOR_NORETURN    __attribute__((noreturn))
00070 #define UVISOR_RAMFUNC     __attribute__ ((section (".ramfunc"), noinline))
00071 #define UVISOR_DEPRECATED  __attribute__((deprecated))
00072 #endif
00073 
00074 /* array count macro */
00075 #define UVISOR_ARRAY_COUNT(x) (sizeof(x)/sizeof(x[0]))
00076 
00077 /** Static Assertion Macro
00078  *
00079  * This macro works from both inside and outside function scope.
00080  * The implementations differ due to compilation differences, C++ static_assert
00081  * is known from C++11 (__cplusplus > 199711L) while mbed-os compiles with c++98,
00082  * and C _Static_assert is known from GCC version 4.6.0. */ 
00083 #define GCC_VERSION (__GNUC__ * 10000 \
00084                      + __GNUC_MINOR__ * 100 \
00085                      + __GNUC_PATCHLEVEL__)
00086 #if (__cplusplus > 199711L)
00087 #define UVISOR_STATIC_ASSERT(cond, msg) static_assert(cond, #msg)
00088 #elif (!__cplusplus && GCC_VERSION > 40600)
00089 #define UVISOR_STATIC_ASSERT(cond, msg) _Static_assert(cond, #msg)
00090 #else
00091 #define UVISOR_STATIC_ASSERT(cond, msg) typedef char STATIC_ASSERT_##msg[(cond)?1:-1]
00092 #endif
00093 
00094 /* convert macro argument to string */
00095 /* note: this needs one level of indirection, accomplished with the helper macro
00096  *       __UVISOR_TO_STRING */
00097 #define __UVISOR_TO_STRING(x) #x
00098 #define UVISOR_TO_STRING(x)   __UVISOR_TO_STRING(x)
00099 
00100 /* select an overloaded macro, so that 0 to 4 arguments can be used */
00101 #define __UVISOR_MACRO_SELECT(_0, _1, _2, _3, _4, NAME, ...) NAME
00102 
00103 /* count macro arguments */
00104 #define UVISOR_MACRO_NARGS(...) \
00105      __UVISOR_MACRO_SELECT(_0, ##__VA_ARGS__, 4, 3, 2, 1, 0)
00106 
00107 /* declare explicit callee-saved registers to hold input arguments (0 to 4) */
00108 /* note: sizeof(type) must be less than or equal to 4 */
00109 #define UVISOR_MACRO_REGS_ARGS(type, ...) \
00110      __UVISOR_MACRO_SELECT(_0, ##__VA_ARGS__, __UVISOR_MACRO_REGS_ARGS4, \
00111                                               __UVISOR_MACRO_REGS_ARGS3, \
00112                                               __UVISOR_MACRO_REGS_ARGS2, \
00113                                               __UVISOR_MACRO_REGS_ARGS1, \
00114                                               __UVISOR_MACRO_REGS_ARGS0)(type, ##__VA_ARGS__)
00115 #define __UVISOR_MACRO_REGS_ARGS0(type)
00116 #define __UVISOR_MACRO_REGS_ARGS1(type, a0) \
00117         register type r0 asm("r0") = (type) a0;
00118 #define __UVISOR_MACRO_REGS_ARGS2(type, a0, a1) \
00119         register type r0 asm("r0") = (type) a0; \
00120         register type r1 asm("r1") = (type) a1;
00121 #define __UVISOR_MACRO_REGS_ARGS3(type, a0, a1, a2) \
00122         register type r0 asm("r0") = (type) a0; \
00123         register type r1 asm("r1") = (type) a1; \
00124         register type r2 asm("r2") = (type) a2;
00125 #define __UVISOR_MACRO_REGS_ARGS4(type, a0, a1, a2, a3) \
00126         register type r0 asm("r0") = (type) a0; \
00127         register type r1 asm("r1") = (type) a1; \
00128         register type r2 asm("r2") = (type) a2; \
00129         register type r3 asm("r3") = (type) a3;
00130 
00131 /* declare explicit callee-saved registers to hold output values */
00132 /* note: currently only one output value is allowed, up to 32bits */
00133 #define UVISOR_MACRO_REGS_RETVAL(type, name) \
00134     register type name asm("r0");
00135 
00136 UVISOR_FORCEINLINE void uvisor_noreturn(void)
00137 {
00138     volatile int var = 1;
00139     while(var);
00140 }
00141 
00142 /* declare callee-saved input/output operands for gcc-style inline asm */
00143 /* note: this macro requires that a C variable having the same name of the
00144  *       corresponding callee-saved register is declared; these operands follow
00145  *       the official ABI for ARMv7M (e.g. 2 input arguments of 32bits each max,
00146  *       imply that registers r0 and r1 are used) */
00147 /* note: gcc only */
00148 /* note: for 0 inputs a dummy immediate is passed to avoid errors on a misplaced
00149  *       comma in the inline assembly */
00150 #ifdef __GNUC__
00151 
00152 #define UVISOR_MACRO_GCC_ASM_INPUT(...) \
00153      __UVISOR_MACRO_SELECT(_0, ##__VA_ARGS__, __UVISOR_MACRO_GCC_ASM_INPUT4, \
00154                                               __UVISOR_MACRO_GCC_ASM_INPUT3, \
00155                                               __UVISOR_MACRO_GCC_ASM_INPUT2, \
00156                                               __UVISOR_MACRO_GCC_ASM_INPUT1, \
00157                                               __UVISOR_MACRO_GCC_ASM_INPUT0)(__VA_ARGS__)
00158 #define __UVISOR_MACRO_GCC_ASM_INPUT0()               [__dummy] "I" (0)
00159 #define __UVISOR_MACRO_GCC_ASM_INPUT1(a0)             [r0] "r" (r0)
00160 #define __UVISOR_MACRO_GCC_ASM_INPUT2(a0, a1)         [r0] "r" (r0), [r1] "r" (r1)
00161 #define __UVISOR_MACRO_GCC_ASM_INPUT3(a0, a1, a2)     [r0] "r" (r0), [r1] "r" (r1), [r2] "r" (r2)
00162 #define __UVISOR_MACRO_GCC_ASM_INPUT4(a0, a1, a2, a3) [r0] "r" (r0), [r1] "r" (r1), [r2] "r" (r2), [r3] "r" (r3)
00163 
00164 #define UVISOR_MACRO_GCC_ASM_OUTPUT(name) [res] "=r" (name)
00165 
00166 #endif /* __GNUC__ */
00167 
00168 /* this macro multiplexes read/write opcodes depending on the number of
00169  * arguments */
00170 #define UVISOR_ASM_MEMORY_ACCESS(opcode, type, ...) \
00171     __UVISOR_MACRO_SELECT(_0, ##__VA_ARGS__, /* no macro for 4 args */   , \
00172                                              /* no macro for 3 args */   , \
00173                                              __UVISOR_ASM_MEMORY_ACCESS_W, \
00174                                              __UVISOR_ASM_MEMORY_ACCESS_R, \
00175                                              /* no macro for 0 args */   )(opcode, type, ##__VA_ARGS__)
00176 /* the macros that actually generate the assembly code for the memory access are
00177  * toolchain-specific */
00178 #if defined(__CC_ARM)
00179 
00180 /* TODO/FIXME */
00181 
00182 #elif defined(__GNUC__)
00183 
00184 #define __UVISOR_ASM_MEMORY_ACCESS_R(opcode, type, ...) \
00185     ({ \
00186         UVISOR_MACRO_REGS_ARGS(uint32_t, ##__VA_ARGS__); \
00187         UVISOR_MACRO_REGS_RETVAL(type, res); \
00188         asm volatile( \
00189             UVISOR_TO_STRING(opcode)" %[res], [%[r0]]\n" \
00190             UVISOR_NOP_GROUP \
00191             : UVISOR_MACRO_GCC_ASM_OUTPUT(res) \
00192             : UVISOR_MACRO_GCC_ASM_INPUT(__VA_ARGS__) \
00193         ); \
00194         res; \
00195     })
00196 
00197 #define __UVISOR_ASM_MEMORY_ACCESS_W(opcode, type, ...) \
00198     UVISOR_MACRO_REGS_ARGS(uint32_t, ##__VA_ARGS__); \
00199     asm volatile( \
00200         UVISOR_TO_STRING(opcode)" %[r1], [%[r0]]\n" \
00201         UVISOR_NOP_GROUP \
00202         : \
00203         : UVISOR_MACRO_GCC_ASM_INPUT(__VA_ARGS__) \
00204     );
00205 
00206 #endif /* defined(__CC_ARM) || defined(__GNUC__) */
00207 
00208 typedef struct {
00209     void (*function)(const void *);
00210     size_t priority;
00211     size_t stack_size;
00212 } uvisor_box_main_t;
00213 
00214 #endif /* __UVISOR_API_UVISOR_EXPORTS_H__ */