blob: 73ba80dd59d11cc71c6a857f7d15ec28ec58b220 [file] [log] [blame]
Scott James Remnant81713a32021-07-22 13:09:18 -07001.. _module-pw_boot_cortex_m:
Armando Montanez70095662020-01-09 14:25:04 -08002
Scott James Remnant81713a32021-07-22 13:09:18 -07003----------------
4pw_boot_cortex_m
5----------------
Armando Montanez70095662020-01-09 14:25:04 -08006
Scott James Remnant81713a32021-07-22 13:09:18 -07007The ARM Cortex-M boot module provides a linker script and some early
8initialization of static memory regions and C++ constructors. This is enough to
9get many ARMv7-M and ARMv8-M cores booted and ready to run C++ code.
Armando Montanez70095662020-01-09 14:25:04 -080010
11This module is currently designed to support a very minimal device memory layout
12configuration:
13
14 - One contiguous region for RAM.
15 - One contiguous region for flash.
16 - Static, in-flash vector table at the default location expected by the SoC.
17
18Note that this module is not yet particularly suited for projects that utilize
19a bootloader, as it's relatively opinionated regarding where code is stored.
20
21.. warning::
22 This module is currently NOT stable! Depending on this module may cause
23 breakages as this module is updated.
24
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -070025Sequence
26========
27
Scott James Remnant81713a32021-07-22 13:09:18 -070028The high level pw_boot_cortex_m boot sequence looks like the following
29pseudo-code invocation of the user-implemented functions:
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -070030
31.. code:: cpp
32
33 void pw_boot_Entry() { // Boot entry point.
Scott James Remnant4d604692021-07-20 17:35:49 -070034 // Interrupts disabled.
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -070035 pw_boot_PreStaticMemoryInit(); // User-implemented function.
36 // Static memory initialization.
Scott James Remnant4d604692021-07-20 17:35:49 -070037 // Interrupts enabled.
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -070038 pw_boot_PreStaticConstructorInit(); // User-implemented function.
39 // C++ static constructors are invoked.
40 pw_boot_PreMainInit(); // User-implemented function.
41 main(); // User-implemented function.
Ewout van Bekkum738f42c2020-08-24 12:55:13 -070042 pw_boot_PostMain(); // User-implemented function.
43 PW_UNREACHABLE;
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -070044 }
45
Armando Montanez70095662020-01-09 14:25:04 -080046Setup
47=====
48
Scott James Remnant81713a32021-07-22 13:09:18 -070049Processor Selection
50-------------------
51Set the ``pw_boot_BACKEND`` variable to the appropriate target for the processor
52in use.
53
54 - ``pw_boot_cortex_m:armv7m`` for ARMv7-M cores.
55
Scott James Remnanta19b7ac2021-07-20 17:41:51 -070056 - ``pw_boot_cortex_m:armv8m`` for ARMv8-M cores. This sets the MSPLIM register
57 so that the main stack pointer (MSP) cannot descend outside the bounds of the
58 main stack defined in the linker script. The MSP of the entry point is also
59 adjusted to be within the bounds.
Scott James Remnant259a6fe2021-07-22 13:13:15 -070060
Armando Montanez70095662020-01-09 14:25:04 -080061User-Implemented Functions
62--------------------------
Ewout van Bekkum738f42c2020-08-24 12:55:13 -070063This module expects all of these extern "C" functions to be defined outside this
64module:
Armando Montanez70095662020-01-09 14:25:04 -080065
66 - ``int main()``: This is where applications reside.
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -070067 - ``void pw_boot_PreStaticMemoryInit()``: This function executes just before
Shiva Rajagopal9e516562021-05-11 17:04:15 -070068 static memory has been zeroed and static data is intialized. This function
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -070069 should set up any early initialization that should be done before static
70 memory is initialized, such as:
71
Scott James Remnant4d604692021-07-20 17:35:49 -070072 - Setup the interrupt vector table and VTOR if required.
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -070073 - Enabling the FPU or other coprocessors.
74 - Opting into extra restrictions such as disabling unaligned access to ensure
75 the restrictions are active during static RAM initialization.
76 - Initial CPU clock, flash, and memory configurations including potentially
77 enabling extra memory regions with .bss and .data sections, such as SDRAM
78 or backup powered SRAM.
79 - Fault handler initialization if required before static memory
80 initialization.
81
82 .. warning::
83 Code running in this hook is violating the C spec as static values are not
84 yet initialized, meaning they have not been loaded (.data) nor
85 zero-initialized (.bss).
86
Scott James Remnant4d604692021-07-20 17:35:49 -070087 Interrupts are disabled until after this function returns.
88
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -070089 - ``void pw_boot_PreStaticConstructorInit()``: This function executes just
90 before C++ static constructors are called. At this point, other static memory
91 has been zero or data initialized. This function should set up any early
92 initialization that should be done before C++ static constructors are run,
93 such as:
94
95 - Run time dependencies such as Malloc, and ergo sometimes the RTOS.
96 - Persistent memory that survives warm reboots.
97 - Enabling the MPU to catch nullptr dereferences during construction.
98 - Main stack watermarking.
99 - Further fault handling configuration necessary for your platform which
100 were not safe before pw_boot_PreStaticRamInit().
101 - Boot count and/or boot session UUID management.
102
103 - ``void pw_boot_PreMainInit()``: This function executes just before main, and
Armando Montanez70095662020-01-09 14:25:04 -0800104 can be used for any device initialization that isn't application specific.
105 Depending on your platform, this might be turning on a UART, setting up
106 default clocks, etc.
107
Ewout van Bekkum738f42c2020-08-24 12:55:13 -0700108 - ``PW_NO_RETURN void pw_boot_PostMain()``: This function executes after main
109 has returned. This could be used for device specific teardown such as an
110 infinite loop, soft reset, or QEMU shutdown. In addition, if relevant for
111 your application, this would be the place to invoke the global static
112 destructors. This function must not return!
113
114
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -0700115If any of these functions are unimplemented, executables will encounter a link
116error.
Armando Montanez70095662020-01-09 14:25:04 -0800117
118Required Configs
119----------------
120This module has a number of required configuration options that mold the linker
Scott James Remnant81713a32021-07-22 13:09:18 -0700121script to fit to a wide variety of ARM Cortex-M SoCs.
Armando Montanez70095662020-01-09 14:25:04 -0800122
123Vector Table
124------------
Scott James Remnant81713a32021-07-22 13:09:18 -0700125Targets using ``pw_boot_cortex_m`` will need to provide an ARMv7-M interrupt
Armando Montanez0054a9b2020-03-13 13:06:24 -0700126vector table (ARMv7-M Architecture Reference Manual DDI 0403E.b section B1.5.2
127and B1.5.3). This is done by storing an array into the ``.vector_table``
128section, and properly configuring ``PW_BOOT_VECTOR_TABLE_*`` preprocessor
Armando Montanez70095662020-01-09 14:25:04 -0800129defines to cover the address region your SoC expects the vector table to be
130located at (often the beginning of the flash region). If using a bootloader,
131ensure VTOR (Vector Table Offset Register) is configured to point to the vector
132table. Otherwise, refer to the hardware vendor's documentation to determine
133where the vector table should be located such that it resides where VTOR is
134initialized to by default.
135
136Example vector table:
137
138.. code-block:: cpp
139
140 typedef void (*InterruptHandler)();
141
142 PW_KEEP_IN_SECTION(".vector_table")
143 const InterruptHandler vector_table[] = {
144 // The starting location of the stack pointer.
145 // This address is NOT an interrupt handler/function pointer, it is simply
146 // the address that the main stack pointer should be initialized to. The
147 // value is reinterpret casted because it needs to be in the vector table.
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -0700148 [0] = reinterpret_cast<InterruptHandler>(&pw_boot_stack_high_addr),
Armando Montanez70095662020-01-09 14:25:04 -0800149
150 // Reset handler, dictates how to handle reset interrupt. This is the
151 // address that the Program Counter (PC) is initialized to at boot.
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -0700152 [1] = pw_boot_Entry,
Armando Montanez70095662020-01-09 14:25:04 -0800153
154 // NMI handler.
155 [2] = DefaultFaultHandler,
156 // HardFault handler.
157 [3] = DefaultFaultHandler,
158 ...
159 };
160
161Usage
162=====
163
164Publicly exported symbols
165-------------------------
166The linker script provided by this module exports a number of symbols that
167may be used to retrieve the locations of specific memory regions at runtime.
168These symbols are declared as ``uint8_t`` variables. The variables themselves
169do not contain the addresses, they only reside at the memory location they
170reference. To retrieve the memory locations, simply take the reference of the
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -0700171symbol (e.g. ``&pw_boot_vector_table_addr``).
Armando Montanez70095662020-01-09 14:25:04 -0800172
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -0700173``pw_boot_heap_[low/high]_addr``: Beginning and end of the memory range of the heap.
Armando Montanez70095662020-01-09 14:25:04 -0800174These addresses may be identical, indicating a heap with a size of zero bytes.
175
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -0700176``pw_boot_stack_[low/high]_addr``: Beginning and end of the memory range of the main
Armando Montanez70095662020-01-09 14:25:04 -0800177stack. This might not be the only stack in the system.
178
Ewout van Bekkumfff82ec2020-08-21 15:54:28 -0700179``pw_boot_vector_table_addr``: Beginning of the ARMv7-M interrupt vector table.
Armando Montanez70095662020-01-09 14:25:04 -0800180
181Configuration
182=============
Armando Montaneza761e322020-06-15 16:30:40 -0700183These configuration options can be controlled by appending list items to
Scott James Remnant81713a32021-07-22 13:09:18 -0700184``pw_boot_cortex_m_LINK_CONFIG_DEFINES`` as part of a Pigweed target
Armando Montaneza761e322020-06-15 16:30:40 -0700185configuration.
Armando Montanez70095662020-01-09 14:25:04 -0800186
Armando Montanez0054a9b2020-03-13 13:06:24 -0700187``PW_BOOT_HEAP_SIZE`` (required):
Armando Montanez70095662020-01-09 14:25:04 -0800188How much memory (in bytes) to reserve for the heap. This can be zero.
189
Armando Montanez0054a9b2020-03-13 13:06:24 -0700190``PW_BOOT_MIN_STACK_SIZE`` (required):
Armando Montanez70095662020-01-09 14:25:04 -0800191The minimum size reserved for the main stack. If statically allocated memory
192begins to cut into the minimum, a link error will be emitted.
193
Armando Montanez0054a9b2020-03-13 13:06:24 -0700194``PW_BOOT_FLASH_BEGIN`` (required):
Armando Montanez70095662020-01-09 14:25:04 -0800195The start address of the MCU's flash region. This region must NOT include the
Armando Montanez92212132020-01-16 15:03:20 -0800196vector table. (i.e. if the VECTOR_TABLE is in flash, the flash region
Armando Montanez70095662020-01-09 14:25:04 -0800197should begin *after* the vtable)
198
Armando Montanez0054a9b2020-03-13 13:06:24 -0700199``PW_BOOT_FLASH_SIZE`` (required):
Armando Montanez70095662020-01-09 14:25:04 -0800200Size of the flash region in bytes.
201
Armando Montanez0054a9b2020-03-13 13:06:24 -0700202``PW_BOOT_RAM_BEGIN`` (required):
Armando Montanez70095662020-01-09 14:25:04 -0800203The start address of the MCU's RAM region.
204
Armando Montanez0054a9b2020-03-13 13:06:24 -0700205``PW_BOOT_RAM_SIZE`` (required):
Armando Montanez70095662020-01-09 14:25:04 -0800206Size of the RAM region in bytes.
207
Armando Montanez0054a9b2020-03-13 13:06:24 -0700208``PW_BOOT_VECTOR_TABLE_BEGIN`` (required):
Armando Montanez70095662020-01-09 14:25:04 -0800209Address the target MCU expects the link-time vector table to be located at. This
210is typically the beginning of the flash region. While the vector table may be
211changed later in the boot process, a minimal vector table MUST be present for
212the MCU to operate as expected.
213
Armando Montanez0054a9b2020-03-13 13:06:24 -0700214``PW_BOOT_VECTOR_TABLE_SIZE`` (required):
Armando Montanez70095662020-01-09 14:25:04 -0800215Number of bytes to reserve for the ARMv7-M vector table.
216
Scott James Remnant1fee0f42021-07-20 17:19:05 -0700217Alternatively the linker script can be replaced by setting
218``pw_boot_cortex_m_LINKER_SCRIPT`` to a valid ``pw_linker_script`` target
219as part of a Pigweed target configuration.
220
Armando Montanez70095662020-01-09 14:25:04 -0800221Dependencies
222============
Armando Montanez0054a9b2020-03-13 13:06:24 -0700223 * ``pw_preprocessor`` module