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