ARM-Cortex-M Porting Guide

Overview

XWOS source code already includes most of the ARM-Cortex-M architecture code:

  • Architecture Description Layer (ADL)
    • ARMv7m: XWOS/xwcd/soc/arm/v7m
    • ARMv6m: XWOS/xwcd/soc/arm/v6m
  • CPU Description Layer (CDL)
    • m0: XWOS/xwcd/soc/arm/v6m/m0
    • m0p: XWOS/xwcd/soc/arm/v6m/m0p
    • m3: XWOS/xwcd/soc/arm/v7m/m3
    • m4: XWOS/xwcd/soc/arm/v7m/m4
    • m7: XWOS/xwcd/soc/arm/v7m/m7
  • SoC Description Layer (SDL)
    • STM32:
      • L0/F0: XWOS/xwcd/soc/arm/v7m/m0/stm32
      • L1/F1: XWOS/xwcd/soc/arm/v7m/m3/stm32
      • L4/F4: XWOS/xwcd/soc/arm/v7m/m4/stm32
        • F7/H7: XWOS/xwcd/soc/arm/v7m/m7/stm32
    • S32K: XWOS/xwcd/soc/arm/v7m/m4/s32k14x
    • i.MX RT1052: XWOS/xwcd/soc/arm/v7m/m7/mimxrt1052

For a new SoC chip, you only need to add an SoC folder in the CPU folder, which includes:

  • Initialization: soc_init.h and soc_init.c
  • Interrupts: xwosimpl_irq.h and xwosimpl_irq.c
    • Must provide implementations for functions declared in the XWOS Kernel Porting Layer (XWOSPL) XWOS/xwos/ospl/irq.h.
  • Scheduler: xwosimpl_skd.h and xwosimpl_skd.c
    • Must provide implementations for functions declared in the XWOS Kernel Porting Layer (XWOSPL) XWOS/xwos/ospl/skd.h.
  • Tick Timer: xwosimpl_syshwt.h and xwosimpl_syshwt.c
    • Must provide implementations for functions declared in the XWOS Kernel Porting Layer (XWOSPL) XWOS/xwos/ospl/syshwt.h.
  • .lds: Linker script

You can copy an SDL folder (e.g., STM32) as a template. All Cortex-M microcontrollers share the same XWOSIMPL.

Type Definitions

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_type.h
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_type.h

Compiler Macro Definitions

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_compiler.h
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_compiler.h

Lock-Free Queue Implementation

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_lfq.h
XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_lfq.c
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_lfq.h
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_lfq.c

Spinlock

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_spinlock.h
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_spinlock.h

Architecture Instructions

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_isa.h
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_isa.h

Bit Operations

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_xwbop
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_xwbop

8-bit Atomic Operations

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_xwaop/xws8/
XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_xwaop/xwu8/
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_xwaop/xws8/
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_xwaop/xwu8/

16-bit Atomic Operations

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_xwaop/xws16/
XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_xwaop/xwu16/
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_xwaop/xws16/
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_xwaop/xwu16/

32-bit Atomic Operations

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_xwaop/xws32/
XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_xwaop/xwu32/
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_xwaop/xws32/
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_xwaop/xwu32/

64-bit Atomic Operations

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_xwaop/xws64/
XWOS/xwcd/soc/arm/v6m/xwosimpl_arch_xwaop/xwu64/
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_xwaop/xws64/
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_xwaop/xwu64/

setjmp()/longjmp()

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_setjmp.h
XWOS/xwcd/soc/arm/v7m/xwosimpl_arch_setjmp.c

The setjmp()/longjmp() defined in the C standard library are goto statements that can jump between different functions. Some libc implementations do not consider the floating-point register stack, so XWOS has re-implemented these two functions.

  • The complete stack layout is as follows:
            -----------------------------
   sp+0x64  | s31             |         |
   sp+0x60  | s30             |         |
   sp+0x5C  | s29             |         |
   sp+0x58  | s28             |         |
   sp+0x54  | s27             |         |
   sp+0x50  | s26             |         |
   sp+0x4C  | s25             |   FP    |
   sp+0x48  | s24             |  Frame  |
   sp+0x44  | s23             |         |
   sp+0x40  | s22             |         |
   sp+0x3C  | s21             |         |
   sp+0x38  | s20             |         |
   sp+0x34  | s19             |         |
   sp+0x30  | s18             |         |
   sp+0x2C  | s17             |         |
   sp+0x28  | s16             |         |
            -----------------------------
   sp+0x24  | r14 (lr)        |         |
   sp+0x20  | r13 (sp)        |         |
   sp+0x1C  | r11 (fp)        |         |
   sp+0x18  | r10 (sl)        |         |
   sp+0x14  | r9              |  Basic  |
   sp+0x10  | r8              |  Frame  |
   sp+0x0C  | r7              |         |
   sp+0x08  | r6              |         |
   sp+0x04  | r5              |         |
   sp+0x00  | r4              |         |
            -----------------------------
              setjmp/longjmp Register Stack Layout

Thread Local Storage (TLS)

TLS is a language feature introduced starting from the C11 standard. XWOS supports TLS, and Cortex-M MCUs use a unified implementation:

XWOS/xwcd/soc/arm/v6m/xwosimpl_tls.c
XWOS/xwcd/soc/arm/v7m/xwosimpl_tls.c

XWOS places the TLS data section at the start of the thread stack memory.

            ------------------------
            | Thread Stack Memory  |
            +----------------------+
   SP --->  |                      |
            |                      |
            |                      |
            |                      |
            |                      |
            |                      |
            |     Stack Region     |
            |                      |
            |                      |
            |                      |
            |                      |
            |                      |
            |                      |
            +----------------------+
            |                      |
            |     Stack Guard      |
            |                      |
            +----------------------+
            |                      |
            |      TLS Region      |
            |                      |
            ------------------------

Scheduler

The XWOS Porting Implementation Layer is located at:

XWOS/xwcd/soc/arm/v6m/[CPU]/[SoC]/xwosimpl_arch_skd.h
XWOS/xwcd/soc/arm/v6m/[CPU]/[SoC]/xwosimpl_arch_skd.c
XWOS/xwcd/soc/arm/v7m/[CPU]/[SoC]/xwosimpl_arch_skd.h
XWOS/xwcd/soc/arm/v7m/[CPU]/[SoC]/xwosimpl_arch_skd.c

Due to the good consistency of Cortex-M core microcontrollers, different microcontrollers ultimately call functions in the following files to provide specific implementations:

XWOS/xwcd/soc/arm/v6m/arch_skd.h
XWOS/xwcd/soc/arm/v6m/arch_skd.c
XWOS/xwcd/soc/arm/v7m/arch_skd.h
XWOS/xwcd/soc/arm/v7m/arch_skd.c

Thread Stack

  • On ARMv6/7-m platforms, XWOS uses an 8-byte aligned stack, therefore STKALIGN in the CCR register must be set to 1 at the earliest stage of chip initialization:
cm_scs.scb.ccr.bit.stkalign = 1;
  • A full descending stack is used, meaning XWMMCFG_FD_STACK in the configuration file cfg/xwos.h is configured as 1.
  • When the CPU includes a floating-point unit, enable automatic floating-point context saving and restoring via:
cm_scs.scb.fpu.fpccr.bit.aspen = 1;

Thread Stack Layout

In C, registers are generally divided into two types: volatile and non-volatile. When volatile registers are used, their values do not need to be saved and restored; when non-volatile registers are used, their values need to be saved and restored.

Volatile Stack Layout

On ARMv6/v7-m CPUs, when entering interrupt mode from thread mode, volatile registers are automatically saved to the stack.

            ------------------------
            | Prev Frame           |
            +------------+---------+
   sp+0x64  |            |         |
   sp+0x60  | FPSCR      |         |
   sp+0x5C  | s15        |         |
   sp+0x58  | s14        |         |
   sp+0x54  | s13        |         |
   sp+0x50  | s12        |         |
   sp+0x4C  | s11        |         |
   sp+0x48  | s10        |         |
   sp+0x44  | s9         |   FP    |
   sp+0x40  | s8         |  Frame  |
   sp+0x3C  | s7         |         |
   sp+0x38  | s6         |         |
   sp+0x34  | s5         |         |
   sp+0x30  | s4         |         |
   sp+0x2C  | s3         |         |
   sp+0x28  | s2         |         |
   sp+0x24  | s1         |         |
   sp+0x20  | s0         |         |
            ------------------------
   sp+0x1C  | xpsr       |         |
   sp+0x18  | pc         |         |
   sp+0x14  | lr         |         |
   sp+0x10  | r12 (ip)   |  Basic  |
   sp+0x0C  | r3         |  Frame  |
   sp+0x08  | r2         |         |
   sp+0x04  | r1         |         |
   sp+0x00  | r0         |         |
            ------------------------
           Volatile Register Stack Layout
Non-Volatile Stack Layout

The compiler can automatically handle non-volatile registers, so in the same context, restoring the environment does not require saving non-volatile registers. However, when the OS switches tasks, the non-volatile register environments of different tasks are different and need to be saved and restored.

XWOS’s non-volatile register stack layout on ARMv6/7-m platforms is as follows:

            -----------------------------
            |   Volatile stack Frame    |
            +-----------------+---------+
   sp+0x64  | s31             |         |
   sp+0x60  | s30             |         |
   sp+0x5C  | s29             |         |
   sp+0x58  | s28             |         |
   sp+0x54  | s27             |         |
   sp+0x50  | s26             |         |
   sp+0x4C  | s25             |   FP    |
   sp+0x48  | s24             |  Frame  |
   sp+0x44  | s23             |         |
   sp+0x40  | s22             |         |
   sp+0x3C  | s21             |         |
   sp+0x38  | s20             |         |
   sp+0x34  | s19             |         |
   sp+0x30  | s18             |         |
   sp+0x2C  | s17             |         |
   sp+0x28  | s16             |         |
            -----------------------------
   sp+0x24  | lr (EXC_RETURN) |         |
   sp+0x20  | r11 (fp)        |         |
   sp+0x1C  | r10 (sl)        |         |
   sp+0x18  | r9              |         |
   sp+0x14  | r8              |  Basic  |
   sp+0x10  | r7              |  Frame  |
   sp+0x0C  | r6              |         |
   sp+0x08  | r5              |         |
   sp+0x04  | r4              |         |
   sp+0x00  | CONTROL         |         |
            -----------------------------
           Non-Volatile Register Stack Layout

Interrupts

The XWOS Porting Implementation Layer is located at:

xwcd/soc/arm/v6m/[CPU]/[SoC]/xwosimpl_irq.h
xwcd/soc/arm/v6m/[CPU]/[SoC]/xwosimpl_irq.c
xwcd/soc/arm/v7m/[CPU]/[SoC]/xwosimpl_irq.h
xwcd/soc/arm/v7m/[CPU]/[SoC]/xwosimpl_irq.c

Tick Timer

The XWOS Porting Implementation Layer is located at:

xwcd/soc/arm/v6m/[CPU]/[SoC]/xwosimpl_syshwt.h
xwcd/soc/arm/v6m/[CPU]/[SoC]/xwosimpl_syshwt.c
xwcd/soc/arm/v7m/[CPU]/[SoC]/xwosimpl_syshwt.h
xwcd/soc/arm/v7m/[CPU]/[SoC]/xwosimpl_syshwt.c