SoC Porting

Overview

XWOS porting involves the following steps:

  • Build environment
  • Initialization flow
  • XWOS Porting Layer (XWOSPL)
  • XWOS Porting Implementation Layer (XWOSIMPL)

The XWOS Porting Layer (XWOSPL) defines interfaces, while the XWOS Porting Implementation Layer (XWOSIMPL) provides implementations.

To improve code reusability, the code related to the XWOS Porting Implementation Layer (XWOSIMPL) is further subdivided into:

  • Architecture Description Layer (ADL)
  • CPU Description Layer (CDL)
  • SoC Description Layer (SDL)
  • Board Description Layer (BDL)

For example, under the ARMv7m architecture, the ADL directory is xwcd/soc/arm/v7m/gcc/. The code within is reused for STM32, S32K, i.MX RT1052, GD32, etc. Differences between m3, m4, and m7 are described by the CDL directory. Different SoCs with the same CPU core are described by SDL. Different boards are described by BDL. Together they complete the implementation of the build environment, initialization flow, and the XWOS Porting Implementation Layer (XWOSIMPL).

XWOS Porting Layer (XWOSPL) Header File Rules

  • xwos/ospl/*.h: Header files provided by XWOS to the BSP, must not be included by XWOS’s own header files.
    • Prefix xwospl: Functions that the BSP must implement
    • Prefix xwosplcb: Functions that can be called by the BSP
  • xwos/ospl/*.h: Contains header files provided by the BSP to XWOS, can be included by XWOS’s header files.
    • xwos/ospl/type.h: Contains platform type definitions
    • xwos/ospl/compiler.h: Contains platform compiler-related definitions
    • xwos/ospl/isa.h: Contains platform instruction and architecture-related definitions
    • xwos/ospl/lfq.h: Contains lock-free queue-related definitions
    • xwos/ospl/setjmp.h: Contains setjmp.h-related definitions
    • xwos/ospl/spinlock.h: Contains spinlock-related definitions
    • xwos/ospl/xwaop[bit].h: Contains atomic operation-related definitions
    • xwos/ospl/xwbmpaop.h: Contains bitmap atomic operation-related definitions
    • xwos/ospl/xwbop.h: Contains bit operation-related definitions
    • xwos/ospl/xwsc.h: Contains system call-related definitions

Porting

XWOS porting includes: basic types, compiler, breakpoints, setjmp, system calls and system privilege, bit operations, atomic operations, lock-free queues, spinlocks, interrupts, hardware timers, and scheduler.

Basic Types

XWOS defines its own set of basic types, around which all source code is built.

  • XWOS header file: xwos/lib/type.h, see Basic Types for details.
  • Interface: xwos/ospl/type.h
  • Implementation: The file xwosimpl_soc_type.h redefines certain types according to the architecture’s ELF ABI rules, and the macro ARCH_HAVE_xxxx must be defined as 1, indicating that the default definition of xxxx is overridden. This file is generally located in the ADL directory, e.g., xwcd/soc/arm/v7m/gcc/xwosimpl_soc_type.h.
  • Basic types:
    • ARCH_HAVE_XWU8_T: Macro, defined as 1 indicates that type xwu8_t is provided in arch_type.h
    • xwu8_t: Type, 8-bit unsigned integer
    • ARCH_HAVE_ATOMIC_XWU8_T: Macro, defined as 1 indicates that type atomic_xwu8_t is provided in arch_type.h
    • atomic_xwu8_t: Type, atomic 8-bit unsigned integer
    • ARCH_HAVE_XWS8_T: Macro, defined as 1 indicates that type xws8_t is provided in arch_type.h
    • xws8_t: Type, 8-bit signed integer
    • ARCH_HAVE_ATOMIC_XWS8_T: Macro, defined as 1 indicates that type atomic_xws8_t is provided in arch_type.h
    • atomic_xws8_t: Type, atomic 8-bit signed integer
    • ARCH_HAVE_XWU16_T: Macro, defined as 1 indicates that type xwu16_t is provided in arch_type.h
    • xwu16_t: Type, 16-bit unsigned integer
    • ARCH_HAVE_ATOMIC_XWU16_T: Macro, defined as 1 indicates that type atomic_xwu16_t is provided in arch_type.h
    • atomic_xwu16_t: Type, atomic 16-bit unsigned integer
    • ARCH_HAVE_XWS16_T: Macro, defined as 1 indicates that type xws16_t is provided in arch_type.h
    • xws16_t: Type, 16-bit signed integer
    • ARCH_HAVE_ATOMIC_XWS16_T: Macro, defined as 1 indicates that type atomic_xws16_t is provided in arch_type.h
    • atomic_xws16_t: Type, atomic 16-bit signed integer
    • ARCH_HAVE_XWU32_T: Macro, defined as 1 indicates that type xwu32_t is provided in arch_type.h
    • xwu32_t: Type, 32-bit unsigned integer
    • ARCH_HAVE_ATOMIC_XWU32_T: Macro, defined as 1 indicates that type atomic_xwu32_t is provided in arch_type.h
    • atomic_xwu32_t: Type, atomic 32-bit unsigned integer
    • ARCH_HAVE_XWS32_T: Macro, defined as 1 indicates that type xws32_t is provided in arch_type.h
    • xws32_t: Type, 32-bit signed integer
    • ARCH_HAVE_ATOMIC_XWS32_T: Macro, defined as 1 indicates that type atomic_xws32_t is provided in arch_type.h
    • atomic_xws32_t: Type, atomic 32-bit signed integer
    • ARCH_HAVE_XWU64_T: Macro, defined as 1 indicates that type xwu64_t is provided in arch_type.h
    • xwu64_t: Type, 64-bit unsigned integer
    • ARCH_HAVE_ATOMIC_XWU64_T: Macro, defined as 1 indicates that type atomic_xwu64_t is provided in arch_type.h
    • atomic_xwu64_t: Type, atomic 64-bit unsigned integer
    • ARCH_HAVE_XWS64_T: Macro, defined as 1 indicates that type xws64_t is provided in arch_type.h
    • xws64_t: Type, 64-bit signed integer
    • ARCH_HAVE_ATOMIC_XWS64_T: Macro, defined as 1 indicates that type atomic_xws64_t is provided in arch_type.h
    • atomic_xws64_t: Type, atomic 64-bit signed integer
    • ARCH_HAVE_XWSZ_T: Macro, defined as 1 indicates that type xwsz_t is provided in arch_type.h
    • xwsz_t: Type, unsigned size value type
    • ARCH_HAVE_ATOMIC_XWSZ_T: Macro, defined as 1 indicates that type atomic_xwsz_t is provided in arch_type.h
    • atomic_xwsz_t: Type, atomic unsigned size value type
    • ARCH_HAVE_XWSSZ_T: Macro, defined as 1 indicates that type xwssz_t is provided in arch_type.h
    • xwssz_t: Type, signed size value type
    • ARCH_HAVE_ATOMIC_XWSSZ_T: Macro, defined as 1 indicates that type atomic_xwssz_t is provided in arch_type.h
    • atomic_xwssz_t: Type, atomic signed size value type
    • ARCH_HAVE_XWSTK_T: Macro, defined as 1 indicates that type xwstk_t is provided in arch_type.h
    • xwstk_t: Type, unsigned stack type
    • ARCH_HAVE_ATOMIC_XWSTK_T: Macro, defined as 1 indicates that type atomic_xwstk_t is provided in arch_type.h
    • atomic_xwstk_t: Type, atomic unsigned stack type
    • ARCH_HAVE_XWPTR_T: Macro, defined as 1 indicates that type xwptr_t is provided in arch_type.h
    • xwptr_t: Type, unsigned pointer value type
    • ARCH_HAVE_ATOMIC_XWPTR_T: Macro, defined as 1 indicates that type atomic_xwptr_t is provided in arch_type.h
    • atomic_xwptr_t: Type, atomic unsigned pointer value type
    • ARCH_HAVE_XWREG_T: Macro, defined as 1 indicates that type xwreg_t is provided in arch_type.h
    • xwreg_t: Type, unsigned register type
    • ARCH_HAVE_ATOMIC_XWREG_T: Macro, defined as 1 indicates that type atomic_xwreg_t is provided in arch_type.h
    • atomic_xwreg_t: Type, atomic unsigned register type
    • ARCH_HAVE_XWSREG_T: Macro, defined as 1 indicates that type xwsreg_t is provided in arch_type.h
    • xwsreg_t: Type, signed register type
    • ARCH_HAVE_ATOMIC_XWSREG_T: Macro, defined as 1 indicates that type atomic_xwsreg_t is provided in arch_type.h
    • atomic_xwsreg_t: Type, atomic signed register type
    • ARCH_HAVE_XWSQ_T: Macro, defined as 1 indicates that type xwsq_t is provided in arch_type.h
    • xwsq_t: Type, unsigned sequence value type
    • ARCH_HAVE_ATOMIC_XWSQ_T: Macro, defined as 1 indicates that type atomic_xwsq_t is provided in arch_type.h
    • atomic_xwsq_t: Type, atomic unsigned sequence value type
    • ARCH_HAVE_XWSSQ_T: Macro, defined as 1 indicates that type xwssq_t is provided in arch_type.h
    • xwssq_t: Type, signed sequence value type
    • ARCH_HAVE_ATOMIC_XWSSQ_T: Macro, defined as 1 indicates that type atomic_xwssq_t is provided in arch_type.h
    • atomic_xwssq_t: Type, atomic signed sequence value type
    • ARCH_HAVE_XWID_T: Macro, defined as 1 indicates that type xwid_t is provided in arch_type.h
    • xwid_t: Type, unsigned ID value type
    • ARCH_HAVE_ATOMIC_XWID_T: Macro, defined as 1 indicates that type atomic_xwid_t is provided in arch_type.h
    • atomic_xwid_t: Type, atomic unsigned ID value type
    • ARCH_HAVE_XWSID_T: Macro, defined as 1 indicates that type xwsid_t is provided in arch_type.h
    • xwsid_t: Type, signed ID value type
    • ARCH_HAVE_ATOMIC_XWSID_T: Macro, defined as 1 indicates that type atomic_xwsid_t is provided in arch_type.h
    • atomic_xwsid_t: Type, atomic signed ID value type
    • ARCH_HAVE_XWER_T: Macro, defined as 1 indicates that type xwer_t is provided in arch_type.h
    • xwer_t: Type, signed error code type
    • ARCH_HAVE_ATOMIC_XWER_T: Macro, defined as 1 indicates that type atomic_xwer_t is provided in arch_type.h
    • atomic_xwer_t: Type, atomic signed error code type
    • ARCH_HAVE_XWPR_T: Macro, defined as 1 indicates that type xwpr_t is provided in arch_type.h
    • xwpr_t: Type, signed priority type
    • ARCH_HAVE_ATOMIC_XWPR_T: Macro, defined as 1 indicates that type atomic_xwpr_t is provided in arch_type.h
    • atomic_xwpr_t: Type, atomic signed priority type
    • ARCH_HAVE_XWBMP_T: Macro, defined as 1 indicates that type xwbmp_t is provided in arch_type.h
    • xwbmp_t: Type, unsigned bitmap type
    • ARCH_HAVE_ATOMIC_XWBMP_T: Macro, defined as 1 indicates that type atomic_xwbmp_t is provided in arch_type.h
    • xwbmpy_a: Type, atomic unsigned bitmap type
    • ARCH_HAVE_XWTM_T: Macro, defined as 1 indicates that type xwtm_t is provided in arch_type.h
    • xwtm_t: Type, signed priority type
    • ARCH_HAVE_ATOMIC_XWTM_T: Macro, defined as 1 indicates that type atomic_xwtm_t is provided in arch_type.h
    • atomic_xwtm_t: Type, atomic signed priority type
    • ARCH_HAVE_XWLFQ_T: Macro, defined as 1 indicates that type xwlfq_t is provided in arch_type.h
    • xwlfq_t: Type, lock-free queue type
    • ARCH_HAVE_ATOMIC_XWLFQ_T: Macro, defined as 1 indicates that type atomic_xwlfq_t is provided in arch_type.h
    • atomic_xwlfq_t: Type, atomic lock-free queue type
    • ARCH_HAVE_XWISR_F: Macro, defined as 1 indicates that type xwisr_f is provided in arch_type.h
    • atomic_xwer_t: Type, atomic signed error code type
    • ARCH_HAVE_XWIRQ_T: Macro, defined as 1 indicates that type xwirq_t is provided in arch_type.h
    • xwirq_t: Type, signed interrupt number type

Compiler

  • XWOS header file: xwos/lib/compiler.h, included by xwos/standard.h.
  • Interface: xwos/ospl/compiler.h
  • Implementation: xwosimpl_soc_compiler.h

Compiler-related macro definitions:

  • __xwcc_section(s): Indicates that a symbol belongs to section s.
  • __xwcc_aligned(x): Indicates that data’s starting address is aligned to x bytes.
  • __xwcc_inline: Indicates that a function is inline, must be used together with static.
  • __xwcc_packed: Indicates that a data structure is densely packed, and the compiler should not perform alignment optimization.
  • __xwcc_must_check: Indicates that the function’s return value must be read, otherwise the compiler will issue a warning.
  • __xwcc_unused: Indicates that a variable or function is unused, used to suppress compiler warnings.
  • __xwcc_noreturn: Indicates that a function will not return.
  • __xwcc_hot: Indicates that a function is frequently called in the code, which may help some compilers optimize compilation.
  • __xwcc_atomic: Indicates that a variable is atomic. Defined as _Atomic in the C11 standard, and as volatile in the C99 standard.
  • __xwcc_likely(x): Indicates that condition x is likely true, used for if..else.. optimization.
  • __xwcc_unlikely(x): Indicates that condition x is likely false, used for if..else.. optimization.
  • __xwcc_alignl1cache: Indicates that data’s starting address is aligned to the L1 cache (way-set cache) cache line.
  • __xwcc_alignptr: Indicates that data’s starting address is aligned to the pointer size.
  • xwcc_offsetof(type, member): Calculates the offset of member within the structure type, equivalent to offsetof() in the standard C library.

Architecture Instructions

The CPU architecture provides some special instructions that are generally difficult to express in C language for convenient use. XWOS kernel provides the same encapsulation for unified parts.

  • XWOS header file: Included in xwos/standard.h.
  • Interface: xwos/ospl/isa.h
  • Implementation: xwosimpl_soc_isa.h

These architecture instructions include but are not limited to:

  • Breakpoint instruction
  • Memory barrier

setjmp/longjmp

XWOS’s C library provides a function combination similar to setjmp()/longjmp() from the C standard library. Its implementation is closely related to how registers are saved during context switching.

  • XWOS header file: xwos/lib/setjmp.h
  • Interface: xwos/ospl/setjmp.h
  • Implementation: xwosimpl_soc_setjmp.h

System Calls and System Privilege

CPUs typically have two privilege modes: user and system.

  • In system mode, all registers can be accessed;
  • In user mode, certain internal CPU registers cannot be accessed (e.g., interrupt enable/disable), and can only be accessed through special instructions that switch the CPU to system mode.

XWOS’s C library provides the function xwsc() for switching CPU access privilege, allowing user mode to temporarily have system privilege to call a function.

  • XWOS header file: xwos/lib/sc.h
  • Interface: xwos/ospl/xwsc.h
  • Implementation: xwosimpl_soc_xwsc.h

Bit Operations

XWOS’s C library provides a function set for bit operations. To improve efficiency, some bit operations can be implemented using special instructions.

  • XWOS header file: xwos/lib/xwbop.h
  • Interface: xwos/ospl/xwbop.h
  • Implementation: xwosimpl_soc_xwbop.h
  • Basic type bit operation function sets:
    • Bit order mirroring: Intel bit order (mainstream little-endian CPUs use Intel bit order) has higher bits with larger bit numbers. Motorola bit order (PowerPC architecture CPUs) has higher bits with smaller bit numbers. Therefore, when mixing the two systems, data bit order must be mirrored.
      • xwbop_rbit8(): Mirror the bit order of 8-bit data
      • xwbop_rbit16(): Mirror the bit order of 16-bit data
      • xwbop_rbit32(): Mirror the bit order of 32-bit data
      • xwbop_rbit64(): Mirror the bit order of 64-bit data
    • Endian reversal:
      • xwbop_re16(): Reverse the byte order of 16-bit data
      • xwbop_re16s32(): Reverse the byte order of 16-bit data, sign-extend to 32 bits, return signed 32-bit data
      • xwbop_re32(): Reverse the byte order of 32-bit data
      • xwbop_re32s64(): Reverse the byte order of 32-bit data, sign-extend to 64 bits, return signed 64-bit data
      • xwbop_re64(): Reverse the byte order of 64-bit data
    • Find set bits:
      • xwbop_ffs8(): 8-bit data, search from the least significant bit
      • xwbop_fls8(): 8-bit data, search from the most significant bit
      • xwbop_ffs16(): 16-bit data, search from the least significant bit
      • xwbop_fls16(): 16-bit data, search from the most significant bit
      • xwbop_ffs32(): 32-bit data, search from the least significant bit
      • xwbop_fls32(): 32-bit data, search from the most significant bit
      • xwbop_ffs64(): 64-bit data, search from the least significant bit
      • xwbop_fls64(): 64-bit data, search from the most significant bit

Atomic Operations

XWOS’s C library provides a function set for atomic operations. The implementation of atomic operations depends on the CPU’s atomic operation instructions.

  • XWOS header files:
    • xwos/lib/xwaop.h
  • Interface:
    • xwos/ospl/xwaop.h
  • Implementation:
    • xwosimpl_soc_xwaop.h
    • xwosimpl_soc_xwaop/*
  • Description:
    • Other types of atomic operations will be wrapped by the XWOS kernel based on 4 basic types. 64-bit atomic operations may not be provided if unsupported;
    • If the CPU architecture is relatively simple and lacks atomic operation instructions, these atomic operation functions can be implemented by disabling interrupts;
    • Some CPU architectures only provide atomic operation instructions that match the CPU bit width. For code portability, it is best to use only atomic data types that match the CPU bit width;
  • Basic type atomic operation function sets:
    • load(): Load (memory order specifiable)
    • store(): Store (memory order specifiable)
    • read(): Read (memory order: load-acquire)
    • write(): Write (memory order: store-release)
    • add(): Addition
    • sub(): Subtraction
    • rsb(): Reverse subtraction
    • and(): AND operation
    • or(): OR operation
    • xor(): XOR operation
    • teq_then_write(): Test if equal to test value, then write
    • teq_then_add(): Test if equal to test value, then add
    • teq_then_sub(): Test if equal to test value, then subtract
    • teq_then_rsb(): Test if equal to test value, then reverse subtract
    • tne_then_write(): Test if not equal to test value, then write
    • tne_then_add(): Test if not equal to test value, then add
    • tne_then_sub(): Test if not equal to test value, then subtract
    • tne_then_rsb(): Test if not equal to test value, then reverse subtract
    • tge_then_write(): Test if greater than or equal to test value, then write
    • tge_then_add(): Test if greater than or equal to test value, then add
    • tge_then_sub(): Test if greater than or equal to test value, then subtract
    • tge_then_rsb(): Test if greater than or equal to test value, then reverse subtract
    • tgt_then_write(): Test if greater than test value, then write
    • tgt_then_add(): Test if greater than test value, then add
    • tgt_then_sub(): Test if greater than test value, then subtract
    • tgt_then_rsb(): Test if greater than test value, then reverse subtract
    • tle_then_write(): Test if less than or equal to test value, then write
    • tle_then_add(): Test if less than or equal to test value, then add
    • tle_then_sub(): Test if less than or equal to test value, then subtract
    • tle_then_rsb(): Test if less than or equal to test value, then reverse subtract
    • tlt_then_write(): Test if less than test value, then write
    • tlt_then_add(): Test if less than test value, then add
    • tlt_then_sub(): Test if less than test value, then subtract
    • tlt_then_rsb(): Test if less than test value, then reverse subtract
    • tgele_then_write(): Test if old value is in closed interval [l,r], then write
    • tgele_then_add(): Test if old value is in closed interval [l,r], then add
    • tgele_then_sub(): Test if old value is in closed interval [l,r], then subtract
    • tgele_then_rsb(): Test if old value is in closed interval [l,r], then reverse subtract
    • tgelt_then_write(): Test if old value is in left-closed right-open interval [l,r), then write
    • tgelt_then_add(): Test if old value is in left-closed right-open interval [l,r), then add
    • tgelt_then_sub(): Test if old value is in left-closed right-open interval [l,r), then subtract
    • tgelt_then_rsb(): Test if old value is in left-closed right-open interval [l,r), then reverse subtract
    • tgtle_then_write(): Test if old value is in left-open right-closed interval (l,r], then write
    • tgtle_then_add(): Test if old value is in left-open right-closed interval (l,r], then add
    • tgtle_then_sub(): Test if old value is in left-open right-closed interval (l,r], then subtract
    • tgtle_then_rsb(): Test if old value is in left-open right-closed interval (l,r], then reverse subtract
    • tgtlt_then_write(): Test if old value is in open interval (l,r), then write
    • tgtlt_then_add(): Test if old value is in open interval (l,r), then add
    • tgtlt_then_sub(): Test if old value is in open interval (l,r), then subtract
    • tgtlt_then_rsb(): Test if old value is in open interval (l,r), then reverse subtract
    • tst_then_op(): Test using tst() function, then operate using op() function
  • Bitmap array atomic operations:
    • xwbmpaop_c0i(): Clear bit i to 0
    • xwbmpaop_s1i(): Set bit i to 1
    • xwbmpaop_x1i(): Toggle bit i
    • xwbmpaop_t1i(): Test if bit i is 1
    • xwbmpaop_t0i_then_s1i(): Test if bit i is 0, then set it to 1
    • xwbmpaop_t1i_then_c0i(): Test if bit i is 1, then clear it to 0
    • xwbmpaop_ffs_then_c0i(): Find the first set bit from the least significant bit and clear it to 0
    • xwbmpaop_ffz_then_s1i(): Find the first zero bit from the least significant bit and set it to 1
    • xwbmpaop_fls_then_c0i(): Find the first set bit from the most significant bit and clear it to 0
    • xwbmpaop_flz_then_s1i(): Find the first zero bit from the most significant bit and set it to 1

Lock-Free Queues

XWOS’s C library provides lock-free queue functions. The implementation of lock-free queues depends on the CPU’s atomic operation instructions.

  • XWOS header file: xwos/lib/lfq.h
  • Interface: xwos/ospl/lfq.h
  • Implementation: xwosimpl_soc_lfq.h

Spinlocks

In multi-core systems, memory regions shared by multiple CPUs need to be protected by spinlocks. The implementation of spinlocks depends on atomic operation instructions and memory barrier instructions.

  • XWOS header files:
    • xwos/osal/lock/spinlock.h: Spinlock
    • xwos/osal/lock/seqlock.h: Spinlock derivative lock, sequential lock
  • Interface: xwos/ospl/spinlock.h
  • Implementation: xwosimpl_soc_spinlock.h

Interrupts

  • XWOS header file: xwos/osal/irq.h
  • Interface:
    • xwos/ospl/irq.h: Defines functions that the BSP needs to adapt;
  • Implementation:
    • xwosimpl_irq.h: Implements the functions defined in the XWOS porting layer;
  • Interrupt numbers:
    • XWOS defines the interrupt number type xwirq_t, which is a signed number:
    • Positive integers and 0: Represent SoC peripheral interrupts;
    • Negative numbers: Represent exceptions.
  • Interrupt priority requirements
The context switching interrupt is the lowest priority interrupt in the system
Context switching interrupt <= Tick timer interrupt <= Scheduler service interrupt
  • Functions that must be provided in the OS porting layer:
    • void xwospl_cpuirq_enable_lc(void): Enable local CPU interrupts
    • void xwospl_cpuirq_disable_lc(void): Disable local CPU interrupts
    • void xwospl_cpuirq_restore_lc(xwreg_t cpuirq): Restore local CPU interrupts
    • void xwospl_cpuirq_save_lc(xwreg_t * cpuirq): Save then disable local CPU interrupts
    • bool xwospl_cpuirq_test_lc(void): Test local CPU interrupt status
    • xwer_t xwospl_irq_get_id(xwirq_t * irqnbuf): Get the current interrupt number, also used for determining context
    • xwer_t xwospl_irq_enable(xwirq_t irqn): Enable a specific peripheral interrupt
    • xwer_t xwospl_irq_disable(xwirq_t irqn): Disable a specific peripheral interrupt
    • xwer_t xwospl_irq_save(xwirq_t irqn, xwreg_t * flag): Save a specific peripheral interrupt’s enabled state, then disable it
    • xwer_t xwospl_irq_restore(xwirq_t irqn, xwreg_t flag): Restore a specific peripheral interrupt’s enabled state

Hardware Timer

Each CPU requires a private hardware timer to provide tick interrupts. XWOS’s scheduling, timeout, and software timers are all based on tick interrupts.

  • Interface: xwos/ospl/syshwt.h
  • Implementation: xwosimpl_syshwt.h
  • Interface functions:
    • xwospl_syshwt_init(): Initialize the hardware timer
    • xwospl_syshwt_start(): Start the hardware timer
    • xwospl_syshwt_stop(): Stop the hardware timer
    • xwospl_syshwt_get_timeconfetti(): Return how many nanoseconds until the next timer interrupt

Scheduler

  • Interface: xwos/ospl/skd.h
  • Implementation: xwosimpl_skd.h
  • Interface functions:
    • xwospl_skd_init(struct xwospl_skd * xwskd): Initialize the scheduler
    • xwospl_skd_init_stack(): Initialize the scheduler object (thread) stack
    • xwospl_skd_get_id(): Get the current CPU ID
    • xwospl_skd_start(): Start the scheduler
    • xwospl_skd_suspend(): Suspend the scheduler, for power management
    • xwospl_skd_resume(): Resume the scheduler, for power management
    • xwospl_skd_req_swcx(): Request scheduling
    • xwospl_skd_isr_swcx(): Context switching interrupt
    • xwospl_thd_exit_lc(): Thread exit on the current CPU
    • xwospl_thd_freeze_lc(): Freeze the currently running thread on the current CPU
    • xwospl_thd_outmigrate(): Migrate a thread out of another CPU and prepare to migrate it to another CPU (multi-core only)
    • xwospl_thd_immigrate(): Migrate a thread to a target CPU (multi-core only)

Linker Script

The SoC Description Layer includes the SoC’s basic linker script. When using it, a XuanWuOS.lds must be defined in the cfg folder of the board directory, which contains the definition of the SoC’s address space, and then includes the linker script from the SoC Description Layer. For example: xwbd/WeActH750/cfg/XuanWuOS.lds only defines MEMORY and include xwcd/soc/arm/v7m/gcc/m7/stm32/h7.lds.

  • XWOS defines some sections. During linking, kernel code and kernel data can be placed in specific regions of the image file. This requires specifying in the linker script how these sections should be placed.
    • __xwos_init_code: Initialization code, placed in the .xwos.init.text section
    • __xwos_init_rodata: const data during the initialization phase, placed in the .xwos.init.rodata section
    • __xwos_exit_code: Exit code, placed in the .xwos.exit.text section
    • __xwos_exit_rodata: const data during the exit phase, placed in the .xwos.exit.rodata section
    • __xwos_ivt: Interrupt vector table, placed in the .xwos.ivt section
    • __xwos_isr: Interrupt code, placed in the .xwos.isr.text section
    • __xwos_bh: Interrupt bottom-half code, placed in the .xwos.isr.text section
    • __xwos_code: XWOS kernel code, placed in the .xwos.text section
    • __xwos_api: XWOS kernel API, placed in the .xwos.text section
    • __xwos_rodata: const data, placed in the .xwos.rodata section
    • __xwos_data: Global and static variables, placed in the .xwos.data section
  • If these custom sections are not needed, the above macros can be defined as empty. Correspondingly, code will be placed in the default .text section, data in the .data section, and const data in the .rodata section. These three sections are generated by the compiler by default.
  • When __xwos_data is defined as empty, the configuration XWKNCFG_RELOCATE_DATA in cfg/xwos.h should also be undefined or defined as 0.

Initialization Flow

XWOS provides a universal Boot Flow:

flowchart LR
    poweron("Power On") --> Low-Level Initialization Phase --> System Initialization Phase --> User Program

    subgraph Low-Level Initialization Phase
        direction TB
        arch_lowlevel_init["arch_lowlevel_init()"] --> cpu_lowlevel_init
        cpu_lowlevel_init["cpu_lowlevel_init()"] --> soc_lowlevel_init
        soc_lowlevel_init["soc_lowlevel_init()"] --> board_lowlevel_init
        board_lowlevel_init["board_lowlevel_init()"]
    end

    subgraph System Initialization Phase
        direction TB
        xwos_init["xwos_init()"] --> arch_relocate
        arch_relocate["arch_relocate()"] --> arch_init
        arch_init["arch_init()"] --> cpu_init
        cpu_init["cpu_init()"] --> soc_init
        soc_init["soc_init()"] --> board_init
    end

    subgraph User Program
        direction LR
        subgraph "xwos_main()"
            direction LR
            skd["Start Scheduler"]
            thd["Thread Initialization"]
            device["Device Driver Initialization"]
            libc["C/C++ Standard Library Initialization"]
            lua["Lua VM Initialization"]
        end
    end
  • Users can insert SoC initialization code at appropriate points in the flow, but note:
    • Global variables cannot be accessed during the lowlevel_init flow because the initial values of global variables have not yet been copied from flash to RAM;
    • C++ code can only be called after cxx_init;
  • In XWOS’s initialization flow, the interrupt controller and scheduler are initialized in soc_init(). If the user does not use XWOS’s initialization flow, the following must be called in order:
    • xwos_init(): Initialize the XWOS kernel;
    • Multi-core system:
      • xwmp_irqc_construct(): Initialize the interrupt controller for each CPU;
      • xwmp_irqc_register(): Register each CPU’s interrupt controller to the interrupt control subsystem;
      • xwmp_skd_init_lc(): Run this function once on each CPU to initialize its own scheduler;
    • Single-core system:
      • xwup_irqc_init(): Initialize the interrupt controller;
      • xwup_skd_init_lc(): Initialize the scheduler;

Build Integration Environment

XWOS provides a Build System that can run on Windows and Linux. Users can choose to use XWOS’s build integration environment or use other IDEs for building.

Using the XWOS Build System

  • XWOS’s build system independently compiles the kernel, xwmd modules, xwcd modules, xwem modules, xwam modules, and OEM modules into static libraries .a, and then links them together. The compilation configuration (header files, compiler options) for each module is completely independent, which can be understood as different sub-projects.
  • The build starts by executing the make command from the xwbd/board_name/ directory.

Using Other IDE Build Systems

  • Required header file search paths:
    • XWOS root directory XWOS
    • Architecture Description Layer (ADL) directory: e.g., for ARMv7m, xwcd/soc/arm/v7m/gcc
    • CPU Description Layer (CDL) directory: e.g., for ARMv7m7, xwcd/soc/arm/v7m/gcc/m7
    • SoC Description Layer (SDL) directory: e.g., for STM32H7, xwcd/soc/arm/v7m/gcc/m7/stm32h7x
    • Board directory: e.g., for the WeActMiniStm32H750 board, xwbd/WeActMiniStm32H750
  • Required source files:
    • Kernel directory xwos
    • Architecture Description Layer (ADL) directory: e.g., for ARMv7m, xwcd/soc/arm/v7m/gcc
    • CPU Description Layer (CDL) directory: e.g., for ARMv7m7, xwcd/soc/arm/v7m/gcc/m7
    • SoC Description Layer (SDL) directory: e.g., for STM32H7, xwcd/soc/arm/v7m/gcc/m7/stm32h7x
    • Board directory: e.g., for the WeActH750 board, xwbd/WeActH750
    • Middleware xwmd, driver framework xwcd/ds, third-party modules xwem, application modules xwam are not mandatory. If only the XWOS kernel is used, these can be removed.
  • If the other IDE’s toolchain is not gcc, the xwosimpl code in ADL, CDL, and SDL must be re-implemented. In this case, the code in xwcd/soc is also not needed.
  • Configuration needs to be modified: xwbd/WeActMiniStm32H750/cfg.
  • In the xwbd/WeActMiniStm32H750 directory, execute make cfg once to generate, then copy xwbd/WeActMiniStm32H750/wkspc/autogen.h to xwbd/WeActMiniStm32H750/cfg.
  • The IDE’s linker script needs to be configured.