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