cy_utils.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. /***************************************************************************//**
  2. * \file cy_utils.h
  3. *
  4. * \brief
  5. * Basic utility macros and functions.
  6. *
  7. ********************************************************************************
  8. * \copyright
  9. * Copyright 2018-2020 Cypress Semiconductor Corporation
  10. * SPDX-License-Identifier: Apache-2.0
  11. *
  12. * Licensed under the Apache License, Version 2.0 (the "License");
  13. * you may not use this file except in compliance with the License.
  14. * You may obtain a copy of the License at
  15. *
  16. * http://www.apache.org/licenses/LICENSE-2.0
  17. *
  18. * Unless required by applicable law or agreed to in writing, software
  19. * distributed under the License is distributed on an "AS IS" BASIS,
  20. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  21. * See the License for the specific language governing permissions and
  22. * limitations under the License.
  23. *******************************************************************************/
  24. /**
  25. * \addtogroup group_utils Utilities
  26. * \ingroup group_abstraction
  27. * \{
  28. * Basic utility macros and functions.
  29. */
  30. #if !defined(CY_UTILS_H)
  31. #define CY_UTILS_H
  32. #if defined(__cplusplus)
  33. extern "C" {
  34. #endif
  35. /** Simple macro to supress the unused parameter warning by casting to void. */
  36. #define CY_UNUSED_PARAMETER(x) ( (void)(x) )
  37. /** Halt the processor in the debug state
  38. */
  39. static inline void CY_HALT(void)
  40. {
  41. __asm(" bkpt 1");
  42. }
  43. #ifdef CY_ASSERT
  44. #undef CY_ASSERT
  45. #endif /* ifdef(CY_ASSERT) */
  46. /** Utility macro when neither NDEBUG or CY_NO_ASSERT is not declared to check a condition and, if false, trigger a breakpoint */
  47. #if defined(NDEBUG) || defined(CY_NO_ASSERT)
  48. #define CY_ASSERT(x) do { \
  49. } while(0)
  50. #else
  51. #define CY_ASSERT(x) do { \
  52. if(!(x)) \
  53. { \
  54. CY_HALT(); \
  55. } \
  56. } while(0)
  57. #endif /* defined(NDEBUG) */
  58. /*******************************************************************************
  59. * Data manipulation defines
  60. *******************************************************************************/
  61. /** Get the lower 8 bits of a 16-bit value. */
  62. #define CY_LO8(x) ((uint8_t) ((x) & 0xFFU))
  63. /** Get the upper 8 bits of a 16-bit value. */
  64. #define CY_HI8(x) ((uint8_t) ((uint16_t)(x) >> 8U))
  65. /** Get the lower 16 bits of a 32-bit value. */
  66. #define CY_LO16(x) ((uint16_t) ((x) & 0xFFFFU))
  67. /** Get the upper 16 bits of a 32-bit value. */
  68. #define CY_HI16(x) ((uint16_t) ((uint32_t)(x) >> 16U))
  69. /** Swap the byte ordering of a 16-bit value */
  70. #define CY_SWAP_ENDIAN16(x) ((uint16_t)(((x) << 8U) | (((x) >> 8U) & 0x00FFU)))
  71. /** Swap the byte ordering of a 32-bit value */
  72. #define CY_SWAP_ENDIAN32(x) ((uint32_t)((((x) >> 24U) & 0x000000FFU) | (((x) & 0x00FF0000U) >> 8U) | \
  73. (((x) & 0x0000FF00U) << 8U) | ((x) << 24U)))
  74. /** Swap the byte ordering of a 64-bit value */
  75. #define CY_SWAP_ENDIAN64(x) ((uint64_t) (((uint64_t) CY_SWAP_ENDIAN32((uint32_t)(x)) << 32U) | \
  76. CY_SWAP_ENDIAN32((uint32_t)((x) >> 32U))))
  77. /*******************************************************************************
  78. * Memory model definitions
  79. *******************************************************************************/
  80. #if defined(__ARMCC_VERSION)
  81. /** To create cross compiler compatible code, use the CY_NOINIT, CY_SECTION, CY_UNUSED, CY_ALIGN
  82. * attributes at the first place of declaration/definition.
  83. * For example: CY_NOINIT uint32_t noinitVar;
  84. */
  85. #if (__ARMCC_VERSION >= 6010050)
  86. #define CY_NOINIT __attribute__ ((section(".noinit")))
  87. #else
  88. #define CY_NOINIT __attribute__ ((section(".noinit"), zero_init))
  89. #endif /* (__ARMCC_VERSION >= 6010050) */
  90. #define CY_SECTION(name) __attribute__ ((section(name)))
  91. #define CY_UNUSED __attribute__ ((unused))
  92. #define CY_NOINLINE __attribute__ ((noinline))
  93. /* Specifies the minimum alignment (in bytes) for variables of the specified type. */
  94. #define CY_ALIGN(align) __ALIGNED(align)
  95. #define CY_RAMFUNC_BEGIN __attribute__ ((section(".cy_ramfunc")))
  96. #define CY_RAMFUNC_END
  97. #elif defined (__GNUC__)
  98. #if defined (__clang__)
  99. #define CY_NOINIT __attribute__ ((section("__DATA, __noinit")))
  100. #define CY_SECTION(name) __attribute__ ((section("__DATA, "name)))
  101. #define CY_RAMFUNC_BEGIN __attribute__ ((section("__DATA, .cy_ramfunc")))
  102. #define CY_RAMFUNC_END
  103. #else
  104. #define CY_NOINIT __attribute__ ((section(".noinit")))
  105. #define CY_SECTION(name) __attribute__ ((section(name)))
  106. #define CY_RAMFUNC_BEGIN __attribute__ ((section(".cy_ramfunc")))
  107. #define CY_RAMFUNC_END
  108. #endif
  109. #define CY_UNUSED __attribute__ ((unused))
  110. #define CY_NOINLINE __attribute__ ((noinline))
  111. #define CY_ALIGN(align) __ALIGNED(align)
  112. #elif defined (__ICCARM__)
  113. #define CY_PRAGMA(x) _Pragma(#x)
  114. #define CY_NOINIT __no_init
  115. #define CY_SECTION(name) CY_PRAGMA(location = name)
  116. #define CY_UNUSED
  117. #define CY_NOINLINE CY_PRAGMA(optimize = no_inline)
  118. #define CY_RAMFUNC_BEGIN CY_PRAGMA(diag_suppress = Ta023) __ramfunc
  119. #define CY_RAMFUNC_END CY_PRAGMA(diag_default = Ta023)
  120. #if (__VER__ < 8010001)
  121. #define CY_ALIGN(align) CY_PRAGMA(data_alignment = align)
  122. #else
  123. #define CY_ALIGN(align) __ALIGNED(align)
  124. #endif /* (__VER__ < 8010001) */
  125. #else
  126. #error "An unsupported toolchain"
  127. #endif /* (__ARMCC_VERSION) */
  128. /*******************************************************************************
  129. * Macro Name: CY_GET_REG8(addr)
  130. ****************************************************************************//**
  131. *
  132. * Reads the 8-bit value from the specified address. This function can't be
  133. * used to access the Core register, otherwise a fault occurs.
  134. *
  135. * \param addr The register address.
  136. *
  137. * \return The read value.
  138. *
  139. *******************************************************************************/
  140. #define CY_GET_REG8(addr) (*((const volatile uint8_t *)(addr)))
  141. /*******************************************************************************
  142. * Macro Name: CY_SET_REG8(addr, value)
  143. ****************************************************************************//**
  144. *
  145. * Writes an 8-bit value to the specified address. This function can't be
  146. * used to access the Core register, otherwise a fault occurs.
  147. *
  148. * \param addr The register address.
  149. *
  150. * \param value The value to write.
  151. *
  152. *******************************************************************************/
  153. #define CY_SET_REG8(addr, value) (*((volatile uint8_t *)(addr)) = (uint8_t)(value))
  154. /*******************************************************************************
  155. * Macro Name: CY_GET_REG16(addr)
  156. ****************************************************************************//**
  157. *
  158. * Reads the 16-bit value from the specified address.
  159. *
  160. * \param addr The register address.
  161. *
  162. * \return The read value.
  163. *
  164. *******************************************************************************/
  165. #define CY_GET_REG16(addr) (*((const volatile uint16_t *)(addr)))
  166. /*******************************************************************************
  167. * Macro Name: CY_SET_REG16(addr, value)
  168. ****************************************************************************//**
  169. *
  170. * Writes the 16-bit value to the specified address.
  171. *
  172. * \param addr The register address.
  173. *
  174. * \param value The value to write.
  175. *
  176. *******************************************************************************/
  177. #define CY_SET_REG16(addr, value) (*((volatile uint16_t *)(addr)) = (uint16_t)(value))
  178. /*******************************************************************************
  179. * Macro Name: CY_GET_REG24(addr)
  180. ****************************************************************************//**
  181. *
  182. * Reads the 24-bit value from the specified address.
  183. *
  184. * \param addr The register address.
  185. *
  186. * \return The read value.
  187. *
  188. *******************************************************************************/
  189. #define CY_GET_REG24(addr) (((uint32_t) (*((const volatile uint8_t *)(addr)))) | \
  190. (((uint32_t) (*((const volatile uint8_t *)(addr) + 1))) << 8U) | \
  191. (((uint32_t) (*((const volatile uint8_t *)(addr) + 2))) << 16U))
  192. /*******************************************************************************
  193. * Macro Name: CY_SET_REG24(addr, value)
  194. ****************************************************************************//**
  195. *
  196. * Writes the 24-bit value to the specified address.
  197. *
  198. * \param addr The register address.
  199. *
  200. * \param value The value to write.
  201. *
  202. *******************************************************************************/
  203. #define CY_SET_REG24(addr, value) do \
  204. { \
  205. (*((volatile uint8_t *) (addr))) = (uint8_t)(value); \
  206. (*((volatile uint8_t *) (addr) + 1)) = (uint8_t)((value) >> 8U); \
  207. (*((volatile uint8_t *) (addr) + 2)) = (uint8_t)((value) >> 16U); \
  208. } \
  209. while(0)
  210. /*******************************************************************************
  211. * Macro Name: CY_GET_REG32(addr)
  212. ****************************************************************************//**
  213. *
  214. * Reads the 32-bit value from the specified register. The address is the little
  215. * endian order (LSB in lowest address).
  216. *
  217. * \param addr The register address.
  218. *
  219. * \return The read value.
  220. *
  221. *******************************************************************************/
  222. #define CY_GET_REG32(addr) (*((const volatile uint32_t *)(addr)))
  223. /*******************************************************************************
  224. * Macro Name: CY_SET_REG32(addr, value)
  225. ****************************************************************************//**
  226. *
  227. * Writes the 32-bit value to the specified register. The address is the little
  228. * endian order (LSB in lowest address).
  229. *
  230. * \param addr The register address.
  231. *
  232. * \param value The value to write.
  233. *
  234. *******************************************************************************/
  235. #define CY_SET_REG32(addr, value) (*((volatile uint32_t *)(addr)) = (uint32_t)(value))
  236. /*******************************************************************************
  237. * Macro Name: _CLR_SET_FLD32U
  238. ****************************************************************************//**
  239. *
  240. * The macro for setting a register with a name field and value for providing
  241. * get-clear-modify-write operations.
  242. * Returns a resulting value to be assigned to the register.
  243. *
  244. *******************************************************************************/
  245. #define _CLR_SET_FLD32U(reg, field, value) (((reg) & ((uint32_t)(~(field ## _Msk)))) | (_VAL2FLD(field, value)))
  246. /*******************************************************************************
  247. * Macro Name: CY_REG32_CLR_SET
  248. ****************************************************************************//**
  249. *
  250. * Uses _CLR_SET_FLD32U macro for providing get-clear-modify-write
  251. * operations with a name field and value and writes a resulting value
  252. * to the 32-bit register.
  253. *
  254. *******************************************************************************/
  255. #define CY_REG32_CLR_SET(reg, field, value) ((reg) = _CLR_SET_FLD32U((reg), field, (value)))
  256. /*******************************************************************************
  257. * Macro Name: _CLR_SET_FLD16U
  258. ****************************************************************************//**
  259. *
  260. * The macro for setting a 16-bit register with a name field and value for providing
  261. * get-clear-modify-write operations.
  262. * Returns a resulting value to be assigned to the 16-bit register.
  263. *
  264. *******************************************************************************/
  265. #define _CLR_SET_FLD16U(reg, field, value) ((uint16_t)(((reg) & ((uint16_t)(~(field ## _Msk)))) | \
  266. ((uint16_t)_VAL2FLD(field, value))))
  267. /*******************************************************************************
  268. * Macro Name: CY_REG16_CLR_SET
  269. ****************************************************************************//**
  270. *
  271. * Uses _CLR_SET_FLD16U macro for providing get-clear-modify-write
  272. * operations with a name field and value and writes a resulting value
  273. * to the 16-bit register.
  274. *
  275. *******************************************************************************/
  276. #define CY_REG16_CLR_SET(reg, field, value) ((reg) = _CLR_SET_FLD16U((reg), field, (value)))
  277. /*******************************************************************************
  278. * Macro Name: _CLR_SET_FLD8U
  279. ****************************************************************************//**
  280. *
  281. * The macro for setting a 8-bit register with a name field and value for providing
  282. * get-clear-modify-write operations.
  283. * Returns a resulting value to be assigned to the 8-bit register.
  284. *
  285. *******************************************************************************/
  286. #define _CLR_SET_FLD8U(reg, field, value) ((uint8_t)(((reg) & ((uint8_t)(~(field ## _Msk)))) | \
  287. ((uint8_t)_VAL2FLD(field, value))))
  288. /*******************************************************************************
  289. * Macro Name: CY_REG8_CLR_SET
  290. ****************************************************************************//**
  291. *
  292. * Uses _CLR_SET_FLD8U macro for providing get-clear-modify-write
  293. * operations with a name field and value and writes a resulting value
  294. * to the 8-bit register.
  295. *
  296. *******************************************************************************/
  297. #define CY_REG8_CLR_SET(reg, field, value) ((reg) = _CLR_SET_FLD8U((reg), field, (value)))
  298. /*******************************************************************************
  299. * Macro Name: _BOOL2FLD
  300. ****************************************************************************//**
  301. *
  302. * Returns a field mask if the value is not false.
  303. * Returns 0, if the value is false.
  304. *
  305. *******************************************************************************/
  306. #define _BOOL2FLD(field, value) (((value) != false) ? (field ## _Msk) : 0UL)
  307. /*******************************************************************************
  308. * Macro Name: _FLD2BOOL
  309. ****************************************************************************//**
  310. *
  311. * Returns true, if the value includes the field mask.
  312. * Returns false, if the value doesn't include the field mask.
  313. *
  314. *******************************************************************************/
  315. #define _FLD2BOOL(field, value) (((value) & (field ## _Msk)) != 0UL)
  316. /*******************************************************************************
  317. * Macro Name: CY_SYSLIB_DIV_ROUND
  318. ****************************************************************************//**
  319. *
  320. * Calculates a / b with rounding to the nearest integer,
  321. * a and b must have the same sign.
  322. *
  323. *******************************************************************************/
  324. #define CY_SYSLIB_DIV_ROUND(a, b) (((a) + ((b) / 2U)) / (b))
  325. /*******************************************************************************
  326. * Macro Name: CY_SYSLIB_DIV_ROUNDUP
  327. ****************************************************************************//**
  328. *
  329. * Calculates a / b with rounding up if remainder != 0,
  330. * both a and b must be positive.
  331. *
  332. *******************************************************************************/
  333. #define CY_SYSLIB_DIV_ROUNDUP(a, b) ((((a) - 1U) / (b)) + 1U)
  334. #ifdef __cplusplus
  335. }
  336. #endif
  337. #endif /* CY_UTILS_H */
  338. /** \} group_utils */