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