1 /***********************************************************************************************//**
2 * \file cy_utils.h
3 *
4 * \brief
5 * Basic utility macros and functions.
6 *
7 ***************************************************************************************************
8 * \copyright
9 * Copyright 2018-2022 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 types, 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
44 /* MISRA directive 4.6 recommends using specific-length typedef for the basic
45 * numerical types of signed and unsigned variants of char, float, and double.
46 */
47 typedef char cy_char8_t; /**< Specific-length typedef for the basic numerical types of char */
48 typedef float cy_float32_t; /**< Specific-length typedef for the basic numerical types of float */
49 typedef double cy_float64_t; /**< Specific-length typedef for the basic numerical types of double */
50
51
52 /** Simple macro to suppress the unused parameter warning by casting to void. */
53 #define CY_UNUSED_PARAMETER(x) ( (void)(x) )
54
55 /** Halt the processor in the debug state
56 */
CY_HALT(void)57 static inline void CY_HALT(void)
58 {
59 __asm(" bkpt 1");
60 }
61
62
63 /** Default assert handler.
64 *
65 * To override, define CY_CUSTOM_ASSERT_HANDLER and define own CY_ASSERT_HANDLER API
66 */
67 #if defined(CY_CUSTOM_ASSERT_HANDLER)
68 void CY_ASSERT_HANDLER(void);
69 #else
70 #define CY_ASSERT_HANDLER() CY_HALT()
71 #endif
72
73 #ifdef CY_ASSERT
74 #undef CY_ASSERT
75 #endif // ifdef(CY_ASSERT)
76
77 /** Utility macro when neither NDEBUG or CY_NO_ASSERT is not declared to check a condition and, if
78 false, trigger a breakpoint */
79 #if defined(NDEBUG) || defined(CY_NO_ASSERT)
80 /** Assert an argument is true, else call assert handler */
81 #define CY_ASSERT(x) do { \
82 } while(false)
83 /** Assert an argument is true, else call assert handler and return a value */
84 #define CY_ASSERT_AND_RETURN(condition, value) \
85 do { \
86 (void)(condition); \
87 (void)(value); \
88 } while(false)
89 /** Assert an argument is true, else call assert handler and return */
90 #define CY_ASSERT_AND_RETURN_VOID(condition) \
91 do { \
92 (void)(condition); \
93 } while(false)
94 #else // if defined(NDEBUG) || defined(CY_NO_ASSERT)
95 /** Assert an argument is true, else call assert handler */
96 #define CY_ASSERT(x) do { \
97 if(!(x)) \
98 { \
99 CY_ASSERT_HANDLER();\
100 } \
101 } while (false)
102 /** Assert an argument is true, else call assert handler and return a value */
103 #define CY_ASSERT_AND_RETURN(condition, value) \
104 do { \
105 if(!(condition)) \
106 { \
107 CY_ASSERT_HANDLER();\
108 return (value); \
109 } \
110 } while (false)
111 /** Assert an argument is true, else call assert handler and return */
112 #define CY_ASSERT_AND_RETURN_VOID(condition) \
113 do { \
114 if(!(condition)) \
115 { \
116 CY_ASSERT_HANDLER();\
117 return; \
118 } \
119 } while (false)
120 #endif // defined(NDEBUG)
121
122
123 /*******************************************************************************
124 * Data manipulation defines
125 *******************************************************************************/
126
127 /** Get the lower 8 bits of a 16-bit value. */
128 #define CY_LO8(x) ((uint8_t) ((x) & 0xFFU))
129 /** Get the upper 8 bits of a 16-bit value. */
130 #define CY_HI8(x) ((uint8_t) ((uint16_t)(x) >> 8U))
131
132 /** Get the lower 16 bits of a 32-bit value. */
133 #define CY_LO16(x) ((uint16_t) ((x) & 0xFFFFU))
134 /** Get the upper 16 bits of a 32-bit value. */
135 #define CY_HI16(x) ((uint16_t) ((uint32_t)(x) >> 16U))
136
137 /** Swap the byte ordering of a 16-bit value */
138 #define CY_SWAP_ENDIAN16(x) ((uint16_t)(((x) << 8U) | (((x) >> 8U) & 0x00FFU)))
139
140 /** Swap the byte ordering of a 32-bit value */
141 #define CY_SWAP_ENDIAN32(x) \
142 ((uint32_t)((((x) >> 24U) & 0x000000FFU) | (((x) & 0x00FF0000U) >> 8U) | \
143 (((x) & 0x0000FF00U) << 8U) | ((x) << 24U)))
144
145 /** Swap the byte ordering of a 64-bit value */
146 #define CY_SWAP_ENDIAN64(x) ((uint64_t) (((uint64_t) CY_SWAP_ENDIAN32((uint32_t)(x)) << 32U) | \
147 CY_SWAP_ENDIAN32((uint32_t)((x) >> 32U))))
148
149
150 /*******************************************************************************
151 * Memory model definitions
152 *******************************************************************************/
153 #if defined(__ARMCC_VERSION)
154 /** To create cross compiler compatible code, use the CY_NOINIT, CY_SECTION, CY_UNUSED, CY_ALIGN
155 * attributes at the first place of declaration/definition.
156 * For example: CY_NOINIT uint32_t noinitVar;
157 */
158 #if (__ARMCC_VERSION >= 6160001)
159 #define CY_NOINIT __attribute__ ((section(".bss.noinit")))
160 #elif (__ARMCC_VERSION >= 6010050)
161 #define CY_NOINIT __attribute__ ((section(".noinit")))
162 #else
163 #define CY_NOINIT __attribute__ ((section(".noinit"), zero_init))
164 #endif // (__ARMCC_VERSION >= 6010050)
165 #define CY_SECTION(name) __attribute__ ((section(name)))
166 #define CY_UNUSED __attribute__ ((unused))
167 #define CY_NOINLINE __attribute__ ((noinline))
168 // Specifies the minimum alignment (in bytes) for variables of the specified type.
169 #define CY_ALIGN(align) __ALIGNED(align)
170 #define CY_RAMFUNC_BEGIN __attribute__ ((section(".cy_ramfunc")))
171 #define CY_RAMFUNC_END
172 #elif defined (__GNUC__)
173 #if defined (__clang__)
174 #define CY_NOINIT __attribute__ ((section("__DATA, __noinit")))
175 #define CY_SECTION(name) __attribute__ ((section("__DATA, "name)))
176 #define CY_RAMFUNC_BEGIN __attribute__ ((section("__DATA, .cy_ramfunc")))
177 #define CY_RAMFUNC_END
178 #else
179 #define CY_NOINIT __attribute__ ((section(".noinit")))
180 #define CY_SECTION(name) __attribute__ ((section(name)))
181 #define CY_RAMFUNC_BEGIN __attribute__ ((section(".cy_ramfunc")))
182 #define CY_RAMFUNC_END
183 #endif
184
185 #define CY_UNUSED __attribute__ ((unused))
186 #define CY_NOINLINE __attribute__ ((noinline))
187 #define CY_ALIGN(align) __ALIGNED(align)
188 #elif defined (__ICCARM__)
189 #define CY_PRAGMA(x) _Pragma(#x)
190 #define CY_NOINIT __no_init
191 #define CY_SECTION(name) CY_PRAGMA(location = name)
192 #define CY_UNUSED
193 #define CY_NOINLINE CY_PRAGMA(optimize = no_inline)
194 #define CY_RAMFUNC_BEGIN CY_PRAGMA(diag_suppress = Ta023) __ramfunc
195 #define CY_RAMFUNC_END CY_PRAGMA(diag_default = Ta023)
196 #if (__VER__ < 8010001)
197 #define CY_ALIGN(align) CY_PRAGMA(data_alignment = align)
198 #else
199 #define CY_ALIGN(align) __ALIGNED(align)
200 #endif // (__VER__ < 8010001)
201 #else // if defined(__ARMCC_VERSION)
202 #error "An unsupported toolchain"
203 #endif // (__ARMCC_VERSION)
204
205
206 /***************************************************************************************************
207 * Macro Name: CY_GET_REG8(addr)
208 ***********************************************************************************************//**
209 *
210 * Reads the 8-bit value from the specified address. This function can't be
211 * used to access the Core register, otherwise a fault occurs.
212 *
213 * \param addr The register address.
214 *
215 * \return The read value.
216 *
217 **************************************************************************************************/
218 #define CY_GET_REG8(addr) (*((const volatile uint8_t *)(addr)))
219
220
221 /***************************************************************************************************
222 * Macro Name: CY_SET_REG8(addr, value)
223 ***********************************************************************************************//**
224 *
225 * Writes an 8-bit value to the specified address. This function can't be
226 * used to access the Core register, otherwise a fault occurs.
227 *
228 * \param addr The register address.
229 *
230 * \param value The value to write.
231 *
232 **************************************************************************************************/
233 #define CY_SET_REG8(addr, value) (*((volatile uint8_t *)(addr)) = (uint8_t)(value))
234
235
236 /***************************************************************************************************
237 * Macro Name: CY_GET_REG16(addr)
238 ***********************************************************************************************//**
239 *
240 * Reads the 16-bit value from the specified address.
241 *
242 * \param addr The register address.
243 *
244 * \return The read value.
245 *
246 **************************************************************************************************/
247 #define CY_GET_REG16(addr) (*((const volatile uint16_t *)(addr)))
248
249
250 /***************************************************************************************************
251 * Macro Name: CY_SET_REG16(addr, value)
252 ***********************************************************************************************//**
253 *
254 * Writes the 16-bit value to the specified address.
255 *
256 * \param addr The register address.
257 *
258 * \param value The value to write.
259 *
260 **************************************************************************************************/
261 #define CY_SET_REG16(addr, value) (*((volatile uint16_t *)(addr)) = (uint16_t)(value))
262
263
264 /***************************************************************************************************
265 * Macro Name: CY_GET_REG24(addr)
266 ***********************************************************************************************//**
267 *
268 * Reads the 24-bit value from the specified address.
269 *
270 * \param addr The register address.
271 *
272 * \return The read value.
273 *
274 **************************************************************************************************/
275 #define CY_GET_REG24(addr) (((uint32_t) (*((const volatile uint8_t *)(addr)))) | \
276 (((uint32_t) (*((const volatile uint8_t *)(addr) + 1))) << 8U) | \
277 (((uint32_t) (*((const volatile uint8_t *)(addr) + 2))) << 16U))
278
279
280 /***************************************************************************************************
281 * Macro Name: CY_SET_REG24(addr, value)
282 ***********************************************************************************************//**
283 *
284 * Writes the 24-bit value to the specified address.
285 *
286 * \param addr The register address.
287 *
288 * \param value The value to write.
289 *
290 **************************************************************************************************/
291 #define CY_SET_REG24(addr, value) \
292 do \
293 { \
294 (*((volatile uint8_t *) (addr))) = (uint8_t)(value); \
295 (*((volatile uint8_t *) (addr) + 1)) = (uint8_t)((value) >> 8U); \
296 (*((volatile uint8_t *) (addr) + 2)) = (uint8_t)((value) >> 16U); \
297 } \
298 while(0)
299
300
301 /***************************************************************************************************
302 * Macro Name: CY_GET_REG32(addr)
303 ***********************************************************************************************//**
304 *
305 * Reads the 32-bit value from the specified register. The address is the little
306 * endian order (LSB in lowest address).
307 *
308 * \param addr The register address.
309 *
310 * \return The read value.
311 *
312 **************************************************************************************************/
313 #define CY_GET_REG32(addr) (*((const volatile uint32_t *)(addr)))
314
315
316 /***************************************************************************************************
317 * Macro Name: CY_SET_REG32(addr, value)
318 ***********************************************************************************************//**
319 *
320 * Writes the 32-bit value to the specified register. The address is the little
321 * endian order (LSB in lowest address).
322 *
323 * \param addr The register address.
324 *
325 * \param value The value to write.
326 *
327 **************************************************************************************************/
328 #define CY_SET_REG32(addr, value) (*((volatile uint32_t *)(addr)) = (uint32_t)(value))
329
330
331 /***************************************************************************************************
332 * Macro Name: _CLR_SET_FLD32U
333 ***********************************************************************************************//**
334 *
335 * The macro for setting a register with a name field and value for providing
336 * get-clear-modify-write operations.
337 * Returns a resulting value to be assigned to the register.
338 *
339 **************************************************************************************************/
340 #define _CLR_SET_FLD32U(reg, field, value) \
341 (((reg) & ((uint32_t)(~(field ## _Msk)))) | (_VAL2FLD(field, value)))
342
343
344 /***************************************************************************************************
345 * Macro Name: CY_REG32_CLR_SET
346 ***********************************************************************************************//**
347 *
348 * Uses _CLR_SET_FLD32U macro for providing get-clear-modify-write
349 * operations with a name field and value and writes a resulting value
350 * to the 32-bit register.
351 *
352 **************************************************************************************************/
353 #define CY_REG32_CLR_SET(reg, field, value) ((reg) = _CLR_SET_FLD32U((reg), field, (value)))
354
355
356 /***************************************************************************************************
357 * Macro Name: _CLR_SET_FLD16U
358 ***********************************************************************************************//**
359 *
360 * The macro for setting a 16-bit register with a name field and value for providing
361 * get-clear-modify-write operations.
362 * Returns a resulting value to be assigned to the 16-bit register.
363 *
364 **************************************************************************************************/
365 #define _CLR_SET_FLD16U(reg, field, value) \
366 ((uint16_t)(((reg) & ((uint16_t)(~(field ## _Msk)))) | ((uint16_t)_VAL2FLD(field, value))))
367
368
369 /***************************************************************************************************
370 * Macro Name: CY_REG16_CLR_SET
371 ***********************************************************************************************//**
372 *
373 * Uses _CLR_SET_FLD16U macro for providing get-clear-modify-write
374 * operations with a name field and value and writes a resulting value
375 * to the 16-bit register.
376 *
377 **************************************************************************************************/
378 #define CY_REG16_CLR_SET(reg, field, value) ((reg) = _CLR_SET_FLD16U((reg), field, (value)))
379
380
381 /***************************************************************************************************
382 * Macro Name: _CLR_SET_FLD8U
383 ***********************************************************************************************//**
384 *
385 * The macro for setting a 8-bit register with a name field and value for providing
386 * get-clear-modify-write operations.
387 * Returns a resulting value to be assigned to the 8-bit register.
388 *
389 **************************************************************************************************/
390 #define _CLR_SET_FLD8U(reg, field, value) \
391 ((uint8_t)(((reg) & ((uint8_t)(~(field ## _Msk)))) | ((uint8_t)_VAL2FLD(field, value))))
392
393
394 /***************************************************************************************************
395 * Macro Name: CY_REG8_CLR_SET
396 ***********************************************************************************************//**
397 *
398 * Uses _CLR_SET_FLD8U macro for providing get-clear-modify-write
399 * operations with a name field and value and writes a resulting value
400 * to the 8-bit register.
401 *
402 **************************************************************************************************/
403 #define CY_REG8_CLR_SET(reg, field, value) ((reg) = _CLR_SET_FLD8U((reg), field, (value)))
404
405
406 /***************************************************************************************************
407 * Macro Name: _BOOL2FLD
408 ***********************************************************************************************//**
409 *
410 * Returns a field mask if the value is not false.
411 * Returns 0, if the value is false.
412 *
413 **************************************************************************************************/
414 #define _BOOL2FLD(field, value) (((value) != false) ? (field ## _Msk) : 0UL)
415
416
417 /***************************************************************************************************
418 * Macro Name: _FLD2BOOL
419 ***********************************************************************************************//**
420 *
421 * Returns true, if the value includes the field mask.
422 * Returns false, if the value doesn't include the field mask.
423 *
424 **************************************************************************************************/
425 #define _FLD2BOOL(field, value) (((value) & (field ## _Msk)) != 0UL)
426
427
428 /***************************************************************************************************
429 * Macro Name: CY_SYSLIB_DIV_ROUND
430 ***********************************************************************************************//**
431 *
432 * Calculates a / b with rounding to the nearest integer,
433 * a and b must have the same sign.
434 *
435 **************************************************************************************************/
436 #define CY_SYSLIB_DIV_ROUND(a, b) (((a) + ((b) / 2U)) / (b))
437
438
439 /***************************************************************************************************
440 * Macro Name: CY_SYSLIB_DIV_ROUNDUP
441 ***********************************************************************************************//**
442 *
443 * Calculates a / b with rounding up if remainder != 0,
444 * both a and b must be positive.
445 *
446 **************************************************************************************************/
447 #define CY_SYSLIB_DIV_ROUNDUP(a, b) ((((a) - 1U) / (b)) + 1U)
448
449 /*******************************************************************************
450 * Provides the macros for MISRA violation documentation in Coverity tool.
451 *******************************************************************************/
452
453 /** \cond INTERNAL */
454
455 #ifdef CY_COVERITY_2012_CHECK // Check MISRA-C:2012 with Coverity tool
456 #define CY_COVERITY_PRAGMA_STR(a) #a
457
458 #define CY_MISRA_DEVIATE_LINE(MISRA, MESSAGE) \
459 _Pragma(CY_COVERITY_PRAGMA_STR(coverity compliance deviate MISRA MESSAGE))
460
461 #define CY_MISRA_FP_LINE(MISRA, MESSAGE) \
462 _Pragma(CY_COVERITY_PRAGMA_STR(coverity compliance fp MISRA MESSAGE))
463
464 #define CY_MISRA_DEVIATE_BLOCK_START(MISRA, COUNT, MESSAGE) \
465 _Pragma(CY_COVERITY_PRAGMA_STR(coverity compliance block (deviate:COUNT MISRA MESSAGE)))
466
467 #define CY_MISRA_FP_BLOCK_START(MISRA, COUNT, MESSAGE) \
468 _Pragma(CY_COVERITY_PRAGMA_STR(coverity compliance block (fp:COUNT MISRA MESSAGE)))
469
470 #define CY_MISRA_BLOCK_END(MISRA) \
471 _Pragma(CY_COVERITY_PRAGMA_STR(coverity compliance end_block MISRA))
472
473 #else // General usage
474
475 #define CY_MISRA_DEVIATE_LINE(MISRA, MESSAGE) do{}while(false)
476 #define CY_MISRA_FP_LINE(MISRA, MESSAGE) do{}while(false)
477 #define CY_MISRA_DEVIATE_BLOCK_START(MISRA, COUNT, MESSAGE)
478 #define CY_MISRA_FP_BLOCK_START(MISRA, COUNT, MESSAGE)
479 #define CY_MISRA_BLOCK_END(MISRA)
480
481 #endif // CY_COVERITY_2012_CHECK
482
483 /** \endcond */
484
485 #ifdef __cplusplus
486 }
487 #endif
488
489 /** \} group_utils */
490