1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _PICO_PLATFORM_SECTION_MACROS_H
8 #define _PICO_PLATFORM_SECTION_MACROS_H
9 
10 #ifndef __ASSEMBLER__
11 
12 /*! \brief Section attribute macro for placement in RAM after the `.data` section
13  *  \ingroup pico_platform
14  *
15  * For example a 400 element `uint32_t` array placed after the .data section
16  *
17  *     uint32_t __after_data("my_group_name") a_big_array[400];
18  *
19  * The section attribute is `.after_data.<group>`
20  *
21  * \param group a string suffix to use in the section name to distinguish groups that can be linker
22  *              garbage-collected independently
23  */
24 #ifndef __after_data
25 #define __after_data(group) __attribute__((section(".after_data." group)))
26 #endif
27 
28 /*! \brief Section attribute macro for placement not in flash (i.e in RAM)
29  *  \ingroup pico_platform
30  *
31  * For example a 3 element `uint32_t` array placed in RAM (even though it is `static const`)
32  *
33  *     static const uint32_t __not_in_flash("my_group_name") an_array[3];
34  *
35  * The section attribute is `.time_critical.<group>`
36  *
37  * \param group a string suffix to use in the section name to distinguish groups that can be linker
38  *              garbage-collected independently
39  */
40 #ifndef __not_in_flash
41 #define __not_in_flash(group) __attribute__((section(".time_critical." group)))
42 #endif
43 
44 /*! \brief Section attribute macro for placement in the SRAM bank 4 (known as "scratch X")
45  *  \ingroup pico_platform
46  *
47  * Scratch X is commonly used for critical data and functions accessed only by one core (when only
48  * one core is accessing the RAM bank, there is no opportunity for stalls)
49  *
50  * For example a `uint32_t` variable placed in "scratch X"
51  *
52  *     uint32_t __scratch_x("my_group_name") foo = 23;
53  *
54  * The section attribute is `.scratch_x.<group>`
55  *
56  * \param group a string suffix to use in the section name to distinguish groups that can be linker
57  *              garbage-collected independently
58  */
59 #ifndef __scratch_x
60 #define __scratch_x(group) __attribute__((section(".scratch_x." group)))
61 #endif
62 
63 /*! \brief Section attribute macro for placement in the SRAM bank 5 (known as "scratch Y")
64  *  \ingroup pico_platform
65  *
66  * Scratch Y is commonly used for critical data and functions accessed only by one core (when only
67  * one core is accessing the RAM bank, there is no opportunity for stalls)
68  *
69  * For example a `uint32_t` variable placed in "scratch Y"
70  *
71  *     uint32_t __scratch_y("my_group_name") foo = 23;
72  *
73  * The section attribute is `.scratch_y.<group>`
74  *
75  * \param group a string suffix to use in the section name to distinguish groups that can be linker
76  *              garbage-collected independently
77  */
78 #ifndef __scratch_y
79 #define __scratch_y(group) __attribute__((section(".scratch_y." group)))
80 #endif
81 
82 /*! \brief Section attribute macro for data that is to be left uninitialized
83  *  \ingroup pico_platform
84  *
85  * Data marked this way will retain its value across a reset (normally uninitialized data - in the .bss
86  * section) is initialized to zero during runtime initialization
87  *
88  * For example a `uint32_t` foo that will retain its value if the program is restarted by reset.
89  *
90  *     uint32_t __uninitialized_ram(foo);
91  *
92  * The section attribute is `.uninitialized_data.<group>`
93  *
94  * \param group a string suffix to use in the section name to distinguish groups that can be linker
95  *              garbage-collected independently
96  */
97 #ifndef __uninitialized_ram
98 #define __uninitialized_ram(group) __attribute__((section(".uninitialized_data." #group))) group
99 #endif
100 
101 /*! \brief Section attribute macro for placement in flash even in a COPY_TO_RAM binary
102  *  \ingroup pico_platform
103  *
104  * For example a `uint32_t` variable explicitly placed in flash (it will hard fault if you attempt to write it!)
105  *
106  *     uint32_t __in_flash("my_group_name") foo = 23;
107  *
108  * The section attribute is `.flashdata.<group>`
109  *
110  * \param group a string suffix to use in the section name to distinguish groups that can be linker
111  *              garbage-collected independently
112  */
113 #ifndef __in_flash
114 #define __in_flash(group) __attribute__((section(".flashdata." group)))
115 #endif
116 
117 /*! \brief Indicates a function should not be stored in flash
118  *  \ingroup pico_platform
119  *
120  * Decorates a function name, such that the function will execute from RAM (assuming it is not inlined
121  * into a flash function by the compiler)
122  *
123  * For example a function called my_func taking an int parameter:
124  *
125  *     void __not_in_flash_func(my_func)(int some_arg) {
126  *
127  * The function is placed in the `.time_critical.<func_name>` linker section
128  *
129  * \see __no_inline_not_in_flash_func
130  */
131 #ifndef __not_in_flash_func
132 #define __not_in_flash_func(func_name) __not_in_flash(__STRING(func_name)) func_name
133 #endif
134 
135 /*! \brief Indicates a function is time/latency critical and should not run from flash
136  *  \ingroup pico_platform
137  *
138  * Decorates a function name, such that the function will execute from RAM (assuming it is not inlined
139  * into a flash function by the compiler) to avoid possible flash latency. Currently this macro is identical
140  * in implementation to `__not_in_flash_func`, however the semantics are distinct and a `__time_critical_func`
141  * may in the future be treated more specially to reduce the overhead when calling such function from a flash
142  * function.
143  *
144  * For example a function called my_func taking an int parameter:
145  *
146  *     void __time_critical_func(my_func)(int some_arg) {
147  *
148  * The function is placed in the `.time_critical.<func_name>` linker section
149  *
150  * \see __not_in_flash_func
151  */
152 #ifndef __time_critical_func
153 #define __time_critical_func(func_name) __not_in_flash_func(func_name)
154 #endif
155 
156 /*! \brief Indicate a function should not be stored in flash and should not be inlined
157  *  \ingroup pico_platform
158  *
159  * Decorates a function name, such that the function will execute from RAM, explicitly marking it as
160  * noinline to prevent it being inlined into a flash function by the compiler
161  *
162  * For example a function called my_func taking an int parameter:
163  *
164  *     void __no_inline_not_in_flash_func(my_func)(int some_arg) {
165  *
166  * The function is placed in the `.time_critical.<func_name>` linker section
167  */
168 #ifndef __no_inline_not_in_flash_func
169 #define __no_inline_not_in_flash_func(func_name) __noinline __not_in_flash_func(func_name)
170 #endif
171 
172 #else
173 
174 #ifndef RAM_SECTION_NAME
175 #define RAM_SECTION_NAME(x) .time_critical.##x
176 #endif
177 
178 #ifndef SECTION_NAME
179 #define SECTION_NAME(x) .text.##x
180 #endif
181 
182 #endif // !__ASSEMBLER__
183 
184 #endif
185 
186