1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _PICO_BINARY_INFO_CODE_H
8 #define _PICO_BINARY_INFO_CODE_H
9 
10 #include "pico.h"
11 #include "pico/binary_info/structure.h"
12 
13 #if !PICO_NO_BINARY_INFO
14 #define __bi_decl(name, bi, section_prefix, attr) static const attr __attribute__((section(section_prefix __STRING(name)))) struct _binary_info_core *name = bi
15 #define __bi_lineno_var_name __CONCAT(__bi_, __LINE__)
16 #define __bi_ptr_lineno_var_name __CONCAT(__bi_ptr, __LINE__)
17 #define __bi_enclosure_check_lineno_var_name __CONCAT(_error_bi_is_missing_enclosing_decl_,__LINE__)
18 #define __bi_mark_enclosure static const __unused int __bi_enclosure_check_lineno_var_name=0;
19 #if !defined(__GNUC__) || __cplusplus || __GNUC__ >= 8
20 #define __bi_enclosure_check(x) (x + __bi_enclosure_check_lineno_var_name)
21 #else
22 // skip the version check on older GCC non C++, as it doesn't compile.. this is only here to catch the
23 // user accidentally forgetting to enclose the binary item with bi_decl
24 #define __bi_enclosure_check(x) (x)
25 #endif
26 /**
27  * Declare some binary information that will be included if the contain source file/line is compiled into the binary
28  */
29 #define bi_decl(_decl) __bi_mark_enclosure _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.keep.", __used);
30 /**
31  * Declare some binary information that will be included if the function containing the decl is linked into the binary.
32  * The SDK uses --gc-sections, so functions that are never called will be removed by the linker, and any associated
33  * binary information declared this way will also be stripped
34  */
35 #define bi_decl_if_func_used(_decl) ({__bi_mark_enclosure _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.", ); *(volatile uint8_t *)&__bi_ptr_lineno_var_name;});
36 
37 #define bi_decl_with_attr(_decl, _attr) __bi_mark_enclosure _attr _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.keep.", __used);
38 #define bi_decl_if_func_used_with_attr(_decl, _attr) ({__bi_mark_enclosure _attr _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.", ); *(volatile uint8_t *)&__bi_ptr_lineno_var_name;});
39 #else
40 #define __bi_decl(bi, name, attr)
41 #define bi_decl_with_attr(_decl, _attr)
42 #define bi_decl(_decl)
43 #define bi_decl_if_func_used_with_attr(_decl, _attr) ((void)0);
44 #define bi_decl_if_func_used(_decl) ((void)0);
45 #endif
46 
47 #define bi_int(_tag, _id, _value) \
48      static const struct _binary_info_id_and_int __bi_lineno_var_name = { \
49         .core = { \
50             .type = __bi_enclosure_check(BINARY_INFO_TYPE_ID_AND_INT), \
51             .tag = _tag, \
52         },\
53         .id = _id, \
54         .value = _value \
55     };
56 
57 #define bi_string(_tag, _id, _value) \
58     static const struct _binary_info_id_and_string __bi_lineno_var_name = { \
59         .core = { \
60             .type = __bi_enclosure_check(BINARY_INFO_TYPE_ID_AND_STRING), \
61             .tag = _tag, \
62         },\
63         .id = _id, \
64         .value = _value, \
65     }
66 
67 #define bi_block_device(_tag, _name, _address, _size, _extra, _flags) \
68     static const struct _binary_info_block_device __bi_lineno_var_name = { \
69         .core = { \
70             .type = __bi_enclosure_check(BINARY_INFO_TYPE_BLOCK_DEVICE), \
71             .tag = _tag, \
72         },\
73         .name = _name, \
74         .address = _address, \
75         .size = _size, \
76         .extra = _extra, \
77         .flags = _flags, \
78     }
79 
80 #define __bi_encoded_pins_with_func(_encoding) \
81     static const struct _binary_info_pins_with_func __bi_lineno_var_name = { \
82         .core = { \
83             .type = __bi_enclosure_check(BINARY_INFO_TYPE_PINS_WITH_FUNC), \
84             .tag = BINARY_INFO_TAG_RASPBERRY_PI, \
85         },\
86         .pin_encoding = _encoding \
87     }
88 
89 #define __bi_pins_with_name(_mask, _label) \
90     static const struct _binary_info_pins_with_name __bi_lineno_var_name = { \
91         .core = { \
92             .type = __bi_enclosure_check(BINARY_INFO_TYPE_PINS_WITH_NAME), \
93             .tag = BINARY_INFO_TAG_RASPBERRY_PI, \
94         },\
95         .pin_mask = _mask, \
96         .label = _label \
97     }
98 
99 #define __bi_named_group(_parent_tag, _parent_id, _group_tag, _group_id, _label, _flags) \
100 static const struct _binary_info_named_group __bi_lineno_var_name = { \
101         .core = { \
102             .type = __bi_enclosure_check(BINARY_INFO_TYPE_NAMED_GROUP), \
103             .tag = _parent_tag, \
104         },\
105         .parent_id = _parent_id, \
106         .group_tag = _group_tag, \
107         .flags = _flags, \
108         .group_id = _group_id, \
109         .label = _label \
110     }
111 
112 #define bi_binary_end(end) bi_int(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_BINARY_END, end)
113 #define bi_program_name(name) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_NAME, name)
114 #define bi_program_description(description) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_DESCRIPTION, description)
115 #define bi_program_version_string(version_string) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_VERSION_STRING, version_string)
116 #define bi_program_build_date_string(date_string) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_BUILD_DATE_STRING, date_string)
117 #define bi_program_url(url) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_URL, url)
118 // multiple of these may be added
119 #define bi_program_feature(feature) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_FEATURE, feature)
120 #define bi_program_build_attribute(attr) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_BUILD_ATTRIBUTE, attr)
121 #define bi_program_feature_group(tag, id, name) __bi_named_group(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_FEATURE, tag, id, name, 0)
122 #define bi_program_feature_group_with_flags(tag, id, name, flags) __bi_named_group(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_FEATURE, tag, id, name, flags)
123 
124 #define bi_1pin_with_func(p0, func)                  __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p0) << 12))
125 #define bi_2pins_with_func(p0, p1, func)             __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p1) << 12) | ((p1) << 17))
126 #define bi_3pins_with_func(p0, p1, p2, func)         __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p1) << 12) | ((p2) << 17) | ((p2) << 22))
127 #define bi_4pins_with_func(p0, p1, p2, p3, func)     __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p1) << 12) | ((p2) << 17) | ((p3) << 22) | ((p3) << 27))
128 #define bi_5pins_with_func(p0, p1, p2, p3, p4, func) __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p1) << 12) | ((p2) << 17) | ((p3) << 22) | ((p4) << 27))
129 #define bi_pin_range_with_func(plo, phi, func)       __bi_encoded_pins_with_func(BI_PINS_ENCODING_RANGE | ((func << 3)) | ((plo) << 7) | ((phi) << 12))
130 
131 #define bi_pin_mask_with_name(pmask, label)          __bi_pins_with_name((pmask), (label))
132 // names are sperated by | ... i.e. "name1|name2|name3"
133 #define bi_pin_mask_with_names(pmask, label)          __bi_pins_with_name((pmask), (label))
134 #define bi_1pin_with_name(p0, name)                   bi_pin_mask_with_name(1u << (p0), name)
135 #define bi_2pins_with_names(p0, name0, p1, name1)     bi_pin_mask_with_names((1u << (p0)) | (1u << (p1)), name0 "|" name1)
136 #define bi_3pins_with_names(p0, name0, p1, name1, p2, name2)  bi_pin_mask_with_names((1u << (p0)) | (1u << (p1)) | (1u << (p2)), name0 "|" name1 "|" name2)
137 #define bi_4pins_with_names(p0, name0, p1, name1, p2, name2, p3, name3)  bi_pin_mask_with_names((1u << (p0)) | (1u << (p1)) | (1u << (p2)) | (1u << (p3)), name0 "|" name1 "|" name2 "|" name3)
138 
139 #endif