Arm-2D  
2D Image Processing Library for Cortex-M Processors
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: 12. April 2022
25 * $Revision: V.1.0.1
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#endif
49
50#ifdef __ARM_2D_HAS_USER_HEADER__
51# include __ARM_2D_HAS_USER_HEADER__
52#endif
53
54/*! \note arm-2d relies on CMSIS 5.4.0 and above.
55 */
56#include "cmsis_compiler.h"
57
58#ifdef __cplusplus
59extern "C" {
60#endif
61
62
63
64/*============================ MACROS ========================================*/
65
66
67/*----------------------------------------------------------------------------*
68 * Environment Detection *
69 *----------------------------------------------------------------------------*/
70
71//! \name The macros to identify the compiler
72//! @{
73
74//! \note for IAR
75#ifdef __IS_COMPILER_IAR__
76# undef __IS_COMPILER_IAR__
77#endif
78#if defined(__IAR_SYSTEMS_ICC__)
79# define __IS_COMPILER_IAR__ 1
80#endif
81
82//! \note for arm compiler 5
83#ifdef __IS_COMPILER_ARM_COMPILER_5__
84# undef __IS_COMPILER_ARM_COMPILER_5__
85#endif
86#if ((__ARMCC_VERSION >= 5000000) && (__ARMCC_VERSION < 6000000))
87# define __IS_COMPILER_ARM_COMPILER_5__ 1
88#endif
89//! @}
90
91//! \note for arm compiler 6
92#ifdef __IS_COMPILER_ARM_COMPILER_6__
93# undef __IS_COMPILER_ARM_COMPILER_6__
94#endif
95#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
96# define __IS_COMPILER_ARM_COMPILER_6__ 1
97#endif
98
99#ifdef __IS_COMPILER_LLVM__
100# undef __IS_COMPILER_LLVM__
101#endif
102#if defined(__clang__) && !__IS_COMPILER_ARM_COMPILER_6__
103# define __IS_COMPILER_LLVM__ 1
104#else
105//! \note for gcc
106# ifdef __IS_COMPILER_GCC__
107# undef __IS_COMPILER_GCC__
108# endif
109# if defined(__GNUC__) && !( defined(__IS_COMPILER_ARM_COMPILER_5__) \
110 || defined(__IS_COMPILER_ARM_COMPILER_6__) \
111 || defined(__IS_COMPILER_LLVM__))
112# define __IS_COMPILER_GCC__ 1
113# endif
114//! @}
115#endif
116//! @}
117
118
119/*----------------------------------------------------------------------------*
120 * OOC and Private Protection *
121 *----------------------------------------------------------------------------*/
122/*! \brief minimal support for OOPC
123 */
124#undef __implement_ex
125#undef __implement
126#undef implement
127#undef implement_ex
128#undef inherit
129#undef inherit_ex
130
131#define __implement_ex(__type, __name) \
132 union { \
133 __type __name; \
134 __type; \
135 }
136
137#define __inherit_ex(__type, __name) \
138 __type __name \
139
140#define __implement(__type) __implement_ex( __type, \
141 use_as__##__type)
142
143#define __inherit(__type) __inherit_ex(__type,use_as__##__type)
144
145#define implement(__type) __implement(__type)
146#define implement_ex(__type, __name) __implement_ex(__type, __name)
147
148#define inherit(__type) __inherit(__type)
149#define inherit_ex(__type, __name) __inherit_ex(__type, __name)
150
151
152/*----------------------------------------------------------------------------*
153 * Misc *
154 *----------------------------------------------------------------------------*/
155
156#ifndef ARM_2D_UNUSED
157# define ARM_2D_UNUSED(__VAR) (void)(__VAR)
158#endif
159
160#ifndef ARM_TEST_BITS
161# define ARM_TEST_BITS(__VALUE, __BITS) ((__BITS) == ((__VALUE) & (__BITS)))
162#endif
163
164#ifndef dimof
165# define dimof(__array) (sizeof(__array)/sizeof(__array[0]))
166#endif
167
168#ifndef offsetof
169# define offsetof(__type, __member) \
170 ((uintptr_t)&(((__type *)NULL)->__member))
171#endif
172
173#define __ARM_TO_STRING(__STR) #__STR
174#define ARM_TO_STRING(__STR) __ARM_TO_STRING(__STR)
175
176#define __ARM_VA_NUM_ARGS_IMPL( _0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12, \
177 _13,_14,_15,_16,__N,...) __N
178#define __ARM_VA_NUM_ARGS(...) \
179 __ARM_VA_NUM_ARGS_IMPL( 0,##__VA_ARGS__,16,15,14,13,12,11,10,9, \
180 8,7,6,5,4,3,2,1,0)
181
182/*! \brief detect whether GNU extension is enabled in compilation or not
183 */
184#if __ARM_VA_NUM_ARGS() != 0
185# warning Please enable GNC extensions, it is required by the Arm-2D.
186#endif
187
188#ifndef ARM_2D_INVOKE
189# define ARM_2D_INVOKE(__FUNC_PTR, ...) \
190 do { \
191 if (NULL != (__FUNC_PTR)) { \
192 (*(__FUNC_PTR))(__VA_ARGS__); \
193 } \
194 } while(0)
195#endif
196
197#define __ARM_CONNECT2(__A, __B) __A##__B
198#define __ARM_CONNECT2_ALT(__A, __B) __A##__B
199#define __ARM_CONNECT3(__A, __B, __C) __A##__B##__C
200#define __ARM_CONNECT4(__A, __B, __C, __D) __A##__B##__C##__D
201#define __ARM_CONNECT5(__A, __B, __C, __D, __E) __A##__B##__C##__D##__E
202#define __ARM_CONNECT6(__A, __B, __C, __D, __E, __F) \
203 __A##__B##__C##__D##__E##__F
204#define __ARM_CONNECT7(__A, __B, __C, __D, __E, __F, __G) \
205 __A##__B##__C##__D##__E##__F##__G
206#define __ARM_CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H) \
207 __A##__B##__C##__D##__E##__F##__G##__H
208#define __ARM_CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I) \
209 __A##__B##__C##__D##__E##__F##__G##__H##__I
210
211#define ARM_CONNECT2(__A, __B) __ARM_CONNECT2(__A, __B)
212#define ARM_CONNECT2_ALT(__A, __B) __ARM_CONNECT2_ALT(__A, __B)
213#define ARM_CONNECT3(__A, __B, __C) __ARM_CONNECT3(__A, __B, __C)
214#define ARM_CONNECT4(__A, __B, __C, __D) __ARM_CONNECT4(__A, __B, __C, __D)
215#define ARM_CONNECT5(__A, __B, __C, __D, __E) \
216 __ARM_CONNECT5(__A, __B, __C, __D, __E)
217#define ARM_CONNECT6(__A, __B, __C, __D, __E, __F) \
218 __ARM_CONNECT6(__A, __B, __C, __D, __E, __F)
219#define ARM_CONNECT7(__A, __B, __C, __D, __E, __F, __G) \
220 __ARM_CONNECT7(__A, __B, __C, __D, __E, __F, __G)
221#define ARM_CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H) \
222 __ARM_CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H)
223#define ARM_CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I) \
224 __ARM_CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I)
225
226#define arm_connect(...) \
227 ARM_CONNECT2_ALT(ARM_CONNECT, __ARM_VA_NUM_ARGS(__VA_ARGS__)) \
228 (__VA_ARGS__)
229
230#define ARM_CONNECT(...) arm_connect(__VA_ARGS__)
231
232#define __ARM_USING1(__declare) \
233 for (__declare, *ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr) = NULL; \
234 ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr)++ == NULL; \
235 )
236
237#define __ARM_USING2(__declare, __on_leave_expr) \
238 for (__declare, *ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr) = NULL; \
239 ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr)++ == NULL; \
240 __on_leave_expr \
241 )
242
243#define __ARM_USING3(__declare, __on_enter_expr, __on_leave_expr) \
244 for (__declare, *ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr) = NULL; \
245 ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr)++ == NULL ? \
246 ((__on_enter_expr),1) : 0; \
247 __on_leave_expr \
248 )
249
250#define __ARM_USING4(__dcl1, __dcl2, __on_enter_expr, __on_leave_expr) \
251 for (__dcl1,__dcl2,*ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr)= NULL;\
252 ARM_CONNECT3(__ARM_USING_, __LINE__,_ptr)++ == NULL ? \
253 ((__on_enter_expr),1) : 0; \
254 __on_leave_expr \
255 )
256
257#define arm_using(...) \
258 ARM_CONNECT2(__ARM_USING, __ARM_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
259
260
261#define __ARM_WITH2(__type, __addr) \
262 ARM_USING(__type *_p=(__addr))
263#define __ARM_WITH3(__type, __addr, __item) \
264 ARM_USING(__type *_p=(__addr), *__item = _p, _p=_p, )
265
266#define arm_with(...) \
267 ARM_CONNECT2(__ARM_WITH, __ARM_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
268
269#define ARM_FOREACH2(__type, __array) \
270 arm_using(__type *_ = __array) \
271 for ( uint_fast32_t ARM_CONNECT2(count,__LINE__) = dimof(__array);\
272 ARM_CONNECT2(count,__LINE__) > 0; \
273 _++, ARM_CONNECT2(count,__LINE__)-- \
274 )
275
276#define ARM_FOREACH3(__type, __array, __item) \
277 arm_using(__type *_ = __array, *__item = _, _ = _, ) \
278 for ( uint_fast32_t ARM_CONNECT2(count,__LINE__) = dimof(__array);\
279 ARM_CONNECT2(count,__LINE__) > 0; \
280 _++, __item = _, ARM_CONNECT2(count,__LINE__)-- \
281 )
282
283#define ARM_FOREACH4(__type, __array, __count, __item) \
284 arm_using(__type *_ = __array, *__item = _, _ = _, ) \
285 for ( uint_fast32_t ARM_CONNECT2(count,__LINE__) = (__count); \
286 ARM_CONNECT2(count,__LINE__) > 0; \
287 _++, __item = _, ARM_CONNECT2(count,__LINE__)-- \
288 )
289
290#define arm_foreach(...) \
291 ARM_CONNECT2(ARM_FOREACH, __ARM_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
292
293
294#ifndef ARM_NONNULL
295# if defined(__IS_COMPILER_ARM_COMPILER_5__) ||\
296 defined(__IS_COMPILER_ARM_COMPILER_6__) ||\
297 defined(__IS_COMPILER_GCC__) ||\
298 defined(__IS_COMPILER_LLVM__)
299# define ARM_NONNULL(...) __attribute__((nonnull(__VA_ARGS__)))
300# else
301# define ARM_NONNULL(...)
302# endif
303#endif
304
305#ifndef ARM_NOINIT
306# if defined(__IS_COMPILER_ARM_COMPILER_5__)
307# define ARM_NOINIT __attribute__(( section( ".bss.noinit"),zero_init))
308# elif defined(__IS_COMPILER_ARM_COMPILER_6__)
309# define ARM_NOINIT __attribute__(( section( ".bss.noinit")))
310# elif defined(__IS_COMPILER_IAR__)
311# define ARM_NOINIT __no_init
312# elif defined(__IS_COMPILER_GCC__) || defined(__IS_COMPILER_LLVM__)
313# define ARM_NOINIT __attribute__(( section( ".bss.noinit")))
314# else
315# define ARM_NOINIT
316# endif
317#endif
318
319
320#ifndef ARM_ALIGN
321# define __ARM_ALIGN(__N) __attribute__((aligned(__N)))
322# define ARM_ALIGN(__N) __ARM_ALIGN(__N)
323#endif
324
325
326#ifndef __RESTRICT
327# define __RESTRICT __restrict
328#endif
329
330#ifndef __OVERRIDE_WEAK
331# define __OVERRIDE_WEAK
332#endif
333
334#define ARM_2D_SAFE_NAME(...) ARM_CONNECT(__,__LINE__,##__VA_ARGS__)
335#define arm_2d_safe_name(...) ARM_2D_SAFE_NAME(__VA_ARGS__)
336
337#undef arm_irq_safe
338
339#define arm_irq_safe \
340 arm_using( uint32_t ARM_2D_SAFE_NAME(temp) = \
341 ({uint32_t temp=__get_PRIMASK();__disable_irq();temp;}),\
342 __set_PRIMASK(ARM_2D_SAFE_NAME(temp)))
343
344
345#undef ARM_2D_WRAP_FUNC
346#undef __ARM_2D_WRAP_FUNC
347#undef ARM_2D_ORIG_FUNC
348#undef __ARM_2D_ORIG_FUNC
349
350#if defined(__IS_COMPILER_ARM_COMPILER_6__)
351# define __ARM_2D_WRAP_FUNC(__FUNC) $Sub$$##__FUNC
352# define __ARM_2D_ORIG_FUNC(__FUNC) $Super$$## __FUNC
353#else
354# define __ARM_2D_WRAP_FUNC(x) __wrap_ ## x
355# define __ARM_2D_ORIG_FUNC(x) __real_ ## x
356#endif
357
358#define ARM_2D_WRAP_FUNC(__FUNC) __ARM_2D_WRAP_FUNC(__FUNC)
359#define ARM_2D_ORIG_FUNC(__FUNC) __ARM_2D_ORIG_FUNC(__FUNC)
360
361/*----------------------------------------------------------------------------*
362 * List Operations *
363 *----------------------------------------------------------------------------*/
364
365/*! \note ALL the parameters passed to following macros must be pointer
366 *! variables.
367 */
368
369#define __ARM_LIST_STACK_PUSH(__P_TOP, __P_NODE) \
370 do { \
371 ((__arm_slist_node_t *)(__P_NODE))->ptNext = \
372 (__arm_slist_node_t *)(__P_TOP); \
373 (*(__arm_slist_node_t **)&(__P_TOP)) = \
374 (__arm_slist_node_t *)(__P_NODE); \
375 } while(0)
376#define ARM_LIST_STACK_PUSH(__P_TOP, __P_NODE) \
377 __ARM_LIST_STACK_PUSH((__P_TOP), (__P_NODE))
378#define ARM_LIST_INSERT_AFTER(__P_TARGET, __P_NODE) \
379 __ARM_LIST_STACK_PUSH((__P_TARGET), (__P_NODE))
380
381#define __ARM_LIST_STACK_POP(__P_TOP, __P_NODE) \
382 do { \
383 (*(__arm_slist_node_t **)&(__P_NODE)) = \
384 (__arm_slist_node_t *)(__P_TOP); \
385 if (NULL != (__P_TOP)) { \
386 (*(__arm_slist_node_t **)&(__P_TOP)) = \
387 ((__arm_slist_node_t *)(__P_NODE))->ptNext; \
388 ((__arm_slist_node_t *)(__P_NODE))->ptNext = NULL; \
389 } \
390 } while(0)
391#define ARM_LIST_STACK_POP(__P_TOP, __P_NODE) \
392 __ARM_LIST_STACK_POP((__P_TOP), (__P_NODE))
393#define ARM_LIST_REMOVE_AFTER(__P_TARGET, __P_NODE) \
394 ARM_LIST_STACK_POP((__P_TARGET), (__P_NODE))
395
396
397#define __ARM_LIST_QUEUE_ENQUEUE(__HEAD, __TAIL, __ITEM) \
398 do { \
399 if (NULL == (__TAIL)) { \
400 (*((__arm_slist_node_t **)&(__TAIL))) = \
401 (__arm_slist_node_t *)(__ITEM); \
402 ((__arm_slist_node_t *)(__ITEM))->ptNext = NULL; \
403 (*((__arm_slist_node_t **)&(__HEAD))) = \
404 (__arm_slist_node_t *)(__ITEM); \
405 } else { \
406 ((__arm_slist_node_t *)(__TAIL))->ptNext = \
407 (__arm_slist_node_t *)(__ITEM); \
408 ((__arm_slist_node_t *)(__ITEM))->ptNext = NULL; \
409 (*(__arm_slist_node_t **)&(__TAIL)) = \
410 (__arm_slist_node_t *)(__ITEM); \
411 } \
412 } while(0)
413#define ARM_LIST_QUEUE_ENQUEUE(__HEAD, __TAIL, __ITEM) \
414 __ARM_LIST_QUEUE_ENQUEUE((__HEAD), (__TAIL), (__ITEM))
415
416#define __ARM_LIST_QUEUE_DEQUEUE(__HEAD, __TAIL, __ITEM) \
417 do { \
418 (*(__arm_slist_node_t **)&(__ITEM)) = (__arm_slist_node_t *)(__HEAD); \
419 if (NULL != (__HEAD)) { \
420 (*(__arm_slist_node_t **)&(__HEAD)) = \
421 ((__arm_slist_node_t *)(__HEAD))->ptNext; \
422 if (NULL == (__HEAD)) { \
423 (__TAIL) = NULL; \
424 } \
425 } \
426 } while(0)
427
428#define ARM_LIST_QUEUE_DEQUEUE(__HEAD, __TAIL, __ITEM) \
429 __ARM_LIST_QUEUE_DEQUEUE((__HEAD), (__TAIL), (__ITEM))
430
431#define __ARM_LIST_QUEUE_PEEK(__HEAD, __TAIL, __ITEM) \
432 do { \
433 (*(__arm_slist_node_t **)&(__ITEM)) = (__arm_slist_node_t *)(__HEAD); \
434 } while(0)
435#define ARM_LIST_QUEUE_PEEK(__HEAD, __TAIL, __ITEM) \
436 __ARM_LIST_QUEUE_PEEK((__HEAD), (__TAIL), (__ITEM)) \
437
438/*----------------------------------------------------------------------------*
439 * Definition Template *
440 *----------------------------------------------------------------------------*/
441
442#define __def_low_lv_io(__NAME, __SW, ...) \
443const __arm_2d_low_level_io_t LOW_LEVEL_IO##__NAME = { \
444 .SW = (__arm_2d_io_func_t *)&(__SW), \
445 .HW = (NULL, ##__VA_ARGS__) \
446}
447#define def_low_lv_io(__NAME, __SW, ...) \
448 __def_low_lv_io(__NAME, __SW, ##__VA_ARGS__)
449
450
451#define __ref_low_lv_io(__NAME) &LOW_LEVEL_IO##__NAME
452#define ref_low_lv_io(__NAME) __ref_low_lv_io(__NAME)
453
454/*============================ TYPES =========================================*/
455
458 __arm_slist_node_t *ptNext;
459};
460
461
462/*============================ GLOBAL VARIABLES ==============================*/
463/*============================ PROTOTYPES ====================================*/
464
465#if defined(__clang__)
466# pragma clang diagnostic pop
467#elif __IS_COMPILER_ARM_COMPILER_5__
468#elif __IS_COMPILER_GCC__
469# pragma GCC diagnostic pop
470#endif
471
472#ifdef __cplusplus
473}
474#endif
475
476#endif /* end of __ARM_2D_UTILS_H__ */
477
478
479/*============================ MACROS ========================================*/
480/*----------------------------------------------------------------------------*
481 * Reentrant Macros *
482 *----------------------------------------------------------------------------*/
483
484/* un-define macros */
485#undef ARM_PRIVATE
486
487
488/* redefine macros */
489
490#if defined(__ARM_2D_IMPL__) || defined(__IS_COMPILER_IAR__)
491
492# define ARM_PRIVATE(...) \
493 struct { \
494 __VA_ARGS__ \
495 } __ALIGNED(__alignof__(struct {__VA_ARGS__}));
496
497#else
498# define ARM_PRIVATE(...) \
499 uint8_t ARM_CONNECT3(chMask,__LINE__,__COUNTER__) \
500 [sizeof(struct {__VA_ARGS__})] \
501 __ALIGNED(__alignof__(struct {__VA_ARGS__}));
502#endif
503
504
505
506
507/* post un-define macros */
508
509#undef __ARM_2D_IMPL__
510