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