An example project for the Heltec Turtle LoRa board (STM32L4 and SX1276 chips). The projects is only supported for the Nucleo-L432KC board platform in the mbed online and offline compiler environment. Visit www.radioshuttle.de (choose Turtle board) for instructions. Note that most source files and libraries are open source, however some files especially the RadioShuttle core protocol is copyrighted work. Check header for details.

Dependencies:   mbed BufferedSerial SX1276GenericLib OLED_SSD1306 HELIOS_Si7021 NVProperty RadioShuttle-STM32L4 USBDeviceHT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arch.h Source File

arch.h

00001 /*
00002  * $Id: config.h,v 1.5 2017/02/23 14:31:38 grimrath Exp $
00003  * This is an unpublished work copyright (c) 2019 HELIOS Software GmbH
00004  * 30827 Garbsen, Germany
00005  */
00006 #ifndef __ARCH_H__
00007 #define __ARCH_H__
00008 
00009 #ifdef __cplusplus
00010 #define _extern_c extern "C"
00011 #else
00012 #define _extern_c
00013 #endif
00014 
00015 // --------------------------------------------------------------------------------------------------------------------
00016 // Definitions to adapt between POSIX and MBED
00017 //
00018 #ifdef __MBED__
00019 
00020 #include <mbed_assert.h>
00021 #include <mbed_debug.h>
00022 
00023 #ifdef TARGET_DEBUG
00024 #define DEBUG 1
00025 #define STATIC_ASSERT   MBED_STATIC_ASSERT
00026 #define ASSERT      MBED_ASSERT
00027 #else
00028 #define ASSERT(x)   ((void)0)
00029 #endif
00030 
00031 #define STATIC_ASSERT   MBED_STATIC_ASSERT
00032 
00033 #ifndef TOOLCHAIN_GCC
00034 #ifdef __cplusplus
00035 using std::size_t;
00036 using std::va_list;
00037 using std::abort;
00038 #endif
00039 
00040 _extern_c size_t strnlen(const char *s, size_t maxlen);
00041 _extern_c char *strdup(const char *s);
00042 _extern_c char *stpcpy(char *dest, const char *src);
00043 
00044 #endif
00045 
00046 struct iovec {
00047     void *  iov_base;
00048     size_t  iov_len;
00049 };
00050 
00051 
00052 static inline unsigned read_systicker_us(void) {
00053     extern uint32_t us_ticker_read(void);   // I do not want to include us_ticker_api.h here
00054 
00055     return us_ticker_read();
00056 }
00057 
00058 #define FlashFileSysMount   "Flash"
00059 // #define ESPFileSysMount     "ESP"
00060 #define PseudoFileSysMount  "pseudo"
00061 
00062 #else // __MBED__
00063 
00064 #include <assert.h>
00065 #include <time.h>
00066 
00067 #ifdef __cplusplus
00068 #define STATIC_ASSERT(condition, msg) ((void)sizeof(char[1 - 2*!(condition)]))
00069 #else
00070 #define STATIC_ASSERT(expr, msg)    _Static_assert(expr, msg)  // C11 feature
00071 #endif
00072 #define ASSERT              assert
00073 
00074 //static inline unsigned read_systicker_us(void) {
00075 //  struct timespec ts;
00076 //  clock_gettime(CLOCK_MONOTONIC, &ts);
00077 //  return (ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
00078 //}
00079 
00080 #endif // __MBED__
00081 
00082 
00083 // --------------------------------------------------------------------------------------------------------------------
00084 // synchronize memory contents with external peripherals and interrupt handlers
00085 //
00086 // __ATOMIC_RELAXED should be ok since we are only dealing with irq handlers on exactly one CPU/MCU
00087 //
00088 // __atomic_load_n is not available in the online IDE (yet)
00089 //
00090 #if defined(__ATOMIC_RELAXED)
00091 
00092 #define help_atomic_load_relaxed(ptr) __atomic_load_n((ptr), __ATOMIC_RELAXED)
00093 
00094 #define help_atomic_store_relaxed(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_RELAXED)
00095 
00096 #define help_atomic_readclr_relaxed(ptr) __atomic_exchange_n((ptr), 0, __ATOMIC_RELAXED)
00097 
00098 #define help_atomic_or_relaxed(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_RELAXED)
00099 
00100 #ifdef __cplusplus
00101 template<typename T> inline bool help_atomic_compare_and_swap(T *ptr, T checkval, T newval) {
00102     return __atomic_compare_exchange_n(ptr, &checkval, newval, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
00103 }
00104 #else
00105 #define help_atomic_compare_and_swap(ptr, checkval, newval) __sync_bool_compare_and_swap((ptr), (checkval), (newval))
00106 #endif
00107 
00108 #define sync_memory(mem) do { \
00109     asm volatile("" : "=m" (mem)); \
00110     __atomic_thread_fence(__ATOMIC_SEQ_CST); \
00111 } while (0)
00112 
00113 #define irq_barrier() __atomic_signal_fence(__ATOMIC_SEQ_CST)
00114 
00115 #define sync_memory_all() do { \
00116     asm volatile("" : : : "memory"); \
00117     __atomic_thread_fence(__ATOMIC_SEQ_CST); \
00118 } while (0)
00119 
00120 #else // defined(__ATOMIC_RELAXED)
00121 
00122 #define help_atomic_load_relaxed(ptr) (*(ptr))
00123 
00124 #define help_atomic_store_relaxed(ptr, val) ((void)(*(ptr) = (val)))
00125 
00126 #define help_atomic_readclr_relaxed(ptr) __sync_fetch_and_and((ptr), 0)
00127 
00128 #define help_atomic_or_relaxed(ptr, val) __sync_fetch_and_or((ptr), (val))
00129 
00130 #define help_atomic_compare_and_swap(ptr, checkval, newval) __sync_bool_compare_and_swap((ptr), (checkval), (newval))
00131 
00132 #define sync_memory(mem) __sync_synchronize()
00133 
00134 #define sync_memory_all() __sync_synchronize()
00135 
00136 #define irq_barrier() __sync_synchronize()
00137 
00138 #endif
00139 
00140 
00141 #define help_atomic_init(ptr, initval) do { *(ptr) = (initval); } while (0)
00142 
00143 // --------------------------------------------------------------------------------------------------------------------
00144 // other
00145 
00146 #define ispowerof2(x) (((x) & ((x) - 1)) == 0)
00147 
00148 static inline uint32_t alignup32(uint32_t size, uint32_t next) {
00149     uint32_t next1 = next - 1;
00150     ASSERT((next & next1) == 0);    // 2^n check
00151     return (size + next1) & ~next1;
00152 }
00153 
00154 
00155 // --------------------------------------------------------------------------------------------------------------------
00156 // typesafe macros to get the number of compile-time known array elements.
00157 //
00158 #ifdef __cplusplus
00159 
00160 template< typename T, std::size_t N > char(&COUNTOF_REQUIRES_ARRAY_ARGUMENT(T(&)[N]))[N];
00161 #define ARRAYLEN(x) sizeof(COUNTOF_REQUIRES_ARRAY_ARGUMENT(x))
00162 
00163 #else
00164 
00165 // MBED OS online compiler does not support unnamed and zero sized bitfields as GCC does
00166 // #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))    // used by Linux kernel
00167 #define __must_be_zero(e) (sizeof(struct { char dummy:(1 - 2*!!(e)); }) - 1)
00168 
00169 // __builtin_types_compatible_p: gcc extension, but understood by Intel, clang and ARM compilers too
00170 // __builtin_types_compatible_p is not available in C++
00171 #define __must_be_array(arr) __must_be_zero(__builtin_types_compatible_p(typeof(arr), typeof(&(arr)[0])))
00172 
00173 #define ARRAYLEN(arr) (sizeof(arr) / sizeof(0[arr])) + __must_be_array(arr)
00174 
00175 #endif
00176 
00177 
00178 // --------------------------------------------------------------------------------------------------------------------
00179 // quick int32 -> int conversion mainly for printf. Shorter than static_cast<int> and works with C too.
00180 //
00181 static inline int itoi(int val) { return val; }
00182 static inline long long lltoll(long long val) { return val; }
00183 
00184 
00185 // --------------------------------------------------------------------------------------------------------------------
00186 // Byte order
00187 //
00188 #ifdef __MBED__
00189 
00190 #if BYTE_ORDER == LITTLE_ENDIAN
00191 
00192 static inline uint16_t htole16(uint16_t x) { return x; }
00193 static inline uint16_t le16toh(uint16_t x) { return x; }
00194 static inline uint32_t htole32(uint32_t x) { return x; }
00195 static inline uint32_t le32toh(uint32_t x) { return x; }
00196 
00197 #else
00198 
00199 // unused big endian variants
00200 // static inline uint16_t htobe16(uint16_t x) { return __REV16(x); }
00201 // static inline uint16_t be16toh(uint16_t x) { return __REV16(x); }
00202 // static inline uint32_t htobe32(uint32_t x) { return __REV(x); }
00203 // static inline uint32_t be32toh(uint32_t x) { return __REV(x); }
00204 
00205 #endif
00206 
00207 #elif defined(__linux__)
00208 
00209 #include <endian.h>
00210 
00211 #elif defined(__APPLE__)
00212 
00213 #include <libkern/OSByteOrder.h>
00214 #define htole16 OSSwapHostToLittleInt16
00215 #define le16toh OSSwapHostToLittleInt16
00216 #define htole32 OSSwapHostToLittleInt32
00217 #define le32toh OSSwapHostToLittleInt32
00218 
00219 #endif
00220 
00221 
00222 // --------------------------------------------------------------------------------------------------------------------
00223 // memory debugging
00224 //
00225 #ifdef DEBUG
00226 
00227 #ifdef USE_VALGRIND
00228 
00229 #include <valgrind/valgrind.h>
00230 #include <valgrind/memcheck.h>
00231 #include <string.h>
00232 
00233 #define CHECKDEFINED(obj) VALGRIND_CHECK_MEM_IS_DEFINED(&(obj), sizeof(obj))
00234 
00235 #endif // ! valgrind
00236 
00237 static inline void POISONMEM(void *ptr, size_t sz) {
00238     memset(ptr, 0x55, sz);
00239 #ifdef USE_VALGRIND
00240     VALGRIND_MAKE_MEM_UNDEFINED(ptr, sz);
00241 #endif
00242 }
00243 
00244 #define POISON(obj) POISONMEM(&(obj), sizeof(obj))
00245 
00246 #else // ! DEBUG
00247 
00248 #ifdef USE_VALGRIND
00249 #error valgrind features only useable in debug builds
00250 #endif
00251 
00252 static inline void POISONMEM(void *ptr, size_t sz) { (void)ptr; (void)sz; }
00253 
00254 #define POISON(obj) ((void)0)
00255 
00256 #endif // DEBUG
00257 
00258 // --------------------------------------------------------------------------------------------------------------------
00259 // Macros to live bookmark code
00260 //
00261 #ifdef DEBUG
00262 
00263 _extern_c void dbg_fail_handler(const char *file, int line, const char *func, const char *msg) __attribute__((noreturn));
00264 
00265 #define TODO(...)   dbg_fail_handler(__FILE__, __LINE__, __func__, "TODO" __VA_ARGS__)
00266 #define UNTESTED()  dbg_fail_handler(__FILE__, __LINE__, __func__, "UNTESTED")
00267 #define UNREACHABLE()   dbg_fail_handler(__FILE__, __LINE__, __func__, "UNREACHABLE")
00268 #if defined(__x86_64__) || defined(__i386__)
00269 #define BREAKPOINT()    asm("int $3")
00270 #elif defined(__arm__)
00271 #define BREAKPOINT()    __BKPT(0)
00272 #else
00273 #error no compile time breakpoints supplied for this architecture - add them if needed
00274 #endif
00275 
00276 #else // ! debug
00277 
00278 #define TODO(...)   abort()
00279 #define UNTESTED()  ((void)0)
00280 #ifdef __MBED__
00281 #   define UNREACHABLE()    MBED_UNREACHABLE
00282 #else
00283 #   define UNREACHABLE() __builtin_unreachable()
00284 #endif
00285 // no BREAKPOINT() - these must be removed in release builds
00286 
00287 #endif // debug
00288 
00289 
00290 
00291 // --------------------------------------------------------------------------------------------------------------------
00292 // Tracing
00293 //
00294 #ifdef DEBUG
00295 
00296 // Do not call these directly, use DTRC
00297 _extern_c void trc_dbg(const char *file, int line, const char *func, const char *fmt, ...) __attribute__((format(printf,4,5)));
00298 _extern_c void trc_vdbg(const char *file, int line, const char *func, const char *fmt, va_list ap);
00299 
00300 #define DTRC(_fmt, ...) trc_dbg(__FILE__, __LINE__, __func__, (_fmt), ## __VA_ARGS__)
00301 
00302 
00303 #else // DEBUG
00304 
00305 #define DTRC(_fmt, ...) ((void)0)
00306 
00307 #endif
00308 
00309 // Do not call these directly, use TRC_* macros
00310 _extern_c void trc_printf(const char *fmt, ...) __attribute__((format(printf,1,2)));
00311 _extern_c void trc_vprintf(const char *fmt, va_list ap);
00312 
00313 // These exists even in release builds
00314 #define TRC_INF(_fmt, ...) trc_printf((_fmt), ## __VA_ARGS__)
00315 #define TRC_WRN TRC_INF
00316 #define TRC_ERR TRC_INF
00317 #define TRC_VERR(fmt, ap) trc_vprintf((fmt), (ap))
00318 
00319 #endif // __ARCH_H__