1 /***************************************************************************//**
2 * \file cy_utils.h
3 *
4 * \brief
5 * Basic utility macros and functions.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2018-2020 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24
25 /**
26 * \addtogroup group_utils Utilities
27 * \ingroup group_abstraction
28 * \{
29 * Basic utility macros and functions.
30 */
31
32 #if !defined(CY_UTILS_H)
33 #define CY_UTILS_H
34
35 #if defined(__cplusplus)
36 extern "C" {
37 #endif
38
39 /** Simple macro to supress the unused parameter warning by casting to void. */
40 #define CY_UNUSED_PARAMETER(x) ( (void)(x) )
41
42 /** Halt the processor in the debug state
43 */
CY_HALT(void)44 static inline void CY_HALT(void)
45 {
46 __asm(" bkpt 1");
47 }
48
49 #ifdef CY_ASSERT
50 #undef CY_ASSERT
51 #endif /* ifdef(CY_ASSERT) */
52
53 /** Utility macro when neither NDEBUG or CY_NO_ASSERT is not declared to check a condition and, if false, trigger a breakpoint */
54 #if defined(NDEBUG) || defined(CY_NO_ASSERT)
55 #define CY_ASSERT(x) do { \
56 } while(false)
57 #else
58 #define CY_ASSERT(x) do { \
59 if(!(x)) \
60 { \
61 CY_HALT(); \
62 } \
63 } while(false)
64 #endif /* defined(NDEBUG) */
65
66
67 /*******************************************************************************
68 * Data manipulation defines
69 *******************************************************************************/
70
71 /** Get the lower 8 bits of a 16-bit value. */
72 #define CY_LO8(x) ((uint8_t) ((x) & 0xFFU))
73 /** Get the upper 8 bits of a 16-bit value. */
74 #define CY_HI8(x) ((uint8_t) ((uint16_t)(x) >> 8U))
75
76 /** Get the lower 16 bits of a 32-bit value. */
77 #define CY_LO16(x) ((uint16_t) ((x) & 0xFFFFU))
78 /** Get the upper 16 bits of a 32-bit value. */
79 #define CY_HI16(x) ((uint16_t) ((uint32_t)(x) >> 16U))
80
81 /** Swap the byte ordering of a 16-bit value */
82 #define CY_SWAP_ENDIAN16(x) ((uint16_t)(((x) << 8U) | (((x) >> 8U) & 0x00FFU)))
83
84 /** Swap the byte ordering of a 32-bit value */
85 #define CY_SWAP_ENDIAN32(x) ((uint32_t)((((x) >> 24U) & 0x000000FFU) | (((x) & 0x00FF0000U) >> 8U) | \
86 (((x) & 0x0000FF00U) << 8U) | ((x) << 24U)))
87
88 /** Swap the byte ordering of a 64-bit value */
89 #define CY_SWAP_ENDIAN64(x) ((uint64_t) (((uint64_t) CY_SWAP_ENDIAN32((uint32_t)(x)) << 32U) | \
90 CY_SWAP_ENDIAN32((uint32_t)((x) >> 32U))))
91
92
93 /*******************************************************************************
94 * Memory model definitions
95 *******************************************************************************/
96 #if defined(__ARMCC_VERSION)
97 /** To create cross compiler compatible code, use the CY_NOINIT, CY_SECTION, CY_UNUSED, CY_ALIGN
98 * attributes at the first place of declaration/definition.
99 * For example: CY_NOINIT uint32_t noinitVar;
100 */
101 #if (__ARMCC_VERSION >= 6010050)
102 #define CY_NOINIT __attribute__ ((section(".noinit")))
103 #else
104 #define CY_NOINIT __attribute__ ((section(".noinit"), zero_init))
105 #endif /* (__ARMCC_VERSION >= 6010050) */
106 #define CY_SECTION(name) __attribute__ ((section(name)))
107 #define CY_UNUSED __attribute__ ((unused))
108 #define CY_NOINLINE __attribute__ ((noinline))
109 /* Specifies the minimum alignment (in bytes) for variables of the specified type. */
110 #define CY_ALIGN(align) __ALIGNED(align)
111 #define CY_RAMFUNC_BEGIN __attribute__ ((section(".cy_ramfunc")))
112 #define CY_RAMFUNC_END
113 #elif defined (__GNUC__)
114 #if defined (__clang__)
115 #define CY_NOINIT __attribute__ ((section("__DATA, __noinit")))
116 #define CY_SECTION(name) __attribute__ ((section("__DATA, "name)))
117 #define CY_RAMFUNC_BEGIN __attribute__ ((section("__DATA, .cy_ramfunc")))
118 #define CY_RAMFUNC_END
119 #else
120 #define CY_NOINIT __attribute__ ((section(".noinit")))
121 #define CY_SECTION(name) __attribute__ ((section(name)))
122 #define CY_RAMFUNC_BEGIN __attribute__ ((section(".cy_ramfunc")))
123 #define CY_RAMFUNC_END
124 #endif
125
126 #define CY_UNUSED __attribute__ ((unused))
127 #define CY_NOINLINE __attribute__ ((noinline))
128 #define CY_ALIGN(align) __ALIGNED(align)
129 #elif defined (__ICCARM__)
130 #define CY_PRAGMA(x) _Pragma(#x)
131 #define CY_NOINIT __no_init
132 #define CY_SECTION(name) CY_PRAGMA(location = name)
133 #define CY_UNUSED
134 #define CY_NOINLINE CY_PRAGMA(optimize = no_inline)
135 #define CY_RAMFUNC_BEGIN CY_PRAGMA(diag_suppress = Ta023) __ramfunc
136 #define CY_RAMFUNC_END CY_PRAGMA(diag_default = Ta023)
137 #if (__VER__ < 8010001)
138 #define CY_ALIGN(align) CY_PRAGMA(data_alignment = align)
139 #else
140 #define CY_ALIGN(align) __ALIGNED(align)
141 #endif /* (__VER__ < 8010001) */
142 #else
143 #error "An unsupported toolchain"
144 #endif /* (__ARMCC_VERSION) */
145
146
147 /*******************************************************************************
148 * Macro Name: CY_GET_REG8(addr)
149 ****************************************************************************//**
150 *
151 * Reads the 8-bit value from the specified address. This function can't be
152 * used to access the Core register, otherwise a fault occurs.
153 *
154 * \param addr The register address.
155 *
156 * \return The read value.
157 *
158 *******************************************************************************/
159 #define CY_GET_REG8(addr) (*((const volatile uint8_t *)(addr)))
160
161
162 /*******************************************************************************
163 * Macro Name: CY_SET_REG8(addr, value)
164 ****************************************************************************//**
165 *
166 * Writes an 8-bit value to the specified address. This function can't be
167 * used to access the Core register, otherwise a fault occurs.
168 *
169 * \param addr The register address.
170 *
171 * \param value The value to write.
172 *
173 *******************************************************************************/
174 #define CY_SET_REG8(addr, value) (*((volatile uint8_t *)(addr)) = (uint8_t)(value))
175
176
177 /*******************************************************************************
178 * Macro Name: CY_GET_REG16(addr)
179 ****************************************************************************//**
180 *
181 * Reads the 16-bit value from the specified address.
182 *
183 * \param addr The register address.
184 *
185 * \return The read value.
186 *
187 *******************************************************************************/
188 #define CY_GET_REG16(addr) (*((const volatile uint16_t *)(addr)))
189
190
191 /*******************************************************************************
192 * Macro Name: CY_SET_REG16(addr, value)
193 ****************************************************************************//**
194 *
195 * Writes the 16-bit value to the specified address.
196 *
197 * \param addr The register address.
198 *
199 * \param value The value to write.
200 *
201 *******************************************************************************/
202 #define CY_SET_REG16(addr, value) (*((volatile uint16_t *)(addr)) = (uint16_t)(value))
203
204
205 /*******************************************************************************
206 * Macro Name: CY_GET_REG24(addr)
207 ****************************************************************************//**
208 *
209 * Reads the 24-bit value from the specified address.
210 *
211 * \param addr The register address.
212 *
213 * \return The read value.
214 *
215 *******************************************************************************/
216 #define CY_GET_REG24(addr) (((uint32_t) (*((const volatile uint8_t *)(addr)))) | \
217 (((uint32_t) (*((const volatile uint8_t *)(addr) + 1))) << 8U) | \
218 (((uint32_t) (*((const volatile uint8_t *)(addr) + 2))) << 16U))
219
220
221 /*******************************************************************************
222 * Macro Name: CY_SET_REG24(addr, value)
223 ****************************************************************************//**
224 *
225 * Writes the 24-bit value to the specified address.
226 *
227 * \param addr The register address.
228 *
229 * \param value The value to write.
230 *
231 *******************************************************************************/
232 #define CY_SET_REG24(addr, value) do \
233 { \
234 (*((volatile uint8_t *) (addr))) = (uint8_t)(value); \
235 (*((volatile uint8_t *) (addr) + 1)) = (uint8_t)((value) >> 8U); \
236 (*((volatile uint8_t *) (addr) + 2)) = (uint8_t)((value) >> 16U); \
237 } \
238 while(0)
239
240
241 /*******************************************************************************
242 * Macro Name: CY_GET_REG32(addr)
243 ****************************************************************************//**
244 *
245 * Reads the 32-bit value from the specified register. The address is the little
246 * endian order (LSB in lowest address).
247 *
248 * \param addr The register address.
249 *
250 * \return The read value.
251 *
252 *******************************************************************************/
253 #define CY_GET_REG32(addr) (*((const volatile uint32_t *)(addr)))
254
255
256 /*******************************************************************************
257 * Macro Name: CY_SET_REG32(addr, value)
258 ****************************************************************************//**
259 *
260 * Writes the 32-bit value to the specified register. The address is the little
261 * endian order (LSB in lowest address).
262 *
263 * \param addr The register address.
264 *
265 * \param value The value to write.
266 *
267 *******************************************************************************/
268 #define CY_SET_REG32(addr, value) (*((volatile uint32_t *)(addr)) = (uint32_t)(value))
269
270
271 /*******************************************************************************
272 * Macro Name: _CLR_SET_FLD32U
273 ****************************************************************************//**
274 *
275 * The macro for setting a register with a name field and value for providing
276 * get-clear-modify-write operations.
277 * Returns a resulting value to be assigned to the register.
278 *
279 *******************************************************************************/
280 #define _CLR_SET_FLD32U(reg, field, value) (((reg) & ((uint32_t)(~(field ## _Msk)))) | (_VAL2FLD(field, value)))
281
282
283 /*******************************************************************************
284 * Macro Name: CY_REG32_CLR_SET
285 ****************************************************************************//**
286 *
287 * Uses _CLR_SET_FLD32U macro for providing get-clear-modify-write
288 * operations with a name field and value and writes a resulting value
289 * to the 32-bit register.
290 *
291 *******************************************************************************/
292 #define CY_REG32_CLR_SET(reg, field, value) ((reg) = _CLR_SET_FLD32U((reg), field, (value)))
293
294
295 /*******************************************************************************
296 * Macro Name: _CLR_SET_FLD16U
297 ****************************************************************************//**
298 *
299 * The macro for setting a 16-bit register with a name field and value for providing
300 * get-clear-modify-write operations.
301 * Returns a resulting value to be assigned to the 16-bit register.
302 *
303 *******************************************************************************/
304 #define _CLR_SET_FLD16U(reg, field, value) ((uint16_t)(((reg) & ((uint16_t)(~(field ## _Msk)))) | \
305 ((uint16_t)_VAL2FLD(field, value))))
306
307
308 /*******************************************************************************
309 * Macro Name: CY_REG16_CLR_SET
310 ****************************************************************************//**
311 *
312 * Uses _CLR_SET_FLD16U macro for providing get-clear-modify-write
313 * operations with a name field and value and writes a resulting value
314 * to the 16-bit register.
315 *
316 *******************************************************************************/
317 #define CY_REG16_CLR_SET(reg, field, value) ((reg) = _CLR_SET_FLD16U((reg), field, (value)))
318
319
320 /*******************************************************************************
321 * Macro Name: _CLR_SET_FLD8U
322 ****************************************************************************//**
323 *
324 * The macro for setting a 8-bit register with a name field and value for providing
325 * get-clear-modify-write operations.
326 * Returns a resulting value to be assigned to the 8-bit register.
327 *
328 *******************************************************************************/
329 #define _CLR_SET_FLD8U(reg, field, value) ((uint8_t)(((reg) & ((uint8_t)(~(field ## _Msk)))) | \
330 ((uint8_t)_VAL2FLD(field, value))))
331
332
333 /*******************************************************************************
334 * Macro Name: CY_REG8_CLR_SET
335 ****************************************************************************//**
336 *
337 * Uses _CLR_SET_FLD8U macro for providing get-clear-modify-write
338 * operations with a name field and value and writes a resulting value
339 * to the 8-bit register.
340 *
341 *******************************************************************************/
342 #define CY_REG8_CLR_SET(reg, field, value) ((reg) = _CLR_SET_FLD8U((reg), field, (value)))
343
344
345 /*******************************************************************************
346 * Macro Name: _BOOL2FLD
347 ****************************************************************************//**
348 *
349 * Returns a field mask if the value is not false.
350 * Returns 0, if the value is false.
351 *
352 *******************************************************************************/
353 #define _BOOL2FLD(field, value) (((value) != false) ? (field ## _Msk) : 0UL)
354
355
356 /*******************************************************************************
357 * Macro Name: _FLD2BOOL
358 ****************************************************************************//**
359 *
360 * Returns true, if the value includes the field mask.
361 * Returns false, if the value doesn't include the field mask.
362 *
363 *******************************************************************************/
364 #define _FLD2BOOL(field, value) (((value) & (field ## _Msk)) != 0UL)
365
366
367 /*******************************************************************************
368 * Macro Name: CY_SYSLIB_DIV_ROUND
369 ****************************************************************************//**
370 *
371 * Calculates a / b with rounding to the nearest integer,
372 * a and b must have the same sign.
373 *
374 *******************************************************************************/
375 #define CY_SYSLIB_DIV_ROUND(a, b) (((a) + ((b) / 2U)) / (b))
376
377
378 /*******************************************************************************
379 * Macro Name: CY_SYSLIB_DIV_ROUNDUP
380 ****************************************************************************//**
381 *
382 * Calculates a / b with rounding up if remainder != 0,
383 * both a and b must be positive.
384 *
385 *******************************************************************************/
386 #define CY_SYSLIB_DIV_ROUNDUP(a, b) ((((a) - 1U) / (b)) + 1U)
387
388 /*******************************************************************************
389 * Provides the macros for MISRA violation documentation in Coverity tool.
390 *******************************************************************************/
391
392 /** \cond INTERNAL */
393
394 #ifdef CY_COVERITY_2012_CHECK /* Check MISRA-C:2012 with Coverity tool */
395 #define CY_COVERITY_PRAGMA_STR(a) #a
396
397 #define CY_MISRA_DEVIATE_LINE(MISRA,MESSAGE) \
398 _Pragma(CY_COVERITY_PRAGMA_STR(coverity compliance deviate MISRA MESSAGE))
399
400 #define CY_MISRA_FP_LINE(MISRA,MESSAGE) \
401 _Pragma(CY_COVERITY_PRAGMA_STR(coverity compliance fp MISRA MESSAGE))
402
403 #define CY_MISRA_DEVIATE_BLOCK_START(MISRA,COUNT,MESSAGE) \
404 _Pragma(CY_COVERITY_PRAGMA_STR(coverity compliance block (deviate:COUNT MISRA MESSAGE)))
405
406 #define CY_MISRA_FP_BLOCK_START(MISRA,COUNT,MESSAGE) \
407 _Pragma(CY_COVERITY_PRAGMA_STR(coverity compliance block (fp:COUNT MISRA MESSAGE)))
408
409 #define CY_MISRA_BLOCK_END(MISRA) \
410 _Pragma(CY_COVERITY_PRAGMA_STR(coverity compliance end_block MISRA))
411
412 #else /* General usage */
413
414 #define CY_MISRA_DEVIATE_LINE(MISRA,MESSAGE) do{}while(false)
415 #define CY_MISRA_FP_LINE(MISRA,MESSAGE) do{}while(false)
416 #define CY_MISRA_DEVIATE_BLOCK_START(MISRA,COUNT,MESSAGE)
417 #define CY_MISRA_FP_BLOCK_START(MISRA,COUNT,MESSAGE)
418 #define CY_MISRA_BLOCK_END(MISRA)
419
420 #endif /* CY_COVERITY_2012_CHECK */
421
422 /** \endcond */
423
424 #ifdef __cplusplus
425 }
426 #endif
427
428 #endif /* CY_UTILS_H */
429
430 /** \} group_utils */
431