osi_compiler.h 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /* Copyright (C) 2018 RDA Technologies Limited and/or its affiliates("RDA").
  2. * All rights reserved.
  3. *
  4. * This software is supplied "AS IS" without any warranties.
  5. * RDA assumes no responsibility or liability for the use of the software,
  6. * conveys no license or title under any patent, copyright, or mask work
  7. * right to the product. RDA reserves the right to make changes in the
  8. * software without notification. RDA also make no representation or
  9. * warranty that such application will be suitable for the specified use
  10. * without further testing or modification.
  11. */
  12. #ifndef _OSI_COMPILER_H_
  13. #define _OSI_COMPILER_H_
  14. #include <stdint.h>
  15. #include <stdbool.h>
  16. #include <stddef.h>
  17. // macros for alias, either strong (global) or weak
  18. #define OSI_STRONG_ALIAS(alias, sym) __asm(".global " #alias "\n" #alias " = " #sym)
  19. #define OSI_WEAK_ALIAS(alias, sym) __asm(".weak " #alias "\n" #alias " = " #sym)
  20. // macro for nop instruction
  21. #define OSI_NOP asm volatile("nop")
  22. // macro for compiler memory access barrier
  23. #define OSI_BARRIER() asm volatile("" :: \
  24. : "memory")
  25. // macro for alignment attribute
  26. #define OSI_CACHE_LINE_ALIGNED __attribute__((aligned(CONFIG_CACHE_LINE_SIZE)))
  27. #define OSI_ALIGNED(n) __attribute__((aligned(n)))
  28. #define OSI_ATTRIBUTE_ISR __attribute__((interrupt))
  29. #define OSI_ATTRIBUTE_USED __attribute__((used))
  30. // macros for "known" sections
  31. #define OSI_SECTION(sect) __attribute__((section(#sect)))
  32. #define OSI_SECTION_SRAM_BOOT_TEXT OSI_SECTION(.sramboottext)
  33. #define OSI_SECTION_SRAM_TEXT OSI_SECTION(.sramtext)
  34. #define OSI_SECTION_SRAM_DATA OSI_SECTION(.sramdata)
  35. #define OSI_SECTION_SRAM_BSS OSI_SECTION(.srambss)
  36. #define OSI_SECTION_SRAM_UNINIT OSI_SECTION(.sramuninit)
  37. #define OSI_SECTION_SRAM_UC_DATA OSI_SECTION(.sramucdata)
  38. #define OSI_SECTION_SRAM_UC_BSS OSI_SECTION(.sramucbss)
  39. #define OSI_SECTION_SRAM_UC_UNINIT OSI_SECTION(.sramucuninit)
  40. #define OSI_SECTION_RAM_TEXT OSI_SECTION(.ramtext)
  41. #define OSI_SECTION_RAM_DATA OSI_SECTION(.ramdata)
  42. #define OSI_SECTION_RAM_BSS OSI_SECTION(.rambss)
  43. #define OSI_SECTION_RAM_UNINIT OSI_SECTION(.ramuninit)
  44. #define OSI_SECTION_RAM_UC_DATA OSI_SECTION(.ramucdata)
  45. #define OSI_SECTION_RAM_UC_BSS OSI_SECTION(.ramucbss)
  46. #define OSI_SECTION_RAM_UC_UNINIT OSI_SECTION(.ramucuninit)
  47. #define OSI_SECTION_BOOT_TEXT OSI_SECTION(.boottext)
  48. #define OSI_SECTION_RO_KEEP __attribute__((used, section(".rokeep")))
  49. #define OSI_SECTION_RW_KEEP __attribute__((used, section(".rwkeep")))
  50. // macros for attributes
  51. #define OSI_WEAK __attribute__((weak))
  52. #define OSI_USED __attribute__((used))
  53. #define OSI_UNUSED __attribute__((unused))
  54. #define OSI_NO_RETURN __attribute__((__noreturn__))
  55. #define OSI_NO_INLINE __attribute__((noinline))
  56. #define OSI_FORCE_INLINE __attribute__((always_inline)) inline
  57. #if __mips__
  58. #define OSI_NO_MIPS16 __attribute__((nomips16))
  59. #else
  60. #define OSI_NO_MIPS16
  61. #endif
  62. // macro maybe helpful for compiler optimization
  63. #define OSI_LIKELY(x) __builtin_expect(!!(x), 1)
  64. #define OSI_UNLIKELY(x) __builtin_expect(!!(x), 0)
  65. // macros for MIPS KSEG0/1
  66. #if __mips__
  67. #define OSI_KSEG0(addr) (((unsigned long)(addr)&0x1fffffff) | 0x80000000)
  68. #define OSI_KSEG1(addr) (((unsigned long)(addr)&0x1fffffff) | 0xa0000000)
  69. #define OSI_IS_KSEG0(addr) (((unsigned long)(addr)&0xe0000000) == 0x80000000)
  70. #define OSI_IS_KSEG1(addr) (((unsigned long)(addr)&0xe0000000) == 0xa0000000)
  71. #define OSI_KSEG01_PHY_ADDR(addr) ((unsigned long)(addr)&0x0FFFFFFF)
  72. #endif
  73. // do { ... } while (0) is common trick to avoid if/else error
  74. #define OSI_DO_WHILE0(expr) \
  75. do \
  76. { \
  77. expr \
  78. } while (0)
  79. // just a dead loop
  80. #define OSI_DEAD_LOOP OSI_DO_WHILE0(for (;;);)
  81. // Busy loop wait until condition is true
  82. #define OSI_LOOP_WAIT(cond) OSI_DO_WHILE0(while (!(cond));)
  83. // wait until condition is true with timeout, use osiDelayUS(8) inside
  84. // return the condition
  85. #define OSI_LOOP_WAIT_TIMEOUT_US(cond, us) ({ unsigned _us8 = (us) / 8; bool _waited = false; for (unsigned n = 0; n < _us8; n++) if (cond) { _waited = true; break; } else { osiDelayUS(8); } _waited; })
  86. // Busy loop wait util condition is true. When polling peripherals, it is
  87. // needed to avoid read peripheral registers without delay, especially
  88. // when the peripheral is connected to a slow bus. This may cause the bus
  89. // is busy to react CPU register read, and other operations are affected.
  90. #define OSI_POLL_WAIT(cond) OSI_DO_WHILE0(while (!(cond)) { OSI_NOP; OSI_NOP; OSI_NOP; OSI_NOP; })
  91. // Wait until condition is true, and return false when cond2 becomes false
  92. #define OSI_LOOP_WAIT_IF(cond, cond2) ({bool _waited = false; do { if (cond) { _waited = true; break; }} while (cond2); _waited; })
  93. // macro for load section, symbol naming style matches linker script
  94. #define OSI_LOAD_SECTION(name) \
  95. do \
  96. { \
  97. extern uint32_t __##name##_start; \
  98. extern uint32_t __##name##_end; \
  99. extern uint32_t __##name##_load_start; \
  100. uint32_t *p; \
  101. uint32_t *l; \
  102. for (p = &__##name##_start, \
  103. l = &__##name##_load_start; \
  104. p < &__##name##_end;) \
  105. *p++ = *l++; \
  106. } while (0)
  107. // macro for clear section, symbol naming style matches linker script
  108. #define OSI_CLEAR_SECTION(name) \
  109. do \
  110. { \
  111. extern uint32_t __##name##_start; \
  112. extern uint32_t __##name##_end; \
  113. uint32_t *p; \
  114. for (p = &__##name##_start; \
  115. p < &__##name##_end;) \
  116. *p++ = 0; \
  117. } while (0)
  118. // macro for fourcc tag
  119. #define OSI_MAKE_TAG(a, b, c, d) ((unsigned)(a) | ((unsigned)(b) << 8) | ((unsigned)(c) << 16) | ((unsigned)(d) << 24))
  120. // macro for array dimension
  121. #define OSI_ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
  122. // macros for 2^n, and 2^n alignment
  123. #define OSI_IS_POW2(v) (((v) & ((v)-1)) == 0)
  124. #define OSI_IS_ALIGNED(v, n) (((unsigned long)(v) & ((n)-1)) == 0)
  125. #define OSI_ALIGN_UP(v, n) (((unsigned long)(v) + (n)-1) & ~((n)-1))
  126. #define OSI_ALIGN_DOWN(v, n) ((unsigned long)(v) & ~((n)-1))
  127. #define OSI_DIV_ROUND(m, n) (((m) + ((n) >> 1)) / (n))
  128. #define OSI_DIV_ROUND_UP(n, m) (((n) + (m)-1) / (m))
  129. // macro for compare two chars ignoring case
  130. #define OSI_CHAR_CASE_EQU(a, b) (((a) | 0x20) == ((b) | 0x20))
  131. // macro to increase the pointer, and return the original pointer
  132. #define OSI_PTR_INCR_POST(p, n) ({uintptr_t _orig = (p); (p) += (n); _orig; })
  133. // pointer (signed) diff, either can be any pointer type
  134. #define OSI_PTR_DIFF(a, b) ((intptr_t)(a) - (intptr_t)(b))
  135. // Macro for variadic argument count
  136. #define OSI_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, N, ...) N
  137. #define OSI_VA_NARGS(...) OSI_VA_NARGS_IMPL(0, ##__VA_ARGS__, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
  138. // macros for declaration and definition
  139. #define OSI_DEF_CONST_VAR(decl, ...) static const decl = __VA_ARGS__
  140. #define OSI_DEF_GLOBAL_VAR(decl, ...) decl = __VA_ARGS__
  141. #define OSI_DECL_GLOBAL_VAR(decl, ...) extern decl
  142. // macros to convert CPU endian to little/big endian
  143. #define OSI_TO_LE16(v) (v)
  144. #define OSI_TO_LE32(v) (v)
  145. #define OSI_TO_BE16(v) __builtin_bswap16(v)
  146. #define OSI_TO_BE32(v) __builtin_bswap32(v)
  147. // macros to convert CPU endian from little/big endian
  148. #define OSI_FROM_LE16(v) (v)
  149. #define OSI_FROM_LE32(v) (v)
  150. #define OSI_FROM_BE16(v) __builtin_bswap16(v)
  151. #define OSI_FROM_BE32(v) __builtin_bswap32(v)
  152. // macro for 32bits register read and write
  153. #define OSI_REG32_WRITE(address, value) *(volatile uint32_t *)(address) = (value)
  154. #define OSI_REG32_READ(address) (*(volatile uint32_t *)(address))
  155. // macros for easier writing
  156. #define OSI_KB(n) ((unsigned)(n) * (unsigned)(1024))
  157. #define OSI_MB(n) ((unsigned)(n) * (unsigned)(1024 * 1024))
  158. #define OSI_GB(n) ((unsigned)(n) * (unsigned)(1024 * 1024 * 1024))
  159. #define OSI_MHZ(n) ((unsigned)(n) * (unsigned)(1000 * 1000))
  160. // macros for min, max. the variable will be accessed only once
  161. #define OSI_MIN(type, a, b) ({ type _a = (type)(a); type _b = (type)(b); _a < _b? _a : _b; })
  162. #define OSI_MAX(type, a, b) ({ type _a = (type)(a); type _b = (type)(b); _a > _b? _a : _b; })
  163. #define OSI_IS_IN_RANGE(type, a, start, end) ({type _a = (type)(a); type _start = (type)(start); type _end = (type)(end); _a >= _start && _a < _end; })
  164. #define OSI_IS_IN_REGION(type, a, start, size) ({type _a = (type)(a); type _start = (type)(start); type _end = _start + (type)(size); _a >= _start && _a < _end; })
  165. #define OSI_RANGE_INSIDE(type, start1, end1, start2, end2) ({type _s1 = (type)(start1), _e1 = (type)(end1), _s2 = (type)(start2), _e2 = (type)(end2); _s1 >= _s2 && _e1 <= _e2; })
  166. #define OSI_REGION_INSIDE(type, start1, size1, start2, size2) ({type _s1 = (type)(start1), _e1 = _s1 + (type)(size1), _s2 = (type)(start2), _e2 = _s2 + (type)(size2); _s1 >= _s2 && _e1 <= _e2; })
  167. // macro to swap 2 variables
  168. #define OSI_SWAP(type, a, b) ({ type _t = (a); (a) = (b); (b) = _t; })
  169. // macro for offsetof and container_of
  170. #define OSI_OFFSETOF(type, member) __builtin_offsetof(type, member)
  171. #define OSI_CONTAINER_OF(ptr, type, member) ((type *)((char *)(ptr)-OSI_OFFSETOF(type, member)))
  172. // assert not enabled by default, and shall not configured globally
  173. #if defined(OSI_LOCAL_DEBUG_ASSERT_ENABLED) && !defined(OSI_DEBUG_ASSERT_DISABLED)
  174. #define OSI_DEBUG_ASSERT(expr) OSI_DO_WHILE0(if (!(expr)) osiPanic();)
  175. #else
  176. #define OSI_DEBUG_ASSERT(expr)
  177. #endif
  178. #ifdef __cplusplus
  179. #define OSI_EXTERN_C extern "C"
  180. #define OSI_EXTERN_C_BEGIN extern "C" {
  181. #define OSI_EXTERN_C_END }
  182. #else
  183. #define OSI_EXTERN_C
  184. #define OSI_EXTERN_C_BEGIN
  185. #define OSI_EXTERN_C_END
  186. #endif
  187. #endif