xref: /aosp_15_r20/external/pigweed/pw_boot_cortex_m/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1.. _module-pw_boot_cortex_m:
2
3----------------
4pw_boot_cortex_m
5----------------
6.. pigweed-module::
7   :name: pw_boot_cortex_m
8
9The ARM Cortex-M boot module provides a linker script and some early
10initialization of static memory regions and C++ constructors. This is enough to
11get many ARMv7-M and ARMv8-M cores booted and ready to run C++ code.
12
13This module is currently designed to support a very minimal device memory layout
14configuration:
15
16- One contiguous region for RAM.
17- One contiguous region for flash.
18- Static, in-flash vector table at the default location expected by the SoC.
19
20Note that this module is not yet particularly suited for projects that utilize
21a bootloader, as it's relatively opinionated regarding where code is stored.
22
23.. warning::
24
25   This module is currently NOT stable! Depending on this module may cause
26   breakages as this module is updated.
27
28Sequence
29========
30
31The high level pw_boot_cortex_m boot sequence looks like the following
32pseudo-code invocation of the user-implemented functions:
33
34.. code-block:: cpp
35
36   void pw_boot_Entry() {  // Boot entry point.
37     // Set VTOR.
38     // Interrupts disabled.
39     pw_boot_PreStaticMemoryInit();  // User-implemented function.
40     // Static memory initialization.
41     // Interrupts enabled.
42     pw_boot_PreStaticConstructorInit();  // User-implemented function.
43     // C++ static constructors are invoked.
44     pw_boot_PreMainInit();  // User-implemented function.
45     main();  // User-implemented function.
46     pw_boot_PostMain();  // User-implemented function.
47     PW_UNREACHABLE;
48   }
49
50Setup
51=====
52
53Processor Selection
54-------------------
55Set the ``pw_boot_BACKEND`` variable to the appropriate target for the processor
56in use.
57
58- ``pw_boot_cortex_m:armv7m`` for ARMv7-M cores.
59
60- ``pw_boot_cortex_m:armv8m`` for ARMv8-M cores. This sets the MSPLIM register
61  so that the main stack pointer (MSP) cannot descend outside the bounds of the
62  main stack defined in the linker script. The MSP of the entry point is also
63  adjusted to be within the bounds.
64
65User-Implemented Functions
66--------------------------
67This module expects all of these extern "C" functions to be defined outside this
68module:
69
70- ``int main()``: This is where applications reside.
71- ``void pw_boot_PreStaticMemoryInit()``: This function executes just before
72  static memory has been zeroed and static data is intialized. This function
73  should set up any early initialization that should be done before static
74  memory is initialized, such as:
75
76  - Setup the interrupt vector table and VTOR if required.
77  - Enabling the FPU or other coprocessors.
78  - Opting into extra restrictions such as disabling unaligned access to ensure
79    the restrictions are active during static RAM initialization.
80  - Initial CPU clock, flash, and memory configurations including potentially
81    enabling extra memory regions with .bss and .data sections, such as SDRAM
82    or backup powered SRAM.
83  - Fault handler initialization if required before static memory
84    initialization.
85
86  .. warning::
87
88     Code running in this hook is violating the C spec as static values are not
89     yet initialized, meaning they have not been loaded (.data) nor
90     zero-initialized (.bss).
91
92     Interrupts are disabled until after this function returns.
93
94- ``void pw_boot_PreStaticConstructorInit()``: This function executes just
95  before C++ static constructors are called. At this point, other static memory
96  has been zero or data initialized. This function should set up any early
97  initialization that should be done before C++ static constructors are run,
98  such as:
99
100  - Run time dependencies such as Malloc, and ergo sometimes the RTOS.
101  - Persistent memory that survives warm reboots.
102  - Enabling the MPU to catch nullptr dereferences during construction.
103  - Main stack watermarking.
104  - Further fault handling configuration necessary for your platform which were
105    not safe before pw_boot_PreStaticRamInit().
106  - Boot count and/or boot session UUID management.
107
108- ``void pw_boot_PreMainInit()``: This function executes just before main, and
109  can be used for any device initialization that isn't application specific.
110  Depending on your platform, this might be turning on a UART, setting up
111  default clocks, etc.
112
113- ``PW_NO_RETURN void pw_boot_PostMain()``: This function executes after main
114  has returned. This could be used for device specific teardown such as an
115  infinite loop, soft reset, or QEMU shutdown. In addition, if relevant for your
116  application, this would be the place to invoke the global static
117  destructors. This function must not return!
118
119
120If any of these functions are unimplemented, executables will encounter a link
121error.
122
123Required Configs
124----------------
125This module has a number of required configuration options that mold the linker
126script to fit to a wide variety of ARM Cortex-M SoCs.
127
128Vector Table
129------------
130Targets using ``pw_boot_cortex_m`` will need to provide an ARMv7-M interrupt
131vector table (ARMv7-M Architecture Reference Manual DDI 0403E.b section B1.5.2
132and B1.5.3). This is done by storing an array into the ``.vector_table``
133section, and properly configuring ``PW_BOOT_VECTOR_TABLE_*`` preprocessor
134defines to cover the address region your SoC expects the vector table to be
135located at (often the beginning of the flash region). If using a bootloader,
136ensure VTOR (Vector Table Offset Register) is configured to point to the vector
137table, otherwise ensure that execution begins at ``pw_boot_Entry`` which will
138set VTOR as its first operation. If in doubt, refer to the hardware vendor's
139documentation to determine where the vector table and reset handler should be
140located.
141
142Example vector table:
143
144.. code-block:: cpp
145
146   typedef void (*InterruptHandler)();
147
148   PW_KEEP_IN_SECTION(".vector_table")
149   const InterruptHandler vector_table[] = {
150       // The starting location of the stack pointer.
151       // This address is NOT an interrupt handler/function pointer, it is simply
152       // the address that the main stack pointer should be initialized to. The
153       // value is reinterpret casted because it needs to be in the vector table.
154       [0] = reinterpret_cast<InterruptHandler>(&pw_boot_stack_high_addr),
155
156       // Reset handler, dictates how to handle reset interrupt. This is the
157       // address that the Program Counter (PC) is initialized to at boot.
158       [1] = pw_boot_Entry,
159
160       // NMI handler.
161       [2] = DefaultFaultHandler,
162       // HardFault handler.
163       [3] = DefaultFaultHandler,
164       ...
165   };
166
167Usage
168=====
169
170Publicly exported symbols
171-------------------------
172The linker script provided by this module exports a number of symbols that
173may be used to retrieve the locations of specific memory regions at runtime.
174These symbols are declared as ``uint8_t`` variables. The variables themselves
175do not contain the addresses, they only reside at the memory location they
176reference. To retrieve the memory locations, simply take the reference of the
177symbol (e.g. ``&pw_boot_vector_table_addr``).
178
179``pw_boot_heap_[low/high]_addr``: Beginning and end of the memory range of the heap.
180These addresses may be identical, indicating a heap with a size of zero bytes.
181
182``pw_boot_stack_[low/high]_addr``: Beginning and end of the memory range of the main
183stack. This might not be the only stack in the system.
184
185``pw_boot_vector_table_addr``: Beginning of the ARMv7-M interrupt vector table.
186
187Configuration
188=============
189These configuration options can be controlled by appending list items to
190``pw_boot_cortex_m_LINK_CONFIG_DEFINES`` as part of a Pigweed target
191configuration.
192
193``PW_BOOT_HEAP_SIZE`` (required):
194How much memory (in bytes) to reserve for the heap. This can be zero.
195
196``PW_BOOT_MIN_STACK_SIZE`` (required):
197The minimum size reserved for the main stack. If statically allocated memory
198begins to cut into the minimum, a link error will be emitted.
199
200``PW_BOOT_FLASH_BEGIN`` (required):
201The start address of the MCU's flash region. This region must NOT include the
202vector table. (i.e. if the VECTOR_TABLE is in flash, the flash region
203should begin *after* the vtable)
204
205``PW_BOOT_FLASH_SIZE`` (required):
206Size of the flash region in bytes.
207
208``PW_BOOT_RAM_BEGIN`` (required):
209The start address of the MCU's RAM region.
210
211``PW_BOOT_RAM_SIZE`` (required):
212Size of the RAM region in bytes.
213
214``PW_BOOT_VECTOR_TABLE_BEGIN`` (required):
215Address the target MCU expects the link-time vector table to be located at. This
216is typically the beginning of the flash region. While the vector table may be
217changed later in the boot process, a minimal vector table MUST be present for
218the MCU to operate as expected.
219
220``PW_BOOT_VECTOR_TABLE_SIZE`` (required):
221Number of bytes to reserve for the ARMv7-M vector table.
222
223Alternatively the linker script can be replaced by setting
224``pw_boot_cortex_m_LINKER_SCRIPT`` to a valid ``pw_linker_script`` target
225as part of a Pigweed target configuration.
226
227Dependencies
228============
229- :bdg-ref-primary-line:`module-pw_preprocessor`
230