-
Notifications
You must be signed in to change notification settings - Fork 54
/
lib_mem.h
1493 lines (1243 loc) · 95.9 KB
/
lib_mem.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
*********************************************************************************************************
* uC/LIB
* Custom Library Modules
*
* Copyright 2004-2021 Silicon Laboratories Inc. www.silabs.com
*
* SPDX-License-Identifier: APACHE-2.0
*
* This software is subject to an open source license and is distributed by
* Silicon Laboratories Inc. pursuant to the terms of the Apache License,
* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
*
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*
* STANDARD MEMORY OPERATIONS
*
* Filename : lib_mem.h
* Version : V1.39.01
*********************************************************************************************************
* Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software.
*
* (a) ALL standard library functions are implemented in the custom library modules :
*
* (1) \<Custom Library Directory>\lib_*.*
*
* (2) \<Custom Library Directory>\Ports\<cpu>\<compiler>\lib*_a.*
*
* where
* <Custom Library Directory> directory path for custom library software
* <cpu> directory name for specific processor (CPU)
* <compiler> directory name for specific compiler
*
* (b) Product-specific library functions are implemented in individual products.
*
* (2) Assumes the following versions (or more recent) of software modules are included in
* the project build :
*
* (a) uC/CPU V1.27
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* MODULE
*
* Note(s) : (1) This memory library header file is protected from multiple pre-processor inclusion through
* use of the memory library module present pre-processor macro definition.
*********************************************************************************************************
*/
#ifndef LIB_MEM_MODULE_PRESENT /* See Note #1. */
#define LIB_MEM_MODULE_PRESENT
/*
*********************************************************************************************************
* INCLUDE FILES
*
* Note(s) : (1) The custom library software files are located in the following directories :
*
* (a) \<Your Product Application>\lib_cfg.h
*
* (b) \<Custom Library Directory>\lib_*.*
*
* where
* <Your Product Application> directory path for Your Product's Application
* <Custom Library Directory> directory path for custom library software
*
* (2) CPU-configuration software files are located in the following directories :
*
* (a) \<CPU-Compiler Directory>\cpu_*.*
* (b) \<CPU-Compiler Directory>\<cpu>\<compiler>\cpu*.*
*
* where
* <CPU-Compiler Directory> directory path for common CPU-compiler software
* <cpu> directory name for specific processor (CPU)
* <compiler> directory name for specific compiler
*
* (3) Compiler MUST be configured to include as additional include path directories :
*
* (a) '\<Your Product Application>\' directory See Note #1a
*
* (b) '\<Custom Library Directory>\' directory See Note #1b
*
* (c) (1) '\<CPU-Compiler Directory>\' directory See Note #2a
* (2) '\<CPU-Compiler Directory>\<cpu>\<compiler>\' directory See Note #2b
*
* (4) NO compiler-supplied standard library functions SHOULD be used.
*********************************************************************************************************
*/
#include <cpu.h>
#include <cpu_core.h>
#include <lib_def.h>
#include <lib_cfg.h>
/*
*********************************************************************************************************
* EXTERNS
*********************************************************************************************************
*/
#ifdef LIB_MEM_MODULE
#define LIB_MEM_EXT
#else
#define LIB_MEM_EXT extern
#endif
/*
*********************************************************************************************************
* DEFINES
*********************************************************************************************************
*/
#define LIB_MEM_PADDING_ALIGN_NONE 1u
#define LIB_MEM_BLK_QTY_UNLIMITED 0u
/*
*********************************************************************************************************
* DEFAULT CONFIGURATION
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* MEMORY LIBRARY ARGUMENT CHECK CONFIGURATION
*
* Note(s) : (1) Configure LIB_MEM_CFG_ARG_CHK_EXT_EN to enable/disable the memory library suite external
* argument check feature :
*
* (a) When ENABLED, arguments received from any port interface provided by the developer
* or application are checked/validated.
*
* (b) When DISABLED, NO arguments received from any port interface provided by the developer
* or application are checked/validated.
*********************************************************************************************************
*/
/* Cfg external argument check feature (see Note #1) : */
#ifndef LIB_MEM_CFG_ARG_CHK_EXT_EN
#define LIB_MEM_CFG_ARG_CHK_EXT_EN DEF_DISABLED
/* DEF_DISABLED Argument check DISABLED */
/* DEF_ENABLED Argument check ENABLED */
#endif
/*
*********************************************************************************************************
* MEMORY LIBRARY ASSEMBLY OPTIMIZATION CONFIGURATION
*
* Note(s) : (1) Configure LIB_MEM_CFG_OPTIMIZE_ASM_EN to enable/disable assembly-optimized memory
* functions.
*********************************************************************************************************
*/
/* Cfg assembly-optimized function(s) [see Note #1] : */
#ifndef LIB_MEM_CFG_OPTIMIZE_ASM_EN
#define LIB_MEM_CFG_OPTIMIZE_ASM_EN DEF_DISABLED
/* DEF_DISABLED Assembly-optimized fnct(s) DISABLED */
/* DEF_ENABLED Assembly-optimized fnct(s) ENABLED */
#endif
/*
*********************************************************************************************************
* MEMORY ALLOCATION DEBUG INFORMATION CONFIGURATION
*
* Note(s) : (1) Configure LIB_MEM_CFG_DBG_INFO_EN to enable/disable debug information associated to each
* segment allocation.
*********************************************************************************************************
*/
#ifndef LIB_MEM_CFG_DBG_INFO_EN
#define LIB_MEM_CFG_DBG_INFO_EN DEF_DISABLED
#endif
/*
*********************************************************************************************************
* HEAP PADDING ALIGN CONFIGURATION
*
* Note(s) : (1) Configure LIB_MEM_CFG_HEAP_PADDING_ALIGN to set the padding alignment of any buffer
* allocated from the heap.
*********************************************************************************************************
*/
#ifndef LIB_MEM_CFG_HEAP_PADDING_ALIGN
#define LIB_MEM_CFG_HEAP_PADDING_ALIGN LIB_MEM_PADDING_ALIGN_NONE
#endif
/*
*********************************************************************************************************
* DATA TYPES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LIB MEM TYPE
*
* Note(s) : (1) 'LIB_MEM_TYPE' declared as 'CPU_INT32U' & all 'LIB_MEM_TYPE's #define'd with large, non-trivial
* values to trap & discard invalid/corrupted library memory objects based on 'LIB_MEM_TYPE'.
*********************************************************************************************************
*/
typedef CPU_INT32U LIB_MEM_TYPE;
/*
*********************************************************************************************************
* MEMORY POOL BLOCK QUANTITY DATA TYPE
*********************************************************************************************************
*/
typedef CPU_SIZE_T MEM_POOL_BLK_QTY;
/*
*********************************************************************************************************
* MEMORY POOL TABLE IX TYPE
*********************************************************************************************************
*/
typedef MEM_POOL_BLK_QTY MEM_POOL_IX;
/*
*********************************************************************************************************
* MEMORY ALLOCATION TRACKING INFO DATA TYPE
*********************************************************************************************************
*/
#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
typedef struct mem_alloc_info MEM_ALLOC_INFO;
struct mem_alloc_info { /* ------------------ MEM ALLOC INFO ------------------ */
const CPU_CHAR *NamePtr; /* Ptr to name. */
CPU_SIZE_T Size; /* Total alloc'd size, in bytes. */
MEM_ALLOC_INFO *NextPtr; /* Ptr to next alloc info in list. */
};
#endif
/*
*********************************************************************************************************
* MEMORY SEGMENTS DATA TYPES
*********************************************************************************************************
*/
typedef struct mem_seg MEM_SEG; /* --------------------- SEG DATA --------------------- */
struct mem_seg {
CPU_ADDR AddrBase; /* Seg start addr. */
CPU_ADDR AddrEnd; /* Seg end addr (last addr). */
CPU_ADDR AddrNext; /* Next free addr. */
MEM_SEG *NextPtr; /* Ptr to next seg. */
CPU_SIZE_T PaddingAlign; /* Padding alignment in byte. */
#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
const CPU_CHAR *NamePtr; /* Ptr to seg name. */
MEM_ALLOC_INFO *AllocInfoHeadPtr; /* Ptr to head of alloc info struct list. */
#endif
};
typedef struct mem_seg_info { /* --------------------- SEG INFO --------------------- */
CPU_SIZE_T UsedSize; /* Used size, independently of alignment. */
CPU_SIZE_T TotalSize; /* Total seg capacity, in octets. */
CPU_ADDR AddrBase;
CPU_ADDR AddrNextAlloc; /* Next aligned address, 0 if none available. */
} MEM_SEG_INFO;
/*
*********************************************************************************************************
* (STATIC) MEMORY POOL DATA TYPES
*
* Note(s) : (1) Free static memory pool blocks are indexed in the 'BlkFreeTbl' table. Newly freed blocks
* are added at the first available position in the table and blocks are retrieved from the
* last occupied position, in a LIFO fashion.
*
* /-------------------------------\
* |/------------\ |
* BlkFreeTbl || Start v v End
* /--------\ || /--------------------------------------------\
* |p_free_1|---/| | | | | | |
* |--------| | \--------------------------------------------/
* |p_free_2|----/ ^ | |
* |--------| | |__Blk___|
* |p_free_3|--------/ (Next block to be retrieved.) Size
* |--------|
* | |<-------- (Next block to be freed.)
* \--------/
*
*********************************************************************************************************
*/
/* --------------------- MEM POOL --------------------- */
typedef struct mem_pool {
void *PoolAddrStart; /* Ptr to start of mem seg for mem pool blks. */
void *PoolAddrEnd; /* Ptr to end of mem seg for mem pool blks. */
MEM_POOL_BLK_QTY BlkNbr; /* Nbr of mem pool blks. */
CPU_SIZE_T BlkSize; /* Size of mem pool blks (in octets). */
void **BlkFreeTbl; /* Tbl of free mem pool blks. */
CPU_SIZE_T BlkFreeTblIx; /* Ix of next free blk free tbl entry. */
} MEM_POOL;
/*
*********************************************************************************************************
* DYNAMIC MEMORY POOL DATA TYPE
*
* Note(s) : (1) Dynamic memory pool blocks are not indexed in a table. Only freed blocks are linked using
* a singly linked list, in a LIFO fashion; newly freed blocks are inserted at the head of the
* list and blocks are also retrieved from the head of the list.
*
* (2) Pointers to the next block are only present when a block is free, using the first location
* in the allocated memory block. The user of dynamic memory pool must not assume his data
* will not be overwritten when a block is freed.
*
* /----------------\
* /----------\ | /----------\ | /----------\ /----------\
* BlkFreePtr-->|(NextPtr) |---/ | | \--->|(NextPtr) |-->|(NextPtr) |--> DEF_NULL
* |----------| | Blk in | |----------| |----------|
* | | | use | | | | |
* | | | | | | | |
* \----------/ \----------/ \----------/ \----------/
*
*********************************************************************************************************
*/
typedef struct mem_dyn_pool { /* ---------------- DYN MEM POOL DATA ----------------- */
MEM_SEG *PoolSegPtr; /* Mem pool from which blks are alloc'd. */
CPU_SIZE_T BlkSize; /* Size of pool blks, in octets. */
CPU_SIZE_T BlkAlign; /* Align req'd for blks, in octets. */
CPU_SIZE_T BlkPaddingAlign; /* Padding alignment in bytes for this mem seg. */
void *BlkFreePtr; /* Ptr to first free blk. */
CPU_SIZE_T BlkQtyMax; /* Max qty of blk in dyn mem pool. 0 = unlimited. */
CPU_SIZE_T BlkAllocCnt; /* Cnt of alloc blk. */
#if (LIB_MEM_CFG_DBG_INFO_EN == DEF_ENABLED)
const CPU_CHAR *NamePtr; /* Ptr to mem pool name. */
#endif
} MEM_DYN_POOL;
/*
*********************************************************************************************************
* GLOBAL VARIABLES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* MACRO'S
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* MEMORY DATA VALUE MACRO'S
*
* Note(s) : (1) (a) Some variables & variable buffers to pass & receive data values MUST start on appropriate
* CPU word-aligned addresses. This is required because most word-aligned processors are more
* efficient & may even REQUIRE that multi-octet words start on CPU word-aligned addresses.
*
* (1) For 16-bit word-aligned processors, this means that
*
* all 16- & 32-bit words MUST start on addresses that are multiples of 2 octets
*
* (2) For 32-bit word-aligned processors, this means that
*
* all 16-bit words MUST start on addresses that are multiples of 2 octets
* all 32-bit words MUST start on addresses that are multiples of 4 octets
*
* (b) However, some data values macro's appropriately access data values from any CPU addresses,
* word-aligned or not. Thus for processors that require data word alignment, data words can
* be accessed to/from any CPU address, word-aligned or not, without generating data-word-
* alignment exceptions/faults.
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* ENDIAN WORD ORDER MACRO'S
*
* Description : Convert data values to & from big-, little, or host-endian CPU word order.
*
* Argument(s) : val Data value to convert (see Notes #1 & #2).
*
* Return(s) : Converted data value (see Notes #1 & #2).
*
* Caller(s) : Application.
*
* Note(s) : (1) Convert data values to the desired data-word order :
*
* MEM_VAL_BIG_TO_LITTLE_xx() Convert big- endian data values
* to little- endian data values
* MEM_VAL_LITTLE_TO_BIG_xx() Convert little- endian data values
* to big- endian data values
* MEM_VAL_xxx_TO_HOST_xx() Convert big-/little-endian data values
* to host- endian data values
* MEM_VAL_HOST_TO_xxx_xx() Convert host- endian data values
* to big-/little-endian data values
*
* See also 'cpu.h CPU WORD CONFIGURATION Note #2'.
*
* (2) 'val' data value to convert & any variable to receive the returned conversion MUST
* start on appropriate CPU word-aligned addresses.
*
* See also 'MEMORY DATA VALUE MACRO'S Note #1a'.
*
* (3) MEM_VAL_COPY_xxx() macro's are more efficient than generic endian word order macro's &
* are also independent of CPU data-word-alignment & SHOULD be used whenever possible.
*
* See also 'MEM_VAL_COPY_GET_xxx() Note #4'
* & 'MEM_VAL_COPY_SET_xxx() Note #4'.
*
* (4) Generic endian word order macro's are NOT atomic operations & MUST NOT be used on any
* non-static (i.e. volatile) variables, registers, hardware, etc.; without the caller of
* the macro's providing some form of additional protection (e.g. mutual exclusion).
*
* (5) The 'CPU_CFG_ENDIAN_TYPE' pre-processor 'else'-conditional code SHOULD never be compiled/
* linked since each 'cpu.h' SHOULD ensure that the CPU data-word-memory order configuration
* constant (CPU_CFG_ENDIAN_TYPE) is configured with an appropriate data-word-memory order
* value (see 'cpu.h CPU WORD CONFIGURATION Note #2'). The 'else'-conditional code is
* included as an extra precaution in case 'cpu.h' is incorrectly configured.
*********************************************************************************************************
*/
#if ((CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_64) || \
(CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_32))
#define MEM_VAL_BIG_TO_LITTLE_16(val) ((CPU_INT16U)(((CPU_INT16U)((((CPU_INT16U)(val)) & (CPU_INT16U) 0xFF00u) >> (1u * DEF_OCTET_NBR_BITS))) | \
((CPU_INT16U)((((CPU_INT16U)(val)) & (CPU_INT16U) 0x00FFu) << (1u * DEF_OCTET_NBR_BITS)))))
#define MEM_VAL_BIG_TO_LITTLE_32(val) ((CPU_INT32U)(((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0xFF000000u) >> (3u * DEF_OCTET_NBR_BITS))) | \
((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x00FF0000u) >> (1u * DEF_OCTET_NBR_BITS))) | \
((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x0000FF00u) << (1u * DEF_OCTET_NBR_BITS))) | \
((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x000000FFu) << (3u * DEF_OCTET_NBR_BITS)))))
#elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_16)
#define MEM_VAL_BIG_TO_LITTLE_16(val) ((CPU_INT16U)(((CPU_INT16U)((((CPU_INT16U)(val)) & (CPU_INT16U) 0xFF00u) >> (1u * DEF_OCTET_NBR_BITS))) | \
((CPU_INT16U)((((CPU_INT16U)(val)) & (CPU_INT16U) 0x00FFu) << (1u * DEF_OCTET_NBR_BITS)))))
#define MEM_VAL_BIG_TO_LITTLE_32(val) ((CPU_INT32U)(((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0xFF000000u) >> (1u * DEF_OCTET_NBR_BITS))) | \
((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x00FF0000u) << (1u * DEF_OCTET_NBR_BITS))) | \
((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x0000FF00u) >> (1u * DEF_OCTET_NBR_BITS))) | \
((CPU_INT32U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x000000FFu) << (1u * DEF_OCTET_NBR_BITS)))))
#else
#define MEM_VAL_BIG_TO_LITTLE_16(val) (val)
#define MEM_VAL_BIG_TO_LITTLE_32(val) (val)
#endif
#define MEM_VAL_LITTLE_TO_BIG_16(val) MEM_VAL_BIG_TO_LITTLE_16(val)
#define MEM_VAL_LITTLE_TO_BIG_32(val) MEM_VAL_BIG_TO_LITTLE_32(val)
#if (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
#define MEM_VAL_BIG_TO_HOST_16(val) (val)
#define MEM_VAL_BIG_TO_HOST_32(val) (val)
#define MEM_VAL_LITTLE_TO_HOST_16(val) MEM_VAL_LITTLE_TO_BIG_16(val)
#define MEM_VAL_LITTLE_TO_HOST_32(val) MEM_VAL_LITTLE_TO_BIG_32(val)
#elif (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_LITTLE)
#define MEM_VAL_BIG_TO_HOST_16(val) MEM_VAL_BIG_TO_LITTLE_16(val)
#define MEM_VAL_BIG_TO_HOST_32(val) MEM_VAL_BIG_TO_LITTLE_32(val)
#define MEM_VAL_LITTLE_TO_HOST_16(val) (val)
#define MEM_VAL_LITTLE_TO_HOST_32(val) (val)
#else /* See Note #5. */
#error "CPU_CFG_ENDIAN_TYPE illegally #defined in 'cpu.h' "
#error " [See 'cpu.h CONFIGURATION ERRORS']"
#endif
#define MEM_VAL_HOST_TO_BIG_16(val) MEM_VAL_BIG_TO_HOST_16(val)
#define MEM_VAL_HOST_TO_BIG_32(val) MEM_VAL_BIG_TO_HOST_32(val)
#define MEM_VAL_HOST_TO_LITTLE_16(val) MEM_VAL_LITTLE_TO_HOST_16(val)
#define MEM_VAL_HOST_TO_LITTLE_32(val) MEM_VAL_LITTLE_TO_HOST_32(val)
/*
*********************************************************************************************************
* MEM_VAL_GET_xxx()
*
* Description : Decode data values from any CPU memory address.
*
* Argument(s) : addr Lowest CPU memory address of data value to decode (see Notes #2 & #3a).
*
* Return(s) : Decoded data value from CPU memory address (see Notes #1 & #3b).
*
* Caller(s) : Application.
*
* Note(s) : (1) Decode data values based on the values' data-word order in CPU memory :
*
* MEM_VAL_GET_xxx_BIG() Decode big- endian data values -- data words' most
* significant octet @ lowest memory address
* MEM_VAL_GET_xxx_LITTLE() Decode little-endian data values -- data words' least
* significant octet @ lowest memory address
* MEM_VAL_GET_xxx() Decode data values using CPU's native or configured
* data-word order
*
* See also 'cpu.h CPU WORD CONFIGURATION Note #2'.
*
* (2) CPU memory addresses/pointers NOT checked for NULL.
*
* (3) (a) MEM_VAL_GET_xxx() macro's decode data values without regard to CPU word-aligned addresses.
* Thus for processors that require data word alignment, data words can be decoded from any
* CPU address, word-aligned or not, without generating data-word-alignment exceptions/faults.
*
* (b) However, any variable to receive the returned data value MUST start on an appropriate CPU
* word-aligned address.
*
* See also 'MEMORY DATA VALUE MACRO'S Note #1'.
*
* (4) MEM_VAL_COPY_GET_xxx() macro's are more efficient than MEM_VAL_GET_xxx() macro's & are
* also independent of CPU data-word-alignment & SHOULD be used whenever possible.
*
* See also 'MEM_VAL_COPY_GET_xxx() Note #4'.
*
* (5) MEM_VAL_GET_xxx() macro's are NOT atomic operations & MUST NOT be used on any non-static
* (i.e. volatile) variables, registers, hardware, etc.; without the caller of the macro's
* providing some form of additional protection (e.g. mutual exclusion).
*
* (6) The 'CPU_CFG_ENDIAN_TYPE' pre-processor 'else'-conditional code SHOULD never be compiled/
* linked since each 'cpu.h' SHOULD ensure that the CPU data-word-memory order configuration
* constant (CPU_CFG_ENDIAN_TYPE) is configured with an appropriate data-word-memory order
* value (see 'cpu.h CPU WORD CONFIGURATION Note #2'). The 'else'-conditional code is
* included as an extra precaution in case 'cpu.h' is incorrectly configured.
*********************************************************************************************************
*/
#define MEM_VAL_GET_INT08U_BIG(addr) ((CPU_INT08U) ((CPU_INT08U)(((CPU_INT08U)(*(((CPU_INT08U *)(addr)) + 0))) << (0u * DEF_OCTET_NBR_BITS))))
#define MEM_VAL_GET_INT16U_BIG(addr) ((CPU_INT16U)(((CPU_INT16U)(((CPU_INT16U)(*(((CPU_INT08U *)(addr)) + 0))) << (1u * DEF_OCTET_NBR_BITS))) + \
((CPU_INT16U)(((CPU_INT16U)(*(((CPU_INT08U *)(addr)) + 1))) << (0u * DEF_OCTET_NBR_BITS)))))
#define MEM_VAL_GET_INT24U_BIG(addr) ((CPU_INT32U)(((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 0))) << (2u * DEF_OCTET_NBR_BITS))) + \
((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 1))) << (1u * DEF_OCTET_NBR_BITS))) + \
((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 2))) << (0u * DEF_OCTET_NBR_BITS)))))
#define MEM_VAL_GET_INT32U_BIG(addr) ((CPU_INT32U)(((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 0))) << (3u * DEF_OCTET_NBR_BITS))) + \
((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 1))) << (2u * DEF_OCTET_NBR_BITS))) + \
((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 2))) << (1u * DEF_OCTET_NBR_BITS))) + \
((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 3))) << (0u * DEF_OCTET_NBR_BITS)))))
#define MEM_VAL_GET_INT08U_LITTLE(addr) ((CPU_INT08U) ((CPU_INT08U)(((CPU_INT08U)(*(((CPU_INT08U *)(addr)) + 0))) << (0u * DEF_OCTET_NBR_BITS))))
#define MEM_VAL_GET_INT16U_LITTLE(addr) ((CPU_INT16U)(((CPU_INT16U)(((CPU_INT16U)(*(((CPU_INT08U *)(addr)) + 0))) << (0u * DEF_OCTET_NBR_BITS))) + \
((CPU_INT16U)(((CPU_INT16U)(*(((CPU_INT08U *)(addr)) + 1))) << (1u * DEF_OCTET_NBR_BITS)))))
#define MEM_VAL_GET_INT24U_LITTLE(addr) ((CPU_INT32U)(((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 0))) << (0u * DEF_OCTET_NBR_BITS))) + \
((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 1))) << (1u * DEF_OCTET_NBR_BITS))) + \
((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 2))) << (2u * DEF_OCTET_NBR_BITS)))))
#define MEM_VAL_GET_INT32U_LITTLE(addr) ((CPU_INT32U)(((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 0))) << (0u * DEF_OCTET_NBR_BITS))) + \
((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 1))) << (1u * DEF_OCTET_NBR_BITS))) + \
((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 2))) << (2u * DEF_OCTET_NBR_BITS))) + \
((CPU_INT32U)(((CPU_INT32U)(*(((CPU_INT08U *)(addr)) + 3))) << (3u * DEF_OCTET_NBR_BITS)))))
#if (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
#define MEM_VAL_GET_INT08U(addr) MEM_VAL_GET_INT08U_BIG(addr)
#define MEM_VAL_GET_INT16U(addr) MEM_VAL_GET_INT16U_BIG(addr)
#define MEM_VAL_GET_INT24U(addr) MEM_VAL_GET_INT24U_BIG(addr)
#define MEM_VAL_GET_INT32U(addr) MEM_VAL_GET_INT32U_BIG(addr)
#elif (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_LITTLE)
#define MEM_VAL_GET_INT08U(addr) MEM_VAL_GET_INT08U_LITTLE(addr)
#define MEM_VAL_GET_INT16U(addr) MEM_VAL_GET_INT16U_LITTLE(addr)
#define MEM_VAL_GET_INT24U(addr) MEM_VAL_GET_INT24U_LITTLE(addr)
#define MEM_VAL_GET_INT32U(addr) MEM_VAL_GET_INT32U_LITTLE(addr)
#else /* See Note #6. */
#error "CPU_CFG_ENDIAN_TYPE illegally #defined in 'cpu.h' "
#error " [See 'cpu.h CONFIGURATION ERRORS']"
#endif
/*
*********************************************************************************************************
* MEM_VAL_SET_xxx()
*
* Description : Encode data values to any CPU memory address.
*
* Argument(s) : addr Lowest CPU memory address to encode data value (see Notes #2 & #3a).
*
* val Data value to encode (see Notes #1 & #3b).
*
* Return(s) : none.
*
* Caller(s) : Application.
*
* Note(s) : (1) Encode data values into CPU memory based on the values' data-word order :
*
* MEM_VAL_SET_xxx_BIG() Encode big- endian data values -- data words' most
* significant octet @ lowest memory address
* MEM_VAL_SET_xxx_LITTLE() Encode little-endian data values -- data words' least
* significant octet @ lowest memory address
* MEM_VAL_SET_xxx() Encode data values using CPU's native or configured
* data-word order
*
* See also 'cpu.h CPU WORD CONFIGURATION Note #2'.
*
* (2) CPU memory addresses/pointers NOT checked for NULL.
*
* (3) (a) MEM_VAL_SET_xxx() macro's encode data values without regard to CPU word-aligned addresses.
* Thus for processors that require data word alignment, data words can be encoded to any
* CPU address, word-aligned or not, without generating data-word-alignment exceptions/faults.
*
* (b) However, 'val' data value to encode MUST start on an appropriate CPU word-aligned address.
*
* See also 'MEMORY DATA VALUE MACRO'S Note #1'.
*
* (4) MEM_VAL_COPY_SET_xxx() macro's are more efficient than MEM_VAL_SET_xxx() macro's & are
* also independent of CPU data-word-alignment & SHOULD be used whenever possible.
*
* See also 'MEM_VAL_COPY_SET_xxx() Note #4'.
*
* (5) MEM_VAL_SET_xxx() macro's are NOT atomic operations & MUST NOT be used on any non-static
* (i.e. volatile) variables, registers, hardware, etc.; without the caller of the macro's
* providing some form of additional protection (e.g. mutual exclusion).
*
* (6) The 'CPU_CFG_ENDIAN_TYPE' pre-processor 'else'-conditional code SHOULD never be compiled/
* linked since each 'cpu.h' SHOULD ensure that the CPU data-word-memory order configuration
* constant (CPU_CFG_ENDIAN_TYPE) is configured with an appropriate data-word-memory order
* value (see 'cpu.h CPU WORD CONFIGURATION Note #2'). The 'else'-conditional code is
* included as an extra precaution in case 'cpu.h' is incorrectly configured.
*********************************************************************************************************
*/
#define MEM_VAL_SET_INT08U_BIG(addr, val) do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT08U)(val)) & (CPU_INT08U) 0xFFu) >> (0u * DEF_OCTET_NBR_BITS))); } while (0)
#define MEM_VAL_SET_INT16U_BIG(addr, val) do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT16U)(val)) & (CPU_INT16U) 0xFF00u) >> (1u * DEF_OCTET_NBR_BITS))); \
(*(((CPU_INT08U *)(addr)) + 1)) = ((CPU_INT08U)((((CPU_INT16U)(val)) & (CPU_INT16U) 0x00FFu) >> (0u * DEF_OCTET_NBR_BITS))); } while (0)
#define MEM_VAL_SET_INT24U_BIG(addr, val) do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U) 0xFF0000u) >> (2u * DEF_OCTET_NBR_BITS))); \
(*(((CPU_INT08U *)(addr)) + 1)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U) 0x00FF00u) >> (1u * DEF_OCTET_NBR_BITS))); \
(*(((CPU_INT08U *)(addr)) + 2)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U) 0x0000FFu) >> (0u * DEF_OCTET_NBR_BITS))); } while (0)
#define MEM_VAL_SET_INT32U_BIG(addr, val) do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0xFF000000u) >> (3u * DEF_OCTET_NBR_BITS))); \
(*(((CPU_INT08U *)(addr)) + 1)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x00FF0000u) >> (2u * DEF_OCTET_NBR_BITS))); \
(*(((CPU_INT08U *)(addr)) + 2)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x0000FF00u) >> (1u * DEF_OCTET_NBR_BITS))); \
(*(((CPU_INT08U *)(addr)) + 3)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x000000FFu) >> (0u * DEF_OCTET_NBR_BITS))); } while (0)
#define MEM_VAL_SET_INT08U_LITTLE(addr, val) do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT08U)(val)) & (CPU_INT08U) 0xFFu) >> (0u * DEF_OCTET_NBR_BITS))); } while (0)
#define MEM_VAL_SET_INT16U_LITTLE(addr, val) do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT16U)(val)) & (CPU_INT16U) 0x00FFu) >> (0u * DEF_OCTET_NBR_BITS))); \
(*(((CPU_INT08U *)(addr)) + 1)) = ((CPU_INT08U)((((CPU_INT16U)(val)) & (CPU_INT16U) 0xFF00u) >> (1u * DEF_OCTET_NBR_BITS))); } while (0)
#define MEM_VAL_SET_INT24U_LITTLE(addr, val) do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U) 0x0000FFu) >> (0u * DEF_OCTET_NBR_BITS))); \
(*(((CPU_INT08U *)(addr)) + 1)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U) 0x00FF00u) >> (1u * DEF_OCTET_NBR_BITS))); \
(*(((CPU_INT08U *)(addr)) + 2)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U) 0xFF0000u) >> (2u * DEF_OCTET_NBR_BITS))); } while (0)
#define MEM_VAL_SET_INT32U_LITTLE(addr, val) do { (*(((CPU_INT08U *)(addr)) + 0)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x000000FFu) >> (0u * DEF_OCTET_NBR_BITS))); \
(*(((CPU_INT08U *)(addr)) + 1)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x0000FF00u) >> (1u * DEF_OCTET_NBR_BITS))); \
(*(((CPU_INT08U *)(addr)) + 2)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0x00FF0000u) >> (2u * DEF_OCTET_NBR_BITS))); \
(*(((CPU_INT08U *)(addr)) + 3)) = ((CPU_INT08U)((((CPU_INT32U)(val)) & (CPU_INT32U)0xFF000000u) >> (3u * DEF_OCTET_NBR_BITS))); } while (0)
#if (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
#define MEM_VAL_SET_INT08U(addr, val) MEM_VAL_SET_INT08U_BIG((addr), (val))
#define MEM_VAL_SET_INT16U(addr, val) MEM_VAL_SET_INT16U_BIG((addr), (val))
#define MEM_VAL_SET_INT24U(addr, val) MEM_VAL_SET_INT24U_BIG((addr), (val))
#define MEM_VAL_SET_INT32U(addr, val) MEM_VAL_SET_INT32U_BIG((addr), (val))
#elif (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_LITTLE)
#define MEM_VAL_SET_INT08U(addr, val) MEM_VAL_SET_INT08U_LITTLE((addr), (val))
#define MEM_VAL_SET_INT16U(addr, val) MEM_VAL_SET_INT16U_LITTLE((addr), (val))
#define MEM_VAL_SET_INT24U(addr, val) MEM_VAL_SET_INT24U_LITTLE((addr), (val))
#define MEM_VAL_SET_INT32U(addr, val) MEM_VAL_SET_INT32U_LITTLE((addr), (val))
#else /* See Note #6. */
#error "CPU_CFG_ENDIAN_TYPE illegally #defined in 'cpu.h' "
#error " [See 'cpu.h CONFIGURATION ERRORS']"
#endif
/*
*********************************************************************************************************
* MEM_VAL_COPY_GET_xxx()
*
* Description : Copy & decode data values from any CPU memory address to any CPU memory address.
*
* Argument(s) : addr_dest Lowest CPU memory address to copy/decode source address's data value
* (see Notes #2 & #3).
*
* addr_src Lowest CPU memory address of data value to copy/decode
* (see Notes #2 & #3).
*
* Return(s) : none.
*
* Caller(s) : Application.
*
* Note(s) : (1) Copy/decode data values based on the values' data-word order :
*
* MEM_VAL_COPY_GET_xxx_BIG() Decode big- endian data values -- data words' most
* significant octet @ lowest memory address
* MEM_VAL_COPY_GET_xxx_LITTLE() Decode little-endian data values -- data words' least
* significant octet @ lowest memory address
* MEM_VAL_COPY_GET_xxx() Decode data values using CPU's native or configured
* data-word order
*
* See also 'cpu.h CPU WORD CONFIGURATION Note #2'.
*
* (2) (a) CPU memory addresses/pointers NOT checked for NULL.
*
* (b) CPU memory addresses/buffers NOT checked for overlapping.
*
* (1) IEEE Std 1003.1, 2004 Edition, Section 'memcpy() : DESCRIPTION' states that
* "copying ... between objects that overlap ... is undefined".
*
* (3) MEM_VAL_COPY_GET_xxx() macro's copy/decode data values without regard to CPU word-aligned
* addresses. Thus for processors that require data word alignment, data words can be copied/
* decoded to/from any CPU address, word-aligned or not, without generating data-word-alignment
* exceptions/faults.
*
* (4) MEM_VAL_COPY_GET_xxx() macro's are more efficient than MEM_VAL_GET_xxx() macro's & are
* also independent of CPU data-word-alignment & SHOULD be used whenever possible.
*
* See also 'MEM_VAL_GET_xxx() Note #4'.
*
* (5) Since octet-order copy/conversion are inverse operations, MEM_VAL_COPY_GET_xxx() &
* MEM_VAL_COPY_SET_xxx() macros are inverse, but identical, operations & are provided
* in both forms for semantics & consistency.
*
* See also 'MEM_VAL_COPY_SET_xxx() Note #5'.
*
* (6) MEM_VAL_COPY_GET_xxx() macro's are NOT atomic operations & MUST NOT be used on any non-
* static (i.e. volatile) variables, registers, hardware, etc.; without the caller of the
* macro's providing some form of additional protection (e.g. mutual exclusion).
*
* (7) The 'CPU_CFG_ENDIAN_TYPE' pre-processor 'else'-conditional code SHOULD never be compiled/
* linked since each 'cpu.h' SHOULD ensure that the CPU data-word-memory order configuration
* constant (CPU_CFG_ENDIAN_TYPE) is configured with an appropriate data-word-memory order
* value (see 'cpu.h CPU WORD CONFIGURATION Note #2'). The 'else'-conditional code is
* included as an extra precaution in case 'cpu.h' is incorrectly configured.
*********************************************************************************************************
*/
#if (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
#define MEM_VAL_COPY_GET_INT08U_BIG(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 0)); } while (0)
#define MEM_VAL_COPY_GET_INT16U_BIG(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 0)); \
(*((destptr) + 1)) = (*((srcptr) + 1)); } while (0)
#define MEM_VAL_COPY_GET_INT24U_BIG(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 0)); \
(*((destptr) + 1)) = (*((srcptr) + 1)); \
(*((destptr) + 2)) = (*((srcptr) + 2)); } while (0)
#define MEM_VAL_COPY_GET_INT32U_BIG(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 0)); \
(*((destptr) + 1)) = (*((srcptr) + 1)); \
(*((destptr) + 2)) = (*((srcptr) + 2)); \
(*((destptr) + 3)) = (*((srcptr) + 3)); } while (0)
#define MEM_VAL_COPY_GET_INT08U_LITTLE(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 0)); } while (0)
#define MEM_VAL_COPY_GET_INT16U_LITTLE(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 1)); \
(*((destptr) + 1)) = (*((srcptr) + 0)); } while (0)
#define MEM_VAL_COPY_GET_INT24U_LITTLE(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 2)); \
(*((destptr) + 1)) = (*((srcptr) + 1)); \
(*((destptr) + 2)) = (*((srcptr) + 0)); } while (0)
#define MEM_VAL_COPY_GET_INT32U_LITTLE(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 3)); \
(*((destptr) + 1)) = (*((srcptr) + 2)); \
(*((destptr) + 2)) = (*((srcptr) + 1)); \
(*((destptr) + 3)) = (*((srcptr) + 0)); } while (0)
#define MEM_VAL_COPY_GET_INT08U(addr_dest, addr_src) MEM_VAL_COPY_GET_INT08U_BIG((addr_dest), (addr_src))
#define MEM_VAL_COPY_GET_INT16U(addr_dest, addr_src) MEM_VAL_COPY_GET_INT16U_BIG((addr_dest), (addr_src))
#define MEM_VAL_COPY_GET_INT24U(addr_dest, addr_src) MEM_VAL_COPY_GET_INT24U_BIG((addr_dest), (addr_src))
#define MEM_VAL_COPY_GET_INT32U(addr_dest, addr_src) MEM_VAL_COPY_GET_INT32U_BIG((addr_dest), (addr_src))
#elif (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_LITTLE)
#define MEM_VAL_COPY_GET_INT08U_BIG(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 0)); } while (0)
#define MEM_VAL_COPY_GET_INT16U_BIG(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U * srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 1)); \
(*((destptr) + 1)) = (*((srcptr) + 0)); } while (0)
#define MEM_VAL_COPY_GET_INT24U_BIG(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 2)); \
(*((destptr) + 1)) = (*((srcptr) + 1)); \
(*((destptr) + 2)) = (*((srcptr) + 0)); } while (0)
#define MEM_VAL_COPY_GET_INT32U_BIG(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 3)); \
(*((destptr) + 1)) = (*((srcptr) + 2)); \
(*((destptr) + 2)) = (*((srcptr) + 1)); \
(*((destptr) + 3)) = (*((srcptr) + 0)); } while (0)
#define MEM_VAL_COPY_GET_INT08U_LITTLE(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 0)); } while (0)
#define MEM_VAL_COPY_GET_INT16U_LITTLE(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 0)); \
(*((destptr) + 1)) = (*((srcptr) + 1)); } while (0)
#define MEM_VAL_COPY_GET_INT24U_LITTLE(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 0)); \
(*((destptr) + 1)) = (*((srcptr) + 1)); \
(*((destptr) + 2)) = (*((srcptr) + 2)); } while (0)
#define MEM_VAL_COPY_GET_INT32U_LITTLE(addr_dest, addr_src) do { \
CPU_INT08U *destptr = (CPU_INT08U *)(addr_dest); \
CPU_INT08U *srcptr = (CPU_INT08U *)(addr_src); \
(*((destptr) + 0)) = (*((srcptr) + 0)); \
(*((destptr) + 1)) = (*((srcptr) + 1)); \
(*((destptr) + 2)) = (*((srcptr) + 2)); \
(*((destptr) + 3)) = (*((srcptr) + 3)); } while (0)
#define MEM_VAL_COPY_GET_INT08U(addr_dest, addr_src) MEM_VAL_COPY_GET_INT08U_LITTLE((addr_dest), (addr_src))
#define MEM_VAL_COPY_GET_INT16U(addr_dest, addr_src) MEM_VAL_COPY_GET_INT16U_LITTLE((addr_dest), (addr_src))
#define MEM_VAL_COPY_GET_INT24U(addr_dest, addr_src) MEM_VAL_COPY_GET_INT24U_LITTLE((addr_dest), (addr_src))
#define MEM_VAL_COPY_GET_INT32U(addr_dest, addr_src) MEM_VAL_COPY_GET_INT32U_LITTLE((addr_dest), (addr_src))
#else /* See Note #7. */
#error "CPU_CFG_ENDIAN_TYPE illegally #defined in 'cpu.h' "
#error " [See 'cpu.h CONFIGURATION ERRORS']"
#endif
/*
*********************************************************************************************************
* MEM_VAL_COPY_GET_INTU_xxx()
*
* Description : Copy & decode data values from any CPU memory address to any CPU memory address for
* any sized data values.
*
* Argument(s) : addr_dest Lowest CPU memory address to copy/decode source address's data value
* (see Notes #2 & #3).
*
* addr_src Lowest CPU memory address of data value to copy/decode
* (see Notes #2 & #3).
*
* val_size Number of data value octets to copy/decode.
*
* Return(s) : none.
*
* Caller(s) : Application.
*
* Note(s) : (1) Copy/decode data values based on the values' data-word order :
*
* MEM_VAL_COPY_GET_INTU_BIG() Decode big- endian data values -- data words' most
* significant octet @ lowest memory address
* MEM_VAL_COPY_GET_INTU_LITTLE() Decode little-endian data values -- data words' least
* significant octet @ lowest memory address
* MEM_VAL_COPY_GET_INTU() Decode data values using CPU's native or configured
* data-word order
*
* See also 'cpu.h CPU WORD CONFIGURATION Note #2'.
*
* (2) (a) CPU memory addresses/pointers NOT checked for NULL.
*
* (b) CPU memory addresses/buffers NOT checked for overlapping.
*
* (1) IEEE Std 1003.1, 2004 Edition, Section 'memcpy() : DESCRIPTION' states that
* "copying ... between objects that overlap ... is undefined".
*
* (3) MEM_VAL_COPY_GET_INTU_xxx() macro's copy/decode data values without regard to CPU word-
* aligned addresses. Thus for processors that require data word alignment, data words
* can be copied/decoded to/from any CPU address, word-aligned or not, without generating
* data-word-alignment exceptions/faults.
*
* (4) MEM_VAL_COPY_GET_xxx() macro's are more efficient than MEM_VAL_COPY_GET_INTU_xxx()
* macro's & SHOULD be used whenever possible.
*
* See also 'MEM_VAL_COPY_GET_xxx() Note #4'.
*
* (5) Since octet-order copy/conversion are inverse operations, MEM_VAL_COPY_GET_INTU_xxx() &
* MEM_VAL_COPY_SET_INTU_xxx() macros are inverse, but identical, operations & are provided
* in both forms for semantics & consistency.
*
* See also 'MEM_VAL_COPY_SET_INTU_xxx() Note #5'.
*
* (6) MEM_VAL_COPY_GET_INTU_xxx() macro's are NOT atomic operations & MUST NOT be used on any
* non-static (i.e. volatile) variables, registers, hardware, etc.; without the caller of
* the macro's providing some form of additional protection (e.g. mutual exclusion).
*
* (7) MISRA-C 2004 Rule 5.2 states that "identifiers in an inner scope shall not use the same
* name as an indentifier in an outer scope, and therefore hide that identifier".
*
* Therefore, to avoid possible redeclaration of commonly-used loop counter identifier names,
* 'i' & 'j', MEM_VAL_COPY_GET_INTU_xxx() loop counter identifier names are prefixed with a
* single underscore.
*
* (8) The 'CPU_CFG_ENDIAN_TYPE' pre-processor 'else'-conditional code SHOULD never be compiled/
* linked since each 'cpu.h' SHOULD ensure that the CPU data-word-memory order configuration
* constant (CPU_CFG_ENDIAN_TYPE) is configured with an appropriate data-word-memory order
* value (see 'cpu.h CPU WORD CONFIGURATION Note #2'). The 'else'-conditional code is
* included as an extra precaution in case 'cpu.h' is incorrectly configured.
*********************************************************************************************************
*/
#if (CPU_CFG_ENDIAN_TYPE == CPU_ENDIAN_TYPE_BIG)
#define MEM_VAL_COPY_GET_INTU_BIG(addr_dest, addr_src, val_size) do { \
CPU_SIZE_T _i; \
\
for (_i = 0; _i < (val_size); _i++) { \
(*(((CPU_INT08U *)(addr_dest)) + _i)) = (*(((CPU_INT08U *)(addr_src)) + _i)); \
} \
} while (0)
#define MEM_VAL_COPY_GET_INTU_LITTLE(addr_dest, addr_src, val_size) do { \
CPU_SIZE_T _i; \
CPU_SIZE_T _j; \