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