Armando Montanez | 7009566 | 2020-01-09 14:25:04 -0800 | [diff] [blame] | 1 | .. _chapter-pw-boot-armv7m: |
| 2 | |
| 3 | .. default-domain:: cpp |
| 4 | |
| 5 | .. highlight:: sh |
| 6 | |
| 7 | -------------- |
| 8 | pw_boot_armv7m |
| 9 | -------------- |
| 10 | |
| 11 | The ARMv7-M boot module provides a linker script and some early initialization |
| 12 | of static memory regions and C++ constructors. This is enough to get many |
| 13 | ARMv7-M cores booted and ready to run C++ code. |
| 14 | |
| 15 | This module is currently designed to support a very minimal device memory layout |
| 16 | configuration: |
| 17 | |
| 18 | - One contiguous region for RAM. |
| 19 | - One contiguous region for flash. |
| 20 | - Static, in-flash vector table at the default location expected by the SoC. |
| 21 | |
| 22 | Note that this module is not yet particularly suited for projects that utilize |
| 23 | a bootloader, as it's relatively opinionated regarding where code is stored. |
| 24 | |
| 25 | .. warning:: |
| 26 | This module is currently NOT stable! Depending on this module may cause |
| 27 | breakages as this module is updated. |
| 28 | |
| 29 | Setup |
| 30 | ===== |
| 31 | |
| 32 | User-Implemented Functions |
| 33 | -------------------------- |
| 34 | This module expects two extern "C" functions to be defined outside this module. |
| 35 | |
| 36 | - ``int main()``: This is where applications reside. |
| 37 | - ``void pw_PreMainInit()``: This function executes just before main, and |
| 38 | can be used for any device initialization that isn't application specific. |
| 39 | Depending on your platform, this might be turning on a UART, setting up |
| 40 | default clocks, etc. |
| 41 | |
| 42 | If either of these functions are unimplemented, executables will encounter a |
| 43 | link error. |
| 44 | |
| 45 | Required Configs |
| 46 | ---------------- |
| 47 | This module has a number of required configuration options that mold the linker |
| 48 | script to fit to a wide variety of ARMv7-M SoCs. The ``pw_boot_armv7m_config`` |
| 49 | GN variable has a ``defines`` member that can be used to modify these linker |
| 50 | script options. See the documentation section on configuration for information |
| 51 | regarding which configuration options are required. |
| 52 | |
| 53 | Vector Table |
| 54 | ------------ |
| 55 | Targets using pw_boot_armv7m will need to provide an ARMv7-M interrupt vector |
| 56 | table (ARMv7-M Architecture Reference Manual DDI 0403E.b section B1.5.2 and |
| 57 | B1.5.3). This is done by storing an array into the ``.vector_table`` section, |
Armando Montanez | 9221213 | 2020-01-16 15:03:20 -0800 | [diff] [blame] | 58 | and properly configuring ``PW_BOOT_VECTOR_TABLE_*`` preprocessor |
Armando Montanez | 7009566 | 2020-01-09 14:25:04 -0800 | [diff] [blame] | 59 | defines to cover the address region your SoC expects the vector table to be |
| 60 | located at (often the beginning of the flash region). If using a bootloader, |
| 61 | ensure VTOR (Vector Table Offset Register) is configured to point to the vector |
| 62 | table. Otherwise, refer to the hardware vendor's documentation to determine |
| 63 | where the vector table should be located such that it resides where VTOR is |
| 64 | initialized to by default. |
| 65 | |
| 66 | Example vector table: |
| 67 | |
| 68 | .. code-block:: cpp |
| 69 | |
| 70 | typedef void (*InterruptHandler)(); |
| 71 | |
| 72 | PW_KEEP_IN_SECTION(".vector_table") |
| 73 | const InterruptHandler vector_table[] = { |
| 74 | // The starting location of the stack pointer. |
| 75 | // This address is NOT an interrupt handler/function pointer, it is simply |
| 76 | // the address that the main stack pointer should be initialized to. The |
| 77 | // value is reinterpret casted because it needs to be in the vector table. |
| 78 | [0] = reinterpret_cast<InterruptHandler>(&pw_stack_high_addr), |
| 79 | |
| 80 | // Reset handler, dictates how to handle reset interrupt. This is the |
| 81 | // address that the Program Counter (PC) is initialized to at boot. |
| 82 | [1] = pw_BootEntry, |
| 83 | |
| 84 | // NMI handler. |
| 85 | [2] = DefaultFaultHandler, |
| 86 | // HardFault handler. |
| 87 | [3] = DefaultFaultHandler, |
| 88 | ... |
| 89 | }; |
| 90 | |
| 91 | Usage |
| 92 | ===== |
| 93 | |
| 94 | Publicly exported symbols |
| 95 | ------------------------- |
| 96 | The linker script provided by this module exports a number of symbols that |
| 97 | may be used to retrieve the locations of specific memory regions at runtime. |
| 98 | These symbols are declared as ``uint8_t`` variables. The variables themselves |
| 99 | do not contain the addresses, they only reside at the memory location they |
| 100 | reference. To retrieve the memory locations, simply take the reference of the |
| 101 | symbol (e.g. ``&pw_vector_table_addr``). |
| 102 | |
| 103 | ``pw_heap_[low/high]_addr``: Beginning and end of the memory range of the heap. |
| 104 | These addresses may be identical, indicating a heap with a size of zero bytes. |
| 105 | |
| 106 | ``pw_stack_[low/high]_addr``: Beginning and end of the memory range of the main |
| 107 | stack. This might not be the only stack in the system. |
| 108 | |
| 109 | ``pw_vector_table_addr``: Beginning of the ARMv7-M interrupt vector table. |
| 110 | |
| 111 | Configuration |
| 112 | ============= |
| 113 | These configuration options can be controlled by appending to |
| 114 | ``pw_boot_armv7m_config.defines`` as part of a Pigweed target config file. |
| 115 | |
| 116 | **PW_BOOT_HEAP_SIZE** (required): |
| 117 | How much memory (in bytes) to reserve for the heap. This can be zero. |
| 118 | |
| 119 | **PW_BOOT_MIN_STACK_SIZE** (required): |
| 120 | The minimum size reserved for the main stack. If statically allocated memory |
| 121 | begins to cut into the minimum, a link error will be emitted. |
| 122 | |
| 123 | **PW_BOOT_FLASH_BEGIN** (required): |
| 124 | The start address of the MCU's flash region. This region must NOT include the |
Armando Montanez | 9221213 | 2020-01-16 15:03:20 -0800 | [diff] [blame] | 125 | vector table. (i.e. if the VECTOR_TABLE is in flash, the flash region |
Armando Montanez | 7009566 | 2020-01-09 14:25:04 -0800 | [diff] [blame] | 126 | should begin *after* the vtable) |
| 127 | |
| 128 | **PW_BOOT_FLASH_SIZE** (required): |
| 129 | Size of the flash region in bytes. |
| 130 | |
| 131 | **PW_BOOT_RAM_BEGIN** (required): |
| 132 | The start address of the MCU's RAM region. |
| 133 | |
| 134 | **PW_BOOT_RAM_SIZE** (required): |
| 135 | Size of the RAM region in bytes. |
| 136 | |
Armando Montanez | 9221213 | 2020-01-16 15:03:20 -0800 | [diff] [blame] | 137 | **PW_BOOT_VECTOR_TABLE_BEGIN** (required): |
Armando Montanez | 7009566 | 2020-01-09 14:25:04 -0800 | [diff] [blame] | 138 | Address the target MCU expects the link-time vector table to be located at. This |
| 139 | is typically the beginning of the flash region. While the vector table may be |
| 140 | changed later in the boot process, a minimal vector table MUST be present for |
| 141 | the MCU to operate as expected. |
| 142 | |
Armando Montanez | 9221213 | 2020-01-16 15:03:20 -0800 | [diff] [blame] | 143 | **PW_BOOT_VECTOR_TABLE_SIZE** (required): |
Armando Montanez | 7009566 | 2020-01-09 14:25:04 -0800 | [diff] [blame] | 144 | Number of bytes to reserve for the ARMv7-M vector table. |
| 145 | |
| 146 | Dependencies |
| 147 | ============ |
| 148 | * pw_preprocessor module |