Arm-2D  
2D Image Processing Library for Cortex-M Processors
 
Loading...
Searching...
No Matches
arm_2d_utils.h
1/*
2 * Copyright (C) 2010-2022 Arm Limited or its affiliates. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19/* ----------------------------------------------------------------------
20 * Project: Arm-2D Library
21 * Title: arm_2d_utils.h
22 * Description: Public header file for Arm-2D Library
23 *
24 * $Date: 20. Oct 2022
25 * $Revision: V.1.2.3
26 *
27 * -------------------------------------------------------------------- */
28
29#ifndef __ARM_2D_UTILS_H__
30#define __ARM_2D_UTILS_H__
31
32/*============================ INCLUDES ======================================*/
33
34#if defined(__clang__)
35# pragma clang diagnostic push
36# pragma clang diagnostic ignored "-Wunknown-warning-option"
37# pragma clang diagnostic ignored "-Wreserved-identifier"
38# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
39# pragma clang diagnostic ignored "-Wpadded"
40# pragma clang diagnostic ignored "-Wsign-conversion"
41# pragma clang diagnostic ignored "-Wimplicit-int-conversion"
42# pragma clang diagnostic ignored "-Wdollar-in-identifier-extension"
43# pragma clang diagnostic ignored "-Wundef"
44#elif defined(__IS_COMPILER_GCC__)
45# pragma GCC diagnostic push
46# pragma GCC diagnostic ignored "-Wpedantic"
47# pragma GCC diagnostic ignored "-Wstrict-aliasing"
48# pragma GCC diagnostic ignored "-Wnonnull-compare"
49#endif
50
51#ifdef __ARM_2D_HAS_USER_HEADER__
52# include __ARM_2D_HAS_USER_HEADER__
53#endif
54
55/*! \note arm-2d relies on CMSIS 5.8.0 and above.
56 */
57#include "cmsis_compiler.h"
58
59#ifdef __cplusplus
60extern "C" {
61#endif
62
63/*!
64 * \addtogroup gKernel 1 Kernel
65 * @{
66 */
67
68/*============================ MACROS ========================================*/
69
70
71/*----------------------------------------------------------------------------*
72 * Environment Detection *
73 *----------------------------------------------------------------------------*/
74
75/* The macros to identify compilers */
76
77/* detect IAR */
78#undef __IS_COMPILER_IAR__
79#if defined(__IAR_SYSTEMS_ICC__)
80# define __IS_COMPILER_IAR__ 1
81#endif
82
83/* detect arm compiler 5 */
84#undef __IS_COMPILER_ARM_COMPILER_5__
85#if ((__ARMCC_VERSION >= 5000000) && (__ARMCC_VERSION < 6000000))
86# define __IS_COMPILER_ARM_COMPILER_5__ 1
87#endif
88
89
90/* detect arm compiler 6 */
91#undef __IS_COMPILER_ARM_COMPILER_6__
92#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
93# define __IS_COMPILER_ARM_COMPILER_6__ 1
94#endif
95
96/* detect arm compilers */
97#undef __IS_COMPILER_ARM_COMPILER__
98#if defined(__IS_COMPILER_ARM_COMPILER_5__) && __IS_COMPILER_ARM_COMPILER_5__ \
99|| defined(__IS_COMPILER_ARM_COMPILER_6__) && __IS_COMPILER_ARM_COMPILER_6__
100# define __IS_COMPILER_ARM_COMPILER__ 1
101#endif
102
103/* detect clang (llvm) */
104#undef __IS_COMPILER_LLVM__
105#if defined(__clang__) && !__IS_COMPILER_ARM_COMPILER_6__
106# define __IS_COMPILER_LLVM__ 1
107#else
108
109/* detect gcc */
110# undef __IS_COMPILER_GCC__
111# if defined(__GNUC__) && !( defined(__IS_COMPILER_ARM_COMPILER__) \
112 || defined(__IS_COMPILER_LLVM__) \
113 || defined(__IS_COMPILER_IAR__))
114# define __IS_COMPILER_GCC__ 1
115# endif
116
117#endif
118
119
120
121/*----------------------------------------------------------------------------*
122 * OOC and Private Protection *
123 *----------------------------------------------------------------------------*/
124/* minimal support for OOPC */
125#undef __implement_ex
126#undef __implement
127#undef implement
128#undef implement_ex
129#undef inherit
130#undef inherit_ex
131
132/*!
133 * \note do NOT use this macro directly
134 */
135#ifdef __cplusplus
136# define __implement_ex(__type, __name) __type __name
137#else
138# define __implement_ex(__type, __name) \
139 union { \
140 __type __name; \
141 __type; \
142 }
143#endif
144/*!
145 * \note do NOT use this macro
146 */
147#define __inherit_ex(__type, __name) __type __name
148
149
150/*!
151 * \note do NOT use this macro directly
152 */
153#define __implement(__type) __implement_ex( __type, \
154 use_as__##__type)
155
156
157/*!
158 * \note do NOT use this macro directly
159 */
160#define __inherit(__type) __inherit_ex(__type,use_as__##__type)
161
162
163/*!
164 * \brief inherit a given class
165 * \param __type the base class, you can use .use_as_xxxxx for referencing
166 * the base.
167 * \note this macro supports microsoft extensions (-fms-extensions)
168 */
169#define implement(__type) __implement(__type)
170
171/*!
172 * \brief inherit a given class and give it an alias name
173 * \param __type the base class
174 * \param __name an alias name for referencing the base class
175 * \note this macro supports microsoft extensions (-fms-extensions)
176 */
177#define implement_ex(__type, __name) __implement_ex(__type, __name)
178
179
180/*!
181 * \brief inherit a given class
182 * \param __type the base class, you can use .use_as_xxxxx for referencing
183 * the base.
184 * \note this macro does NOT support microsoft extensions (-fms-extensions)
185 */
186#define inherit(__type) __inherit(__type)
187
188/*!
189 * \brief inherit a given class and give it an alias name
190 * \param __type the base class
191 * \param __name an alias name for referencing the base class
192 * \note this macro does NOT support microsoft extensions (-fms-extensions)
193 */
194#define inherit_ex(__type, __name) __inherit_ex(__type, __name)
195
196
197/*----------------------------------------------------------------------------*
198 * Misc *
199 *----------------------------------------------------------------------------*/
200
201/*!
202 * \brief a macro to mark unused variables and let the compiler happy
203 */
204#ifndef ARM_2D_UNUSED
205# define ARM_2D_UNUSED(__VAR) (void)(__VAR)
206#endif
207
208#undef ARM_TYPE_CONVERT
209/*!
210 * \brief convert a given variable to a specified type, the converted result
211 * can be used as lvalue.
212 * \param __VAR the target variable
213 * \param __TYPE the target type
214 */
215#define ARM_TYPE_CONVERT(__VAR, __TYPE) (*((__TYPE *)&(__VAR)))
216
217/*!
218 * \brief a macro to test the boolean result for a given value using a given
219 * bitmask
220 * \param[in] __VALUE the target value
221 * \param[in] __BITS a bitmask
222 * \retval true all bits in the bitmask is 1
223 * \retval false not all bits in the bitmask is 1
224 */
225#ifndef ARM_TEST_BITS
226# define ARM_TEST_BITS(__VALUE, __BITS) ((__BITS) == ((__VALUE) & (__BITS)))
227#endif
228
229/*!
230 * \brief get the number of items in an given array
231 */
232#ifndef dimof
233# define dimof(__array) (sizeof(__array)/sizeof(__array[0]))
234#endif
235
236/*!
237 * \brief get the offset of a given member in a specified structure/union
238 * \param __type the host type
239 * \param __member the name of the target member
240 * \return size_t the offset (in bytes)
241 */
242#ifndef offsetof
243# define offsetof(__type, __member) \
244 ((uintptr_t)&(((__type *)NULL)->__member))
245#endif
246
247/*!
248 * \note do NOT use this macro directly
249 */
250#define __ARM_TO_STRING(__STR) #__STR
251
252/*!
253 * \brief convert a string to C string
254 */
255#define ARM_TO_STRING(__STR) __ARM_TO_STRING(__STR)
256
257/*!
258 * \note do NOT use this macro directly
259 */
260#define __ARM_VA_NUM_ARGS_IMPL( _0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12, \
261 _13,_14,_15,_16,__N,...) __N
262
263/*!
264 * \brief A macro to count the number of parameters
265 *
266 * \note if GNU extension is not supported or enabled, the following express will
267 * be false: (__ARM_VA_NUM_ARGS() != 0)
268 * This might cause problems when in this library.
269 */
270#define __ARM_VA_NUM_ARGS(...) \
271 __ARM_VA_NUM_ARGS_IMPL( 0,##__VA_ARGS__,16,15,14,13,12,11,10,9, \
272 8,7,6,5,4,3,2,1,0)
273
274/*!
275 * \brief detect whether GNU extension is enabled in compilation or not
276 */
277#if __ARM_VA_NUM_ARGS() != 0
278# warning Please enable GNU extensions, it is required by the Arm-2D.
279#endif
280
281
282#undef ARM_2D_PARAM
283
284/*!
285 * \brief a macro helper to be used with ARM_2D_INVODE to improve the
286 * readability of the code
287 */
288#define ARM_2D_PARAM(...) __VA_ARGS__
289
290#ifndef ARM_2D_INVOKE
291/*!
292 * \brief A macro to safely invode a function pointer
293 *
294 * \param[in] __FUNC_PTR the target function pointer
295 * \param[in] ... an optional parameter list
296 */
297# define ARM_2D_INVOKE(__FUNC_PTR, ...) \
298 ((NULL == (__FUNC_PTR)) ? 0 : ((*(__FUNC_PTR))(__VA_ARGS__)))
299
300#endif
301
302#ifndef ARM_2D_INVOKE_RT_VOID
303/*!
304 * \brief A macro to safely call a function pointer that has no return value
305 *
306 * \param[in] __FUNC_PTR the target function pointer
307 * \param[in] ... an optional parameter list
308 */
309# define ARM_2D_INVOKE_RT_VOID(__FUNC_PTR, ...) \
310 if (NULL != (__FUNC_PTR)) (*(__FUNC_PTR))(__VA_ARGS__)
311
312#endif
313
314/*!
315 * \note do NOT use this macro directly
316 */
317#define __ARM_CONNECT2(__A, __B) __A##__B
318
319/*!
320 * \note do NOT use this macro directly
321 */
322#define __ARM_CONNECT2_ALT(__A, __B) __A##__B
323
324/*!
325 * \note do NOT use this macro directly
326 */
327#define __ARM_CONNECT3(__A, __B, __C) __A##__B##__C
328
329/*!
330 * \note do NOT use this macro directly
331 */
332#define __ARM_CONNECT4(__A, __B, __C, __D) __A##__B##__C##__D
333
334/*!
335 * \note do NOT use this macro directly
336 */
337#define __ARM_CONNECT5(__A, __B, __C, __D, __E) __A##__B##__C##__D##__E
338
339/*!
340 * \note do NOT use this macro directly
341 */
342#define __ARM_CONNECT6(__A, __B, __C, __D, __E, __F) \
343 __A##__B##__C##__D##__E##__F
344
345/*!
346 * \note do NOT use this macro directly
347 */
348#define __ARM_CONNECT7(__A, __B, __C, __D, __E, __F, __G) \
349 __A##__B##__C##__D##__E##__F##__G
350
351/*!
352 * \note do NOT use this macro directly
353 */
354#define __ARM_CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H) \
355 __A##__B##__C##__D##__E##__F##__G##__H
356
357/*!
358 * \note do NOT use this macro directly
359 */
360#define __ARM_CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I) \
361 __A##__B##__C##__D##__E##__F##__G##__H##__I
362
363/*!
364 * \brief connect two symbol names as one
365 */
366#define ARM_CONNECT2(__A, __B) __ARM_CONNECT2(__A, __B)
367
368/*!
369 * \brief connect two symbol names as one
370 */
371#define ARM_CONNECT2_ALT(__A, __B) __ARM_CONNECT2_ALT(__A, __B)
372
373/*!
374 * \brief connect three symbol names as one
375 */
376#define ARM_CONNECT3(__A, __B, __C) __ARM_CONNECT3(__A, __B, __C)
377
378/*!
379 * \brief connect four symbol names as one
380 */
381#define ARM_CONNECT4(__A, __B, __C, __D) __ARM_CONNECT4(__A, __B, __C, __D)
382
383/*!
384 * \brief connect five symbol names as one
385 */
386#define ARM_CONNECT5(__A, __B, __C, __D, __E) \
387 __ARM_CONNECT5(__A, __B, __C, __D, __E)
388
389/*!
390 * \brief connect six symbol names as one
391 */
392#define ARM_CONNECT6(__A, __B, __C, __D, __E, __F) \
393 __ARM_CONNECT6(__A, __B, __C, __D, __E, __F)
394
395/*!
396 * \brief connect seven symbol names as one
397 */
398#define ARM_CONNECT7(__A, __B, __C, __D, __E, __F, __G) \
399 __ARM_CONNECT7(__A, __B, __C, __D, __E, __F, __G)
400
401/*!
402 * \brief connect eight symbol names as one
403 */
404#define ARM_CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H) \
405 __ARM_CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H)
406
407/*!
408 * \brief connect nine symbol names as one
409 */
410#define ARM_CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I) \
411 __ARM_CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I)
412
413/*!
414 * \brief connect up to 9 symbol names as one
415 */
416#define arm_connect(...) \
417 ARM_CONNECT2_ALT(ARM_CONNECT, __ARM_VA_NUM_ARGS(__VA_ARGS__)) \
418 (__VA_ARGS__)
419
420/*!
421 * \brief connect up to 9 symbol names as one
422 */
423#define ARM_CONNECT(...) arm_connect(__VA_ARGS__)
424
425/*!
426 * \note do NOT use this macro directly
427 */
428#define __ARM_USING1(__declare) \
429 for (__declare, *ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr) = NULL; \
430 ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr)++ == NULL; \
431 )
432
433/*!
434 * \note do NOT use this macro directly
435 */
436#define __ARM_USING2(__declare, __on_leave_expr) \
437 for (__declare, *ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr) = NULL; \
438 ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr)++ == NULL; \
439 (__on_leave_expr) \
440 )
441
442/*!
443 * \note do NOT use this macro directly
444 */
445#define __ARM_USING3(__declare, __on_enter_expr, __on_leave_expr) \
446 for (__declare, *ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr) = NULL; \
447 ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr)++ == NULL ? \
448 ((__on_enter_expr),1) : 0; \
449 (__on_leave_expr) \
450 )
451
452/*!
453 * \note do NOT use this macro directly
454 */
455#define __ARM_USING4(__dcl1, __dcl2, __on_enter_expr, __on_leave_expr) \
456 for (__dcl1,__dcl2,*ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr)= NULL;\
457 ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr)++ == NULL ? \
458 ((__on_enter_expr),1) : 0; \
459 (__on_leave_expr) \
460 )
461
462/*!
463 * \brief create a code segment with up to two local variables and
464 * entering/leaving operations
465 * \note prototype 1
466 * arm_using(local variable declaration) {
467 * code body
468 * }
469 *
470 * \note prototype 2
471 * arm_using(local variable declaration, {code segment before leaving the body}) {
472 * code body
473 * }
474 *
475 * \note prototype 3
476 * arm_using( local variable declaration,
477 * {code segment before entering the body},
478 * {code segment before leaving the body}
479 * ) {
480 * code body
481 * }
482 *
483 * \note prototype 4
484 * arm_using( local variable1 declaration,
485 local variable2 with the same type as the local variable 1,
486 * {code segment before entering the body},
487 * {code segment before leaving the body}
488 * ) {
489 * code body
490 * }
491 */
492#define arm_using(...) \
493 ARM_CONNECT2(__ARM_USING, __ARM_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
494
495
496/*!
497 * \note do NOT use this macro directly
498 */
499#define __ARM_WITH2(__type, __addr) \
500 ARM_USING(__type *_p=(__addr))
501
502/*!
503 * \note do NOT use this macro directly
504 */
505#define __ARM_WITH3(__type, __addr, __item) \
506 ARM_USING(__type *_p=(__addr), *__item = _p, (void)_p, (void)0)
507
508/*!
509 * \brief a with block to access members of a given object
510 *
511 * \note prototype 1
512 * arm_with(object type, address of the object) {
513 * you can use _.xxxx to access the members of the object
514 * }
515 *
516 * \note prototype 2
517 * arm_with(object type, address of the object, name of the iterator) {
518 * you can use your own iterator to access the members of the object
519 * }
520 */
521#define arm_with(...) \
522 ARM_CONNECT2(__ARM_WITH, __ARM_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
523
524/*!
525 * \brief access each items in a given array
526 * \param __type the type of the array
527 * \param __array the target array
528 * \note you can use "_" as the current object (iterator)
529 */
530#define ARM_FOREACH2(__type, __array) \
531 arm_using(__type *_ = __array) \
532 for ( uint_fast32_t ARM_CONNECT2(count,__LINE__) = dimof(__array);\
533 ARM_CONNECT2(count,__LINE__) > 0; \
534 _++, ARM_CONNECT2(count,__LINE__)-- \
535 )
536
537/*!
538 * \brief access each items in a given array
539 * \param __type the type of the array
540 * \param __array the target array
541 * \param __item a name for the current item (iterator)
542 */
543#define ARM_FOREACH3(__type, __array, __item) \
544 arm_using(__type *_ = __array, *__item = _, (void)_, (void)0 ) \
545 for ( uint_fast32_t ARM_CONNECT2(count,__LINE__) = dimof(__array);\
546 ARM_CONNECT2(count,__LINE__) > 0; \
547 _++, __item = _, ARM_CONNECT2(count,__LINE__)-- \
548 )
549
550/*!
551 * \brief access each items in a given array
552 * \param __type the type of the array
553 * \param __array the target array or the pointer of an memory block
554 * \param __count number of items in the array/memory block
555 * \param __item a name for the current item (iterator)
556 */
557#define ARM_FOREACH4(__type, __array, __count, __item) \
558 arm_using(__type *_ = __array, *__item = _, (void)_, (void)0) \
559 for ( uint_fast32_t ARM_CONNECT2(count,__LINE__) = (__count); \
560 ARM_CONNECT2(count,__LINE__) > 0; \
561 _++, __item = _, ARM_CONNECT2(count,__LINE__)-- \
562 )
563
564/*!
565 * \brief access each items in a given array
566 * \note there are 3 prototypes, please refer to ARM_FOREACH1/2/3 for details
567 */
568#define arm_foreach(...) \
569 ARM_CONNECT2(ARM_FOREACH, __ARM_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
570
571
572/*!
573 * \brief a wrapper for __attribute__((nonnull))
574 */
575#ifndef ARM_NONNULL
576# if defined(__IS_COMPILER_ARM_COMPILER_5__) ||\
577 defined(__IS_COMPILER_ARM_COMPILER_6__) ||\
578 defined(__IS_COMPILER_GCC__) ||\
579 defined(__IS_COMPILER_LLVM__)
580# define ARM_NONNULL(...) __attribute__((nonnull(__VA_ARGS__)))
581# else
582# define ARM_NONNULL(...)
583# endif
584#endif
585
586/*!
587 * \brief an attribute for static variables that no initialisation is required
588 * in the C startup process.
589 */
590#ifndef ARM_NOINIT
591# if defined(__IS_COMPILER_ARM_COMPILER_5__)
592# define ARM_NOINIT __attribute__(( section( ".bss.noinit"),zero_init))
593# elif defined(__IS_COMPILER_ARM_COMPILER_6__)
594# define ARM_NOINIT __attribute__(( section( ".bss.noinit")))
595# elif defined(__IS_COMPILER_IAR__)
596# define ARM_NOINIT __no_init
597# elif defined(__IS_COMPILER_GCC__) || defined(__IS_COMPILER_LLVM__)
598# define ARM_NOINIT __attribute__(( section( ".bss.noinit")))
599# else
600# define ARM_NOINIT
601# endif
602#endif
603
604#undef __ARM_ALIGN
605
606/*!
607 * \note do NOT use this macro directly
608 */
609#define __ARM_ALIGN(__N) __attribute__((aligned(__N)))
610
611/*!
612 * \brief an attribute to specify aligment requirement
613 * \note it works for both functions and static/global variables
614 */
615#ifndef ARM_ALIGN
616# define ARM_ALIGN(__N) __ARM_ALIGN(__N)
617#endif
618
619/*!
620 * \brief local variable decoration for pointers: restrict
621 */
622#ifndef __RESTRICT
623# define __RESTRICT __restrict
624#endif
625
626/*!
627 * \brief an decoration for claiming that the immediate following symbol
628 * (variable / function) is not WEAK. If there is an __WEAK symbol, the
629 * __OVERRIDE_WEAK one can override it.
630 *
631 */
632#ifndef __OVERRIDE_WEAK
633# define __OVERRIDE_WEAK
634#endif
635
636/*!
637 * \brief A macro to generate a safe name, usually used in macro template as the
638 * name of local variables
639 *
640 */
641#define ARM_2D_SAFE_NAME(...) ARM_CONNECT(__,__LINE__,##__VA_ARGS__)
642
643/*!
644 * \brief A macro to generate a safe name, usually used in macro template as the
645 * name of local variables
646 *
647 */
648#define arm_2d_safe_name(...) ARM_2D_SAFE_NAME(__VA_ARGS__)
649
650#undef arm_irq_safe
651
652/*!
653 * \brief a decoration to make the immediate following code irq-safe
654 *
655 * \code
656 arm_irq_safe {
657 // code inside the brackets are IRQ safe
658 ...
659 }
660
661 // the printf is IRQ safe
662 arm_irq_safe printf("IRQ safe printf\n");
663
664 \endcode
665 */
666#define arm_irq_safe \
667 arm_using( uint32_t ARM_2D_SAFE_NAME(temp) = \
668 ({uint32_t temp=__get_PRIMASK();__disable_irq();temp;}),\
669 __set_PRIMASK(ARM_2D_SAFE_NAME(temp)))
670
671
672#undef ARM_2D_WRAP_FUNC
673#undef __ARM_2D_WRAP_FUNC
674#undef ARM_2D_ORIG_FUNC
675#undef __ARM_2D_ORIG_FUNC
676
677#if defined(__IS_COMPILER_ARM_COMPILER_6__)
678
679/*!
680 * \note do NOT use this macro directly
681 */
682# define __ARM_2D_WRAP_FUNC(__FUNC) $Sub$$##__FUNC
683
684/*!
685 * \note do NOT use this macro directly
686 */
687# define __ARM_2D_ORIG_FUNC(__FUNC) $Super$$## __FUNC
688#else
689
690/*!
691 * \note do NOT use this macro directly
692 */
693# define __ARM_2D_WRAP_FUNC(x) __wrap_ ## x
694
695/*!
696 * \note do NOT use this macro directly
697 */
698# define __ARM_2D_ORIG_FUNC(x) __real_ ## x
699#endif
700
701/*!
702 * \brief a symbol wrapper to override a specified function
703 */
704#define ARM_2D_WRAP_FUNC(__FUNC) __ARM_2D_WRAP_FUNC(__FUNC)
705
706/*!
707 * \brief a symbol wrapper to refer the original function with a given name
708 */
709#define ARM_2D_ORIG_FUNC(__FUNC) __ARM_2D_ORIG_FUNC(__FUNC)
710
711/*----------------------------------------------------------------------------*
712 * List Operations *
713 *----------------------------------------------------------------------------*/
714
715/* ALL the parameters passed to following macros must be pointer variables. */
716
717/*!
718 * \note do NOT use this macro directly
719 */
720#define __ARM_LIST_STACK_PUSH(__P_TOP, __P_NODE) \
721 do { \
722 ((__arm_slist_node_t *)(__P_NODE))->ptNext = \
723 (__arm_slist_node_t *)(__P_TOP); \
724 (*(__arm_slist_node_t **)&(__P_TOP)) = \
725 (__arm_slist_node_t *)(__P_NODE); \
726 } while(0)
727
728/*!
729 * \brief push a item to a list
730 * \param[in] __P_TOP a pointer points to the first item of a list
731 * \param[in] __P_NODE a pointer points to the new item
732 */
733#define ARM_LIST_STACK_PUSH(__P_TOP, __P_NODE) \
734 __ARM_LIST_STACK_PUSH((__P_TOP), (__P_NODE))
735
736/*!
737 * \brief insert a item after a specified node
738 * \param[in] __P_TARGET a pointer points to the target node
739 * \param[in] __P_NODE a pointer points to the new item
740 */
741#define ARM_LIST_INSERT_AFTER(__P_TARGET, __P_NODE) \
742 __ARM_LIST_STACK_PUSH((__P_TARGET), (__P_NODE))
743
744/*!
745 * \note do NOT use this macro directly
746 */
747#define __ARM_LIST_STACK_POP(__P_TOP, __P_NODE) \
748 do { \
749 (*(__arm_slist_node_t **)&(__P_NODE)) = \
750 (__arm_slist_node_t *)(__P_TOP); \
751 if (NULL != (__P_TOP)) { \
752 (*(__arm_slist_node_t **)&(__P_TOP)) = \
753 ((__arm_slist_node_t *)(__P_NODE))->ptNext; \
754 ((__arm_slist_node_t *)(__P_NODE))->ptNext = NULL; \
755 } \
756 } while(0)
757
758/*!
759 * \brief pop a item from a list
760 * \param[in] __P_TOP a pointer points to the first item of a list
761 * \param[out] __P_NODE a pointer variable for the node
762 */
763#define ARM_LIST_STACK_POP(__P_TOP, __P_NODE) \
764 __ARM_LIST_STACK_POP((__P_TOP), (__P_NODE))
765
766/*!
767 * \brief remove a item after a specified node
768 * \param[in] __P_TARGET a pointer points to the target node
769 * \param[out] __P_NODE a pointer variable for the node
770 */
771#define ARM_LIST_REMOVE_AFTER(__P_TARGET, __P_NODE) \
772 ARM_LIST_STACK_POP((__P_TARGET), (__P_NODE))
773
774/*!
775 * \note do NOT use this macro directly
776 */
777#define __ARM_LIST_QUEUE_ENQUEUE(__HEAD, __TAIL, __ITEM) \
778 do { \
779 if (NULL == (__TAIL)) { \
780 (*((__arm_slist_node_t **)&(__TAIL))) = \
781 (__arm_slist_node_t *)(__ITEM); \
782 (*((__arm_slist_node_t **)&(__HEAD))) = \
783 (__arm_slist_node_t *)(__ITEM); \
784 } else { \
785 ((__arm_slist_node_t *)(__TAIL))->ptNext = \
786 (__arm_slist_node_t *)(__ITEM); \
787 (*(__arm_slist_node_t **)&(__TAIL)) = \
788 (__arm_slist_node_t *)(__ITEM); \
789 } \
790 ((__arm_slist_node_t *)(__ITEM))->ptNext = NULL; \
791 } while(0)
792
793/*!
794 * \brief enter a node to a queue
795 * \param[in] __HEAD a pointer points to the queue head
796 * \param[in] __TAIL a pointer points to the queue tail
797 * \param[in] __ITEM a pointer variable for the new node
798 */
799#define ARM_LIST_QUEUE_ENQUEUE(__HEAD, __TAIL, __ITEM) \
800 __ARM_LIST_QUEUE_ENQUEUE((__HEAD), (__TAIL), (__ITEM))
801
802/*!
803 * \note do NOT use this macro directly
804 */
805#define __ARM_LIST_QUEUE_DEQUEUE(__HEAD, __TAIL, __ITEM) \
806 do { \
807 (*(__arm_slist_node_t **)&(__ITEM)) = (__arm_slist_node_t *)(__HEAD); \
808 if (NULL != (__HEAD)) { \
809 (*(__arm_slist_node_t **)&(__HEAD)) = \
810 ((__arm_slist_node_t *)(__HEAD))->ptNext; \
811 if (NULL == (__HEAD)) { \
812 (__TAIL) = NULL; \
813 } \
814 } \
815 } while(0)
816
817/*!
818 * \brief fetch a node from a queue
819 * \param[in] __HEAD a pointer points to the queue head
820 * \param[in] __TAIL a pointer points to the queue tail
821 * \param[out] __ITEM a pointer variable for the node
822 */
823#define ARM_LIST_QUEUE_DEQUEUE(__HEAD, __TAIL, __ITEM) \
824 __ARM_LIST_QUEUE_DEQUEUE((__HEAD), (__TAIL), (__ITEM))
825
826/*!
827 * \note do NOT use this macro directly
828 */
829#define __ARM_LIST_QUEUE_PEEK(__HEAD, __TAIL, __ITEM) \
830 do { \
831 (*(__arm_slist_node_t **)&(__ITEM)) = (__arm_slist_node_t *)(__HEAD); \
832 } while(0)
833
834/*!
835 * \brief peek a node from a queue
836 * \param[in] __HEAD a pointer points to the queue head
837 * \param[in] __TAIL a pointer points to the queue tail
838 * \param[out] __ITEM a pointer variable for the node
839 */
840#define ARM_LIST_QUEUE_PEEK(__HEAD, __TAIL, __ITEM) \
841 __ARM_LIST_QUEUE_PEEK((__HEAD), (__TAIL), (__ITEM)) \
842
843/*----------------------------------------------------------------------------*
844 * PT Operations *
845 *----------------------------------------------------------------------------*/
846/*
847Protothreads open source BSD-style license
848The protothreads library is released under an open source license that allows
849both commercial and non-commercial use without restrictions. The only
850requirement is that credits is given in the source code and in the documentation
851for your product.
852
853The full license text follows.
854
855Copyright (c) 2004-2005, Swedish Institute of Computer Science.
856All rights reserved.
857
858Redistribution and use in source and binary forms, with or without
859modification, are permitted provided that the following conditions
860are met:
8611. Redistributions of source code must retain the above copyright
862notice, this list of conditions and the following disclaimer.
8632. Redistributions in binary form must reproduce the above copyright
864notice, this list of conditions and the following disclaimer in the
865documentation and/or other materials provided with the distribution.
8663. Neither the name of the Institute nor the names of its contributors
867may be used to endorse or promote products derived from this software
868without specific prior written permission.
869
870THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS `AS IS' AND
871ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
872IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
873ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
874FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
875DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
876OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
877HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
878LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
879OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
880SUCH DAMAGE.
881
882Author: Adam Dunkels
883*/
884
885#define ARM_PT_BEGIN(__STATE) \
886 enum { \
887 count_offset = __COUNTER__ + 1, \
888 }; \
889 uint8_t *ptPTState = &(__STATE); \
890 switch (__STATE) { \
891 case __COUNTER__ - count_offset:
892
893#define ARM_PT_ENTRY(...) \
894 (*ptPTState) = (__COUNTER__ - count_offset + 1) >> 1; \
895 __VA_ARGS__ \
896 case (__COUNTER__ - count_offset) >> 1: (void)(*ptPTState);
897
898#define ARM_PT_YIELD(...) \
899 ARM_PT_ENTRY(return __VA_ARGS__;)
900
901#define ARM_PT_END() \
902 (*ptPTState) = 0; \
903 break;}
904
905#define ARM_PT_GOTO_PREV_ENTRY(...) return __VA_ARGS__;
906
907
908#define ARM_PT_REPORT_STATUS(...) \
909 ARM_PT_ENTRY( \
910 return __VA_ARGS__; \
911 )
912
913#define ARM_PT_RETURN(...) \
914 (*ptPTState) = 0; \
915 return __VA_ARGS__;
916
917/*----------------------------------------------------------------------------*
918 * Definition Template *
919 *----------------------------------------------------------------------------*/
920
921/*!
922 * \note do NOT use this macro directly
923 */
924#define __def_low_lv_io(__NAME, __SW, ...) \
925const __arm_2d_low_level_io_t LOW_LEVEL_IO##__NAME = { \
926 .SW = (__arm_2d_io_func_t *)&(__SW), \
927 .HW = (NULL, ##__VA_ARGS__) \
928}
929
930
931/*!
932 * \brief a template to implement a specified low-level io interface
933 * \param __NAME the IO name
934 * \param __SW the default c implementation
935 * \param ... you can specify an optional implementation using some acceleration.
936 */
937#define def_low_lv_io(__NAME, __SW, ...) \
938 __def_low_lv_io(__NAME, __SW, ##__VA_ARGS__)
939
940/*!
941 * \note do NOT use this macro directly
942 */
943#define __ref_low_lv_io(__NAME) &LOW_LEVEL_IO##__NAME
944
945/*!
946 * \brief a symbol wrapper for referencing a specified low-level IO
947 */
948#define ref_low_lv_io(__NAME) __ref_low_lv_io(__NAME)
949
950/*============================ TYPES =========================================*/
951
952/*!
953 * \brief a type for generic list
954 *
955 * \note to avoid using container_of() operand, please put __arm_slist_node_t
956 * at the beginning of a class/structure
957 */
960 __arm_slist_node_t *ptNext; //!< the next node
961};
962
963
964/*============================ GLOBAL VARIABLES ==============================*/
965/*============================ PROTOTYPES ====================================*/
966
967#if defined(__clang__)
968# pragma clang diagnostic pop
969#elif __IS_COMPILER_ARM_COMPILER_5__
970#elif __IS_COMPILER_GCC__
971# pragma GCC diagnostic pop
972#endif
973
974#ifdef __cplusplus
975}
976#endif
977
978#endif /* end of __ARM_2D_UTILS_H__ */
979
980
981/*! @} */
982
983/*============================ MACROS ========================================*/
984/*----------------------------------------------------------------------------*
985 * Reentrant Macros *
986 *----------------------------------------------------------------------------*/
987
988/* un-define macros */
989#undef ARM_PRIVATE
990#undef ARM_PROTECTED
991
992/* redefine macros */
993#if defined(__cplusplus)
994# define ARM_PRIVATE(...) \
995 struct { \
996 __VA_ARGS__ \
997 };
998
999# define ARM_PROTECTED(...) \
1000 struct { \
1001 __VA_ARGS__ \
1002 };
1003
1004#elif defined(__ARM_2D_IMPL__) || defined(__IS_COMPILER_IAR__)
1005
1006# define ARM_PRIVATE(...) \
1007 struct { \
1008 __VA_ARGS__ \
1009 } __ALIGNED(__alignof__(struct {__VA_ARGS__}));
1010
1011# define ARM_PROTECTED(...) \
1012 struct { \
1013 __VA_ARGS__ \
1014 } __ALIGNED(__alignof__(struct {__VA_ARGS__}));
1015
1016#elif defined(__ARM_2D_INHERIT__)
1017
1018# define ARM_PRIVATE(...) \
1019 uint8_t ARM_CONNECT3(chMask,__LINE__,__COUNTER__) \
1020 [sizeof(struct {__VA_ARGS__})] \
1021 __ALIGNED(__alignof__(struct {__VA_ARGS__}));
1022
1023# define ARM_PROTECTED(...) \
1024 struct { \
1025 __VA_ARGS__ \
1026 } __ALIGNED(__alignof__(struct {__VA_ARGS__}));
1027
1028#else
1029# define ARM_PRIVATE(...) \
1030 uint8_t ARM_CONNECT3(chMask,__LINE__,__COUNTER__) \
1031 [sizeof(struct {__VA_ARGS__})] \
1032 __ALIGNED(__alignof__(struct {__VA_ARGS__}));
1033
1034# define ARM_PROTECTED(...) \
1035 uint8_t ARM_CONNECT3(chMask,__LINE__,__COUNTER__) \
1036 [sizeof(struct {__VA_ARGS__})] \
1037 __ALIGNED(__alignof__(struct {__VA_ARGS__}));
1038#endif
1039
1040
1041
1042
1043/* post un-define macros */
1044
1045#undef __ARM_2D_IMPL__
1046#undef __ARM_2D_INHERIT__