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