1.. _arm_cortex_m_developer_guide: 2 3Arm Cortex-M Developer Guide 4############################ 5 6Overview 7******** 8 9This page contains detailed information about the status of the Arm Cortex-M 10architecture porting in the Zephyr RTOS and describes key aspects when 11developing Zephyr applications for Arm Cortex-M-based platforms. 12 13Key supported features 14********************** 15 16The table below summarizes the status of key OS features in the different 17Arm Cortex-M implementation variants. 18 19 20+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 21| | | **Processor families** | 22+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 23| Architecture variant | | Arm v6-M | Arm v7-M | Arm v8-M | Arm v8.1-M | 24+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 25| | | **M0/M1** | **M0+** | **M3** | **M4** | **M7** | **M23** | **M33** | **M55** | 26+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 27| **OS Features** | | | 28+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 29| Programmable fault | | | | | | | | | | 30| IRQ priorities | | Y | N | Y | Y | Y | N | Y | Y | 31+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 32| Single-thread kernel support | | Y | Y | Y | Y | Y | Y | Y | Y | 33+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 34| Thread local storage support | | Y | Y | Y | Y | Y | Y | Y | Y | 35+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 36| Interrupt handling | | | 37+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 38| | Regular interrupts | Y | Y | Y | Y | Y | Y | Y | Y | 39+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 40| | Dynamic interrupts | Y | Y | Y | Y | Y | Y | Y | Y | 41+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 42| | Direct interrupts | Y | Y | Y | Y | Y | Y | Y | Y | 43+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 44| | Zero Latency interrupts | N | N | Y | Y | Y | Y | Y | Y | 45+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 46| CPU idling | | Y | Y | Y | Y | Y | Y | Y | Y | 47+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 48| Native system timer (SysTick) | | N [#f1]_ | Y | Y | Y | Y | Y | Y | Y | 49+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 50| Memory protection | | | 51+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 52| | User mode | N | Y | Y | Y | Y | Y | Y | Y | 53+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 54| | HW stack protection (MPU) | N | N | Y | Y | Y | Y | Y | Y | 55+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 56| | HW-assisted stack limit checking | N | N | N | N | N |Y [#f2]_ | Y | Y | 57+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 58| HW-assisted null-pointer | | | | | | | | | | 59| dereference detection | | N | N | Y | Y | Y | Y | Y | Y | 60+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 61| HW-assisted atomic operations | | N | N | Y | Y | Y | N | Y | Y | 62+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 63|Support for non-cacheable regions| | N | N | Y | Y | Y | N | Y | Y | 64+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 65| Execute SRAM functions | | N | N | Y | Y | Y | N | Y | Y | 66+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 67| Floating Point Services | | N | N | N | Y | Y | N | Y | Y | 68+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 69| DSP ISA | | N | N | N | Y | Y | N | Y | Y | 70+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 71| Trusted-Execution | | 72+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 73| | Native TrustZone-M support | N | N | N | N | N | Y | Y | Y | 74+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 75| | TF-M integration | N | N | N | N | N | N | Y | N | 76+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 77| Code relocation | | Y | Y | Y | Y | Y | Y | Y | Y | 78+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 79| SW-based vector table relaying | | Y | Y | Y | Y | Y | Y | Y | Y | 80+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 81| HW-assisted timing functions | | N | N | Y | Y | Y | N | Y | Y | 82+---------------------------------+-----------------------------------+-----------------+---------+--------+-----------+--------+---------+------------+------------+ 83 84Notes 85===== 86 87.. [#f1] SysTick is optional in Cortex-M1 88.. [#f2] Stack limit checking only in Secure builds in Cortex-M23 89 90OS features 91*********** 92 93Threads 94======= 95 96Thread stack alignment 97---------------------- 98 99Each Zephyr thread is defined with its own stack memory. By default, Cortex-M enforces a double word thread stack alignment, see 100:kconfig:`CONFIG_STACK_ALIGN_DOUBLE_WORD`. If MPU-based HW-assisted stack overflow detection (:kconfig:`CONFIG_MPU_STACK_GUARD`) 101is enabled, thread stacks need to be aligned with a larger value, reflected by :kconfig:`CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE`. 102In Arm v6-M and Arm v7-M architecture variants, thread stacks are additionally required to be align with a value equal to their size, 103in applications that need to support user mode (:kconfig:`CONFIG_USERSPACE`). The thread stack sizes in that case need to be a power 104of two. This is all reflected by :kconfig:`CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT`, that is enforced in Arm v6-M and Arm v7-M 105builds with user mode support. 106 107Stack pointers 108-------------- 109 110While executing in thread mode the processor is using the Process Stack Pointer (PSP). The processor uses the Main Stack Pointer (MSP) 111while executing in handler mode, that is, while servicing exceptions and HW interrupts. Using PSP in thread mode *facilitates thread 112stack pointer manipulation* during thread context switching, without affecting the current execution context flow in 113handler mode. 114 115In Arm Cortex-M builds a single interrupt stack memory is shared among exceptions and interrupts. The size of the interrupt stack needs 116to be selected taking into consideration nested interrupts, each pushing an additional stack frame. Deverlopers can modify the interrupt 117stack size using :kconfig:`CONFIG_ISR_STACK_SIZE`. 118 119The interrupt stack is also used during early boot so the kernel can initialize the main thread's stack before switching to the main thread. 120 121Thread context switching 122======================== 123 124In Arm Cortex-M builds, the PendSV exception is used in order to trigger a context switch to a different thread. 125PendSV exception is always present in Cortex-M implementations. PendSV is configured with the lowest possible 126interrupt priority level, in all Cortex-M variants. The main reasons for that design are 127 128* to utilize the tail chaining feature of Cortex-M processors, and thus limit the number of context switch 129 operations that occur. 130* to not impact the interrupt latency observed by HW interrupts. 131 132As a result, context switch in Cortex-M is non-atomic, i.e. it may be *preempted* by HW interrupts, 133however, a context-switch operation must be completed before a new thread context-switch may start. 134 135Typically a thread context-switch will perform the following operations 136 137* When switching-out the current thread, the processor stores 138 139 * the callee-saved registers (R4 - R11) in the thread's container for callee-saved registers, 140 which is located in kernel memory 141 * the thread's current operation *mode* 142 143 * user or privileged execution mode 144 * presense of an active floating point context 145 * the EXC_RETURN value of the current handler context (PendSV) 146 147 * the floating point callee-saved registers (S16 - S31) in the thread's container for FP 148 callee-saved registers, if the current thread has an active FP context 149 * the PSP of the current thread which points to the beginning of the current thread's exception 150 stack frame. The latter contains the caller-saved context and the return address of the switched-out 151 thread. 152 153* When switching-in a new thread the processor 154 155 * restores the new thread's callee-saved registers from the thread's 156 container for callee-saved registers 157 * restores the new thread's operation *mode* 158 * restores the FP callee-saved registers if the switched-in thread had 159 an active FP context before being switched-out 160 * re-programs the dynamic MPU regions to allow a user thread access its stack and application 161 memories, and/or programs a stack-overflow MPU guard at the bottom of the thread's 162 privileged stack 163 * restores the PSP for the incoming thread and re-programs the stack pointer limit 164 register (if applicable, see :kconfig:`CONFIG_BUILTIN_STACK_GUARD`) 165 * optionally does a stack limit checking for the switched-in thread, if 166 sentinel-based stack limit checking is enabled (see :kconfig:`CONFIG_STACK_SENTINEL`). 167 168PendSV exception return sequence restores the new thread's caller-saved registers and the 169return address, as part of unstacking the exception stack frame. 170 171The implementation of the context-switch mechanism is present in 172:file:`arch/arm/core/aarch32/swap_helper.S`. 173 174Stack limit checking (Arm v8-M) 175------------------------------- 176 177Armv8-M and Armv8.1-M variants support stack limit checking using the MSPLIM and PSPLIM 178core registers. The feature is enabled when :kconfig:`CONFIG_BUILTIN_STACK_GUARD` is set. 179When stack limit checking is enabled, both the thread's privileged or user stack, as well 180as the interrupt stack are guarded by PSPLIM and MSPLIM registers, respectively. MSPLIM is 181configured *once* during kernel boot, while PSLIM is re-programmed during every thread 182context-switch or during system calls, when the thread switches from using its default 183stack to using its privileged stack, and vice versa. PSPLIM re-programming 184 185* has a relatively low runtime overhead (programming is done with MSR instructions) 186* does not impact interrupt latency 187* does not require any memory areas to be reserved for stack guards 188* does not make use of MPU regions 189 190It is, therefore, considered as a lightweight but very efficient stack overflow 191detection mechanism in Cortex-M applications. 192 193Stack overflows trigger the dedicated UsageFault exception provided by Arm v8-M. 194 195Interrupt handling features 196=========================== 197 198This section describes certain aspects around exception and interrupt 199handling in Arm Cortex-M. 200 201Interrupt priority levels 202------------------------- 203 204The number of available (configurable) interrupt priority levels is 205determined by the number of implemented interrupt priority bits in 206NVIC; this needs to be described for each Cortex-M platform using 207DeviceTree: 208 209.. code-block:: devicetree 210 211 &nvic { 212 arm,num-irq-priority-bits = <#priority-bits>; 213 }; 214 215 216Reserved priority levels 217------------------------ 218 219A number of interrupt priority levels are reserved for the OS. 220 221By design, system fault exceptions have the highest priority level. In 222*Baseline* Cortex-M, this is actually enforced by hardware, as HardFault 223is the only available processor fault exception, and its priority is 224higher than any configurable exception priority. 225 226In *Mainline* Cortex-M, the available fault exceptions (e.g. MemManageFault, 227UsageFault, etc.) are assigned the highest *configurable* priority level. 228(:kconfig:`CONFIG_CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS` signifies explicitly 229that the Cortex-M implementation supports configurable fault priorities.) 230 231This priority level is never shared with HW interrupts (an exception to 232this rule is described below). As a result, processor faults occurring in regular 233ISRs will be handled by the corresponding fault handler and will not escalate to 234a HardFault, *similar to processor faults occurring in thread mode*. 235 236SVC exception is normally configured with the highest conigurable priority level 237(an exception to this rule will be described below). 238SVCs are used by the Zephyr kernel to dispatch system calls, trigger runtime 239system errors (e.g. Kernel oops or panic), or implement IRQ offloading. 240 241In Baseline Cortex-M the priority level of SVC may be shared with other exceptions 242or HW interrupts that are also given the highest configurable priority level (As a 243result of this, kernel runtime errors during interrupt handling will escalate to 244HardFault. Additional logic in the fault handling routines ensures that such 245runtime errors are detected successfully). 246 247In Mainline Cortex-M, however, the SVC priority level is *reserved*, thus normally it 248is only shared with the fault exceptions of configurable priority. This simplifies the 249fault handling routines in Mainline Cortex-M architecture, since runtime kernel errors 250are serviced by the SVC handler (i.e no HardFault escalation, even if the kernel errors 251occur in ISR context). 252 253HW interrupts in Mainline Cortex-M builds are allocated a priority level lower than the SVC. 254 255One exception to the above rules is when Zephyr applications support Zero Latency Interrupts 256(ZLIs). Such interrupts are designed to have a priority level higher than any HW or system 257interrupt. If the ZLI feature is enabled in Mainline Cortex-M builds (see 258:kconfig:`CONFIG_ZERO_LATENCY_IRQS`), then 259 260* ZLIs are assigned the highest configurable priority level 261* SVCs are assigned the second highest configurable priority level 262* Regular HW interrupts are assigned priority levels lower than SVC. 263 264The priority level configuration in Cortex-M is implemented in 265:file:`include/arch/arm/aarch32/exc.h`. 266 267Locking and unlocking IRQs 268-------------------------- 269 270In Baseline Cortex-M locking interrupts is implemented using the PRIMASK register. 271 272.. code-block:: c 273 274 arch_irq_lock() 275 276will set the PRIMASK register to 1, eventually, masking all IRQs with configurable 277priority. While this fulfils the OS requirement of locking interrupts, the consequence 278is that kernel runtime errors (triggering SVCs) will escalate to HardFault. 279 280In Mainline Cortex-M locking interrupts is implemented using the BASEPRI register (Mainline 281Cortex-M builds select :kconfig:`CONFIG_CPU_CORTEX_M_HAS_BASEPRI` to signify that BASEPRI register is 282implemented.). By modifying BASEPRI (or BASEPRI_MAX) arch_irq_lock() masks all system and HW 283interrupts with the exception of 284 285* SVCs 286* processor faults 287* ZLIs 288 289This allows zero latency interrupts to be triggered inside OS critical sections. 290Additionally, this allows system (processor and kernel) faults to be handled by Zephyr 291in *exactly the same way*, regardless of whether IRQs have been locked or not when the 292error occurs. It also allows for system calls to be dispatched while IRQs are locked. 293 294.. note:: 295 296 Mainline Cortex-M fault handling is designed and configured in a way that all processor 297 and kernel faults are handled by the corresponding exception handlers and never result 298 in HardFault escalation. In other words, a HardFault may only occur in Zephyr applications 299 that have modified the default fault handling configurations. The main reason for this 300 design was to reserve the HardFault exception for handling exceptional error conditions 301 in safety critical applications. 302 303Dynamic direct interrupts 304------------------------- 305 306Cortex-M builds support the installation of direct interrupt service routines during 307runtime. Direct interrupts are designed for performance-critical interrupt 308handling and do not go through all of the common Zephyr interrupt handling 309code. 310 311Direct dynamic interrupts are enabled via switching on 312:kconfig:`CONFIG_DYNAMIC_DIRECT_INTERRUPTS`. 313 314Note that enabling direct dynamic interrupts requires enabling support for 315dynamic interrupts in the kernel, as well (see :kconfig:`CONFIG_DYNAMIC_INTERRUPTS`). 316 317Zero Latency interrupts 318----------------------- 319 320As described above, in Mainline Cortex-M applications, the Zephyr kernel reserves 321the highest configurable interrupt priority level for its own use (SVC). SVCs will 322not be masked by interrupt locking. Zero-latency interrupt can be used to set up 323an interrupt at the highest interrupt priority which will not be blocked by interrupt 324locking. To use the ZLI feature :kconfig:`CONFIG_ZERO_LATENCY_IRQS` needs to be enabled. 325 326Zero latency IRQs have minimal interrupt latency, as they will always preempt regular HW 327or system interrupts. 328 329Note, however, that since ZLI ISRs will run at a priority level higher than the kernel 330exceptions they **cannot use** any kernel functionality. Additionally, since the ZLI 331interrupt priority level is equal to processor fault priority level, faults occurring 332in ZLI ISRs will escalate to HardFault and will not be handled in the same way as regular 333processor faults. Developers need to be aware of this limitation. 334 335CPU Idling 336========== 337 338The Cortex-M architecture port implements both k_cpu_idle() 339and k_cpu_atomic_idle(). The implementation is present in 340:file:`arch/arm/core/aarch32/cpu_idle.S`. 341 342In both implementations, the processor 343will attempt to put the core to low power mode. 344In k_cpu_idle() the processor ends up executing WFI (Wait For Interrupt) 345instruction, while in k_cpu_atomic_idle() the processor will 346execute a WFE (Wait For Event) instruction. 347 348When using the CPU idling API in Cortex-M it is important to note the 349following: 350 351* Both k_cpu_idle() and k_cpu_atomic_idle() are *assumed* to be invoked 352 with interrupts locked. This is taken care of by the kernel if the APIs 353 are called by the idle thread. 354* After waking up from low power mode, both functions will *restore* 355 interrupts unconditionally, that is, regardless of the interrupt lock 356 status before the CPU idle API was called. 357 358The Zephyr CPU Idling mechanism is detailed in :ref:`cpu_idle`. 359 360Memory protection features 361========================== 362 363This section describes certain aspects around memory protection features 364in Arm Cortex-M applications. 365 366User mode system calls 367---------------------- 368 369User mode is supported in Cortex-M platforms that implement the standard (Arm) MPU 370or a similar core peripheral logic for memory access policy configuration and 371control, such as the NXP MPU for Kinetis platforms. (Currently, 372:kconfig:`CONFIG_ARCH_HAS_USERSPACE` is selected if :kconfig:`CONFIG_ARM_MPU` is enabled 373by the user in the board default Kconfig settings). 374 375A thread performs a system call by triggering a (synchronous) SVC exception, where 376 377* up to 5 arguments are placed on registers R1 - R5 378* system call ID is placed on register R6. 379 380The SVC Handler will branch to the system call preparation logic, which will perform 381the following operations 382 383* switch the thread's PSP to point to the beginning of the thread's privileged 384 stack area, optionally reprogramming the PSPLIM if stack limit checking is enabled 385* modify CONTROL register to switch to privileged mode 386* modify the return address in the SVC exception stack frame, so that after exception 387 return the system call dispatcher is executed (in thread privileged mode) 388 389Once the system call execution is completed the system call dispatcher will restore the 390user's original PSP and PSPLIM and switch the CONTROL register back to unprivileged mode 391before returning back to the caller of the system call. 392 393System calls execute in thread mode and can be preempted by interrupts at any time. A 394thread may also be context-switched-out while doing a system call; the system call will 395resume as soon as the thread is switched-in again. 396 397The system call dispatcher executes at SVC priority, therefore it cannot be preempted 398by HW interrupts (with the exception of ZLIs), which may observe some additional interrupt 399latency if they occur during a system call preparation. 400 401MPU-assisted stack overflow detection 402------------------------------------- 403 404Cortex-M platforms with MPU may enable :kconfig:`CONFIG_MPU_STACK_GUARD` to enable the MPU-based 405stack overflow detection mechanism. The following points need to be considered when enabling the 406MPU stack guards 407 408* stack overflows are triggering processor faults as soon as they occur 409* the mechanism is essential for detecting stack overflows in supervisor threads, or 410 user threads in privileged mode; stack overflows in threads in user mode will always be 411 detected regardless of :kconfig:`CONFIG_MPU_STACK_GUARD` being set. 412* stack overflows are always detected, however, the mechanism does not guarantee that 413 no memory corruption occurs when supervisor threads overflow their stack memory 414* :kconfig:`CONFIG_MPU_STACK_GUARD` will normally reserve one MPU region for programming 415 the stack guard (in certain Arm v8-M configurations with :kconfig:`CONFIG_MPU_GAP_FILLING` 416 enabled 2 MPU regions are required to implement the guard feature) 417* MPU guards are re-programmed at every context-switch, adding a small overhead to the 418 thread swap routine. Compared, however, to the :kconfig:`CONFIG_BUILTIN_STACK_GUARD` feature, 419 no re-programming occurs during system calls. 420* When :kconfig:`CONFIG_HW_STACK_PROTECTION` is enabled on Arm v8-M platforms the native 421 stack limit checking mechanism is used by default instead of the MPU-based stack overflow 422 detection mechanism; users may override this setting by manually enabling :kconfig:`CONFIG_MPU_STACK_GUARD` 423 in these scenarios. 424 425Memory map and MPU considerations 426================================= 427 428Fixed MPU regions 429----------------- 430 431By default, when :kconfig:`CONFIG_ARM_MPU` is enabled a set of *fixed* MPU regions 432are programmed during system boot. 433 434* One MPU region programs the entire flash area as read-execute. 435 User can override this setting by enabling :kconfig:`CONFIG_MPU_ALLOW_FLASH_WRITE`, 436 which programs the flash with RWX permissions. If :kconfig:`CONFIG_USERSPACE` is 437 enabled unprivileged access on the entire flash area is allowed. 438* One MPU region programs the entire SRAM area with privileged-only 439 RW permissions. That is, an MPU region is utilized to disallow execute permissions on 440 SRAM. (An exception to this setting is when :kconfig:`CONFIG_MPU_GAP_FILLING` is disabled (Arm v8-M only); 441 in that case no SRAM MPU programming is done so the access is determined by the default 442 Arm memory map policies, allowing for privileged-only RWX permissions on SRAM). 443 444The above MPU regions are defined in :file:`soc/arm/common/arm_mpu_regions.c`. 445Alternative MPU configurations are allowed by enabling :kconfig:`CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS`. 446When enabled, this option signifies that the Cortex-M SoC will define and 447configure its own fixed MPU regions in the SoC definition. 448 449Static MPU regions 450------------------ 451 452Additional *static* MPU regions may be programmed once during system boot. These regions 453are required to enable certain features 454 455* a RX region to allow execution from SRAM, when :kconfig:`CONFIG_ARCH_HAS_RAMFUNC_SUPPORT` is 456 enabled and users have defined functions to execute from SRAM. 457* a RX region for relocating text sections to SRAM, when :kconfig:`CONFIG_CODE_DATA_RELOCATION_SRAM` is enabled 458* a no-cache region to allow for a none-cacheable SRAM area, when :kconfig:`CONFIG_NOCACHE_MEMORY` is enabled 459* a possibly unprivileged RW region for GCOV code coverage accounting area, when :kconfig:`CONFIG_COVERAGE_GCOV` is enabled 460* a no-access region to implement null pointer dereference detection, when :kconfig:`CONFIG_NULL_POINTER_EXCEPTION_DETECTION_MPU` is enabled 461 462The boundaries of these static MPU regions are derived from symbols exposed by the linker, in 463:file:`include/linker/linker-defs.h`. 464 465Dynamic MPU regions 466------------------- 467 468Certain thread-specific MPU regions may be re-programmed dynamically, at each thread context switch: 469 470* an unprivileged RW region for the current thread's stack area (for user threads) 471* a read-only region for the MPU stack guard 472* unprivileged RW regions for the partitions of the currentl thread's application memory 473 domain. 474 475 476Considerations 477-------------- 478 479The number of available MPU regions for a Cortex-M platform is a limited resource. 480Most platforms have 8 MPU regions, while some Cortex-M33 or Cortex-M7 platforms may 481have up to 16 MPU regions. Therefore there is a relatively strict limitation on how 482many fixed, static and dynamic MPU regions may be programmed simultaneously. For platforms 483with 8 available MPU regions it might not be possible to enable all the aforementioned 484features that require MPU region programming. In most practical applications, however, 485only a certain set of features is required and 8 MPU regions are, in many cases, sufficient. 486 487In Arm v8-M processors the MPU architecture does not allow programmed MPU regions to 488overlap. :kconfig:`CONFIG_MPU_GAP_FILLING` controls whether the fixed MPU region 489covering the entire SRAM is programmed. When it does, a full SRAM area partitioning 490is required, in order to program the static and the dynamic MPU regions. This increases 491the total number of required MPU regions. When :kconfig:`CONFIG_MPU_GAP_FILLING` is not 492enabled the fixed MPU region convering the entire SRAM is not programmed, thus, the static 493and dynamic regions are simply programmed on top of the always-existing background region 494(full-SRAM partitioning is not required). 495Note, however, that the background SRAM region allows execution from SRAM, so when 496:kconfig:`CONFIG_MPU_GAP_FILLING` is not set Zephyr is not protected against attacks 497that attempt to execute malicious code from SRAM. 498 499 500Floating point Services 501======================= 502 503Both unshared and shared FP registers mode are supported in Cortex-M (see 504:ref:`float_v2` for more details). 505 506When FPU support is enabled in the build 507(:kconfig:`CONFIG_FPU` is enabled), the 508sharing FP registers mode (:kconfig:`CONFIG_FPU_SHARING`) 509is enabled by default. This is done as some compiler configurations 510may activate a floating point context by generating FP instructions 511for any thread, regardless of whether floating point calculations are 512performed, and that context must be preserved when switching such 513threads in and out. 514 515The developers can still disable the FP sharing mode in their 516application projects, and switch to Unshared FP registers mode, 517if it is guaranteed that the image code does not generate FP 518instructions outside the single thread context that is allowed 519(and supposed) to do so. 520 521Under FPU sharing mode, the callee-saved FPU registers are saved 522and restored in context-switch, if the corresponding threads have 523an active FP context. This adds some runtime overhead on the swap 524routine. In addition to the runtime overhead, the sharing FPU mode 525 526* requires additional memory for each thread to save the callee-saved 527 FP registers 528* requires additional stack memory for each thread, to stack the caller-saved 529 FP registers, upon exception entry, if an FP context is active. Note, however, 530 that since lazy stacking is enabled, there is no runtime overhead of FP context 531 stacking in regular interrupts (FP state preservation is only activated in the 532 swap routine in PendSV interrupt). 533 534 535Misc 536**** 537 538Chain-loadable images 539===================== 540 541Cortex-M applications may either be standalone images or chain-loadable, for instance, 542by a bootloader. Application images chain-loadable by bootloaders (or other applications) 543normally occupy a specific area in the flash denoted as their *code partition*. 544:kconfig:`CONFIG_USE_DT_CODE_PARTITION` will ensure that a Zephyr chain-loadable image 545will be linked into its code partition, specified in DeviceTree. 546 547HW initialization at boot 548------------------------- 549 550In order to boot properly, chain-loaded applications may require that the core Arm 551hardware registers and peripherals are initialized in their reset values. Enabling 552:kconfig:`CONFIG_INIT_ARCH_HW_AT_BOOT` Zephyr to force the initialization of the 553internal Cortex-M architectural state during boot to the reset values as specified 554by the corresponding Arm architecture manual. 555 556Software vector relaying 557------------------------ 558 559In Cortex-M platforms that implement the VTOR register (see :kconfig:`CONFIG_CPU_CORTEX_M_HAS_VTOR`), 560chain-loadable images relocate the Cortex-M vector table by updating the VTOR register with the offset 561of the image vector table. 562 563Baseline Cortex-M platforms without VTOR register might not be able to relocate their 564vector table which remains at a fixed location. Therefore, a chain-loadable image will 565require an alternative way to route HW interrupts and system exeptions to its own vector 566table; this is achieved with software vector relaying. 567 568When a bootloader image enables :kconfig:`CONFIG_SW_VECTOR_RELAY` 569it is able to relay exceptions and interrupts based on a vector table 570pointer that is set by the chain-loadable application. The latter sets 571the :kconfig:`CONFIG_SW_VECTOR_RELAY_CLIENT` option to instruct the boot 572sequence to set the vector table pointer in SRAM so that the bootloader can 573forward the exceptions and interrupts to the chain-loadable image's software 574vector table. 575 576While this feature is intended for processors without VTOR register, it 577may also be used in Mainline Cortex-M platforms. 578 579Code relocation 580=============== 581 582Cortex-M support the code relocation feature. When 583:kconfig:`CONFIG_CODE_DATA_RELOCATION_SRAM` is selected, 584Zephyr will relocate .text, data and .bss sections 585from the specified files and place it in SRAM. It is 586possible to relocate only parts of the code sections 587into SRAM, without relocating the whole image text 588and data sections. More details on the code relocation 589feature can be found in :ref:`code_data_relocation`. 590 591 592Linking Cortex-M applications 593***************************** 594 595Most Cortex-M platforms make use of the default Cortex-M 596GCC linker script in :file:`include/arch/arm/aarch32/cortex-m/scripts/linked.ld`, 597although it is possible for platforms to use a custom linker 598script as well. 599 600 601CMSIS 602***** 603 604Cortex-M CMSIS headers are hosted in a standalone module repository: 605`zephyrproject-rtos/cmsis <https://github.com/zephyrproject-rtos/cmsis>`_. 606 607:kconfig:`CONFIG_CPU_CORTEX_M` selects :kconfig:`CONFIG_HAS_CMSIS_CORE` to signify that 608CMSIS headers are available for all supported Cortex-M variants. 609 610Testing 611******* 612 613A list of unit tests for the Cortex-M porting and miscellaneous features 614is present in :file:`tests/arch/arm/`. The tests suites are continuously 615extended and new test suites are added, in an effort to increase the coverage 616of the Cortex-M architecture support in Zephyr. 617 618QEMU 619**** 620 621We use QEMU to verify the implemented features of the Cortex-M architecture port in Zephyr. 622Adequate coverage is achieved by defining and utilizing a list of QEMU targets, 623each with a specific architecture variant and Arm peripheral support list. 624 625The table below lists the QEMU platform targets defined in Zephyr 626along with the corresponding Cortex-M implementation variant and the peripherals 627these targets emulate. 628 629+---------------------------------+--------------------+--------------------+----------------+-----------------+----------------+ 630| | **QEMU target** | 631+---------------------------------+--------------------+--------------------+----------------+-----------------+----------------+ 632| Architecture variant | Arm v6-M | Arm v7-M | Arm v8-M | Arm v8.1-M | 633+---------------------------------+--------------------+--------------------+----------------+-----------------+----------------+ 634| | **qemu_cortex_m0** | **qemu_cortex_m3** | **mps2_an385** | **mps2_an521** | **mps3_an547** | 635+---------------------------------+--------------------+--------------------+----------------+-----------------+----------------+ 636| **Emulated features** | | 637+---------------------------------+--------------------+--------------------+----------------+-----------------+----------------+ 638| NVIC | Y | Y | Y | Y | Y | 639+---------------------------------+--------------------+--------------------+----------------+-----------------+----------------+ 640| BASEPRI | N | Y | Y | Y | Y | 641+---------------------------------+--------------------+--------------------+----------------+-----------------+----------------+ 642| SysTick | N | Y | Y | Y | Y | 643+---------------------------------+--------------------+--------------------+----------------+-----------------+----------------+ 644| MPU | N | N | Y | Y | Y | 645+---------------------------------+--------------------+--------------------+----------------+-----------------+----------------+ 646| FPU | N | N | N | Y | N | 647+---------------------------------+--------------------+--------------------+----------------+-----------------+----------------+ 648| SPLIM | N | N | N | Y | Y | 649+---------------------------------+--------------------+--------------------+----------------+-----------------+----------------+ 650| TrustZone-M | N | N | N | Y | N | 651+---------------------------------+--------------------+--------------------+----------------+-----------------+----------------+ 652 653Maintainers & Collaborators 654*************************** 655 656The status of the Arm Cortex-M architecture port in Zephyr is: *maintained*. 657The updated list of maintainers and collaborators for Cortex-M can be found 658in :file:`MAINTAINERS.yml`. 659