Added ARMv7-A SMP Linux build scripts(A5,A7,A9) (#674)

* ports: add Linux build scripts for Cortex-A5 SMP

* ports: fix Cortex-A5 SMP sample linking on Linux

* ports: add Linux build scripts for Cortex-A7 and A9 SMP

* ports: fix Cortex-A7 SMP assembly source path

* wip: add ATFE selection to Armv7 SMP scripts

* ports: complete Armv7 SMP Linux toolchain support

* ports: add local startup for Armv7 SMP samples

* ports: add license headers to Armv7 SMP scripts

* Dropped the preprocessing flag the file extension now carries

Two lines named assembly sources that #672 renamed. That change moved
twenty-nine files under gnu trees from .s to .S, because GAS runs the C
preprocessor on .S and not on .s: in a .s file every # line is a comment, so a
#define is never substituted and an #if/#else pair emits both arms. Four files
were silently doing the wrong thing as a result, including
ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.s, which ignored all
four of its own feature macros.

These scripts had worked around the same defect with -x assembler-with-cpp
rather than hitting it, which was correct when they were written. With the
rename the flag is redundant and the lowercase names no longer resolve, so
cortex_a5_smp/build_threadx.sh failed with "cc1: fatal error:
tx_initialize_low_level.s: No such file or directory". The other seven
references to those two files across these three scripts already named them
with a capital S.

Verified with the pinned Arm GNU 14.3.rel1 rather than the 13.2 that a distro
package supplies: build_threadx.sh and build_threadx_sample.sh both succeed for
a5, a7 and a9, all three link a sample_threadx.out, and scripts/check_gcc.sh
passes end to end with its example stage reading 45 of 45, up from 42.

Assisted-by: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Frédéric Desbiens <frederic.desbiens@eclipse-foundation.org>
This commit is contained in:
tardigrade
2026-09-09 16:30:23 -04:00
committed by GitHub
co-authored by Frédéric Desbiens
parent 383dd311cd
commit a8c84593dd
9 changed files with 1352 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,56 @@
#!/bin/sh
##############################################################################
# Copyright (c) 2026 Eclipse ThreadX contributors
#
# This program and the accompanying materials are made available under the
# terms of the MIT License which is available at
# https://opensource.org/licenses/MIT.
#
# SPDX-License-Identifier: MIT
##############################################################################
set -e
cd "$(dirname "$0")"
# this script builds the ThreadX sample image for the Cortex-A5 SMP port using
# GNU toolchain or llvm/clang toolchain (defaults to GNU).
: "${TOOLCHAIN:=gnu}"
case "${TOOLCHAIN}" in
gnu)
CC="arm-none-eabi-gcc"
TARGET_FLAGS=""
# GNU and Clang use different driver syntax for selecting the program's
# entry-point symbol.
ENTRY_FLAG="-e Vectors"
# Bare-metal C libraries require syscall support. GNU uses newlib's nosys stubs
# while ATFE requires a semihost library.
SYSCALL_LIB="--specs=nosys.specs"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
TARGET_FLAGS="--target=arm-none-eabi"
ENTRY_FLAG="-Wl,--entry=Vectors"
SYSCALL_LIB="-lsemihost"
;;
*)
echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2
exit 1
;;
esac
"${CC}" ${TARGET_FLAGS} -c -g -I../../../../common_smp/inc -I../inc -mcpu=cortex-a5 sample_threadx.c
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 startup.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 crt0.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 MP_GIC.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 MP_SCU.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 MP_Mutexes.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 MP_PrivateTimer.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 v7.S
"${CC}" ${TARGET_FLAGS} -g -mcpu=cortex-a5 -nostartfiles \
-T sample_threadx.ld \
${ENTRY_FLAG} \
${SYSCALL_LIB} \
-o sample_threadx.out \
MP_PrivateTimer.o MP_GIC.o MP_Mutexes.o MP_SCU.o \
sample_threadx.o startup.o crt0.o v7.o tx.a \
-Wl,-M > sample_threadx.map
@@ -0,0 +1,101 @@
.syntax unified
#if defined(THUMB_MODE)
.thumb
#else
.arm
#endif
/* .text is used instead of .section .text so it works with arm-aout too. */
.text
.align 0
#if defined(THUMB_MODE)
.thumb_func
#endif
.global _mainCRTStartup
_mainCRTStartup:
#if defined(THUMB_MODE)
.thumb_func
#endif
.global _start
_start:
#if defined(THUMB_MODE)
.thumb_func
#endif
.global start
start:
/* Start by setting up a stack */
/* Set up the stack pointer to a fixed value */
ldr r3, .LC0
mov sp, r3
/* Setup a default stack-limit in case the code has been
compiled with "-mapcs-stack-check". Hard-wiring this value
is not ideal, since there is currently no support for
checking that the heap and stack have not collided, or that
this default 64k is enough for the program being executed.
However, it ensures that this simple crt0 world will not
immediately cause an overflow event: */
sub sl, sp, #64 << 10 /* Still assumes 256bytes below sl */
mov a2, #0 /* Second arg: fill value */
mov fp, a2 /* Null frame pointer */
mov r7, a2 /* Null frame pointer for Thumb */
ldr a1, .LC1 /* First arg: start of memory block */
ldr a3, .LC2
sub a3, a3, a1 /* Third arg: length of block */
bl memset
mov r0, #0 /* no arguments */
mov r1, #0 /* no argv either */
#ifdef __USES_INITFINI__
/* Some arm/elf targets use the .init and .fini sections
to create constructors and destructors, and for these
targets we need to call the _init function and arrange
for _fini to be called at program exit. */
mov r4, r0
mov r5, r1
/* ldr r0, .Lfini */
bl atexit
/* bl init */
mov r0, r4
mov r1, r5
#endif
bl main
bl exit /* Should not return. */
/* For Thumb, constants must be after the code since only
positive offsets are supported for PC relative addresses. */
.align 0
.LC0:
.LC1:
.word __bss_start__
.LC2:
.word __bss_end__
/*
#ifdef __USES_INITFINI__
.Lfini:
.word _fini
#endif */
/* Return ... */
bx lr
.global _fini
.type _fini,function
_fini:
BX lr // Return to caller
/* Workspace for Angel calls. */
.data
/* Data returned by monitor SWI. */
.global __stack_base__
HeapBase: .word 0
HeapLimit: .word 0
__stack_base__: .word 0
StackLimit: .word 0
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,54 @@
#!/bin/sh
##############################################################################
# Copyright (c) 2026 Eclipse ThreadX contributors
#
# This program and the accompanying materials are made available under the
# terms of the MIT License which is available at
# https://opensource.org/licenses/MIT.
#
# SPDX-License-Identifier: MIT
##############################################################################
set -e
cd "$(dirname "$0")"
# this script builds the ThreadX sample image for the Cortex-A7 SMP port using
# GNU toolchain or llvm/clang toolchain (defaults to GNU).
: "${TOOLCHAIN:=gnu}"
case "${TOOLCHAIN}" in
gnu)
CC="arm-none-eabi-gcc"
TARGET_FLAGS=""
# GNU and Clang use different driver syntax for selecting the program's
# entry-point symbol.
ENTRY_FLAG="-e Vectors"
# Bare-metal C libraries require syscall support. GNU uses newlib's nosys stubs
# while ATFE requires a semihost library.
SYSCALL_LIB="--specs=nosys.specs"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
TARGET_FLAGS="--target=arm-none-eabi"
ENTRY_FLAG="-Wl,--entry=Vectors"
SYSCALL_LIB="-lsemihost"
;;
*)
echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2
exit 1
;;
esac
"${CC}" ${TARGET_FLAGS} -c -g -I../../../../common_smp/inc -I../inc -mcpu=cortex-a7 sample_threadx.c
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 startup.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 crt0.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 MP_GIC.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 MP_Mutexes.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 v7.S
"${CC}" ${TARGET_FLAGS} -g -mcpu=cortex-a7 -nostartfiles \
-T sample_threadx.ld \
${SYSCALL_LIB} \
${ENTRY_FLAG} \
-o sample_threadx.out \
MP_GIC.o MP_Mutexes.o \
sample_threadx.o startup.o crt0.o v7.o tx.a \
-Wl,-M > sample_threadx.map
@@ -0,0 +1,101 @@
.syntax unified
#if defined(THUMB_MODE)
.thumb
#else
.arm
#endif
/* .text is used instead of .section .text so it works with arm-aout too. */
.text
.align 0
#if defined(THUMB_MODE)
.thumb_func
#endif
.global _mainCRTStartup
_mainCRTStartup:
#if defined(THUMB_MODE)
.thumb_func
#endif
.global _start
_start:
#if defined(THUMB_MODE)
.thumb_func
#endif
.global start
start:
/* Start by setting up a stack */
/* Set up the stack pointer to a fixed value */
ldr r3, .LC0
mov sp, r3
/* Setup a default stack-limit in case the code has been
compiled with "-mapcs-stack-check". Hard-wiring this value
is not ideal, since there is currently no support for
checking that the heap and stack have not collided, or that
this default 64k is enough for the program being executed.
However, it ensures that this simple crt0 world will not
immediately cause an overflow event: */
sub sl, sp, #64 << 10 /* Still assumes 256bytes below sl */
mov a2, #0 /* Second arg: fill value */
mov fp, a2 /* Null frame pointer */
mov r7, a2 /* Null frame pointer for Thumb */
ldr a1, .LC1 /* First arg: start of memory block */
ldr a3, .LC2
sub a3, a3, a1 /* Third arg: length of block */
bl memset
mov r0, #0 /* no arguments */
mov r1, #0 /* no argv either */
#ifdef __USES_INITFINI__
/* Some arm/elf targets use the .init and .fini sections
to create constructors and destructors, and for these
targets we need to call the _init function and arrange
for _fini to be called at program exit. */
mov r4, r0
mov r5, r1
/* ldr r0, .Lfini */
bl atexit
/* bl init */
mov r0, r4
mov r1, r5
#endif
bl main
bl exit /* Should not return. */
/* For Thumb, constants must be after the code since only
positive offsets are supported for PC relative addresses. */
.align 0
.LC0:
.LC1:
.word __bss_start__
.LC2:
.word __bss_end__
/*
#ifdef __USES_INITFINI__
.Lfini:
.word _fini
#endif */
/* Return ... */
bx lr
.global _fini
.type _fini,function
_fini:
BX lr // Return to caller
/* Workspace for Angel calls. */
.data
/* Data returned by monitor SWI. */
.global __stack_base__
HeapBase: .word 0
HeapLimit: .word 0
__stack_base__: .word 0
StackLimit: .word 0
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,54 @@
#!/bin/sh
##############################################################################
# Copyright (c) 2026 Eclipse ThreadX contributors
#
# This program and the accompanying materials are made available under the
# terms of the MIT License which is available at
# https://opensource.org/licenses/MIT.
#
# SPDX-License-Identifier: MIT
##############################################################################
set -e
cd "$(dirname "$0")"
# this script builds the ThreadX sample image for the Cortex-A9 SMP port using
# GNU toolchain or llvm/clang toolchain (defaults to GNU).
: "${TOOLCHAIN:=gnu}"
case "${TOOLCHAIN}" in
gnu)
CC="arm-none-eabi-gcc"
TARGET_FLAGS="" # GNU and Clang use different driver syntax for selecting the program's
# entry-point symbol.
ENTRY_FLAG="-e Vectors"
# Bare-metal C libraries require syscall support. GNU uses newlib's nosys stubs
# while ATFE requires a semihost library.
SYSCALL_LIB="--specs=nosys.specs"
;;
atfe)
CC="${ATFE_CLANG:-clang}"
TARGET_FLAGS="--target=arm-none-eabi"
ENTRY_FLAG="-Wl,--entry=Vectors"
SYSCALL_LIB="-lsemihost"
;;
*)
echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2
exit 1
;;
esac
"${CC}" ${TARGET_FLAGS} -c -g -I../../../../common_smp/inc -I../inc -mcpu=cortex-a9 sample_threadx.c
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 startup.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 crt0.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 MP_GIC.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 MP_SCU.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 MP_Mutexes.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 MP_PrivateTimer.S
"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 v7.S
"${CC}" ${TARGET_FLAGS} -g -mcpu=cortex-a9 -nostartfiles \
-T sample_threadx.ld \
${ENTRY_FLAG} \
${SYSCALL_LIB} \
-o sample_threadx.out MP_PrivateTimer.o MP_GIC.o MP_Mutexes.o MP_SCU.o \
sample_threadx.o startup.o crt0.o v7.o tx.a \
-Wl,-M > sample_threadx.map
@@ -0,0 +1,101 @@
.syntax unified
#if defined(THUMB_MODE)
.thumb
#else
.arm
#endif
/* .text is used instead of .section .text so it works with arm-aout too. */
.text
.align 0
#if defined(THUMB_MODE)
.thumb_func
#endif
.global _mainCRTStartup
_mainCRTStartup:
#if defined(THUMB_MODE)
.thumb_func
#endif
.global _start
_start:
#if defined(THUMB_MODE)
.thumb_func
#endif
.global start
start:
/* Start by setting up a stack */
/* Set up the stack pointer to a fixed value */
ldr r3, .LC0
mov sp, r3
/* Setup a default stack-limit in case the code has been
compiled with "-mapcs-stack-check". Hard-wiring this value
is not ideal, since there is currently no support for
checking that the heap and stack have not collided, or that
this default 64k is enough for the program being executed.
However, it ensures that this simple crt0 world will not
immediately cause an overflow event: */
sub sl, sp, #64 << 10 /* Still assumes 256bytes below sl */
mov a2, #0 /* Second arg: fill value */
mov fp, a2 /* Null frame pointer */
mov r7, a2 /* Null frame pointer for Thumb */
ldr a1, .LC1 /* First arg: start of memory block */
ldr a3, .LC2
sub a3, a3, a1 /* Third arg: length of block */
bl memset
mov r0, #0 /* no arguments */
mov r1, #0 /* no argv either */
#ifdef __USES_INITFINI__
/* Some arm/elf targets use the .init and .fini sections
to create constructors and destructors, and for these
targets we need to call the _init function and arrange
for _fini to be called at program exit. */
mov r4, r0
mov r5, r1
/* ldr r0, .Lfini */
bl atexit
/* bl init */
mov r0, r4
mov r1, r5
#endif
bl main
bl exit /* Should not return. */
/* For Thumb, constants must be after the code since only
positive offsets are supported for PC relative addresses. */
.align 0
.LC0:
.LC1:
.word __bss_start__
.LC2:
.word __bss_end__
/*
#ifdef __USES_INITFINI__
.Lfini:
.word _fini
#endif */
/* Return ... */
bx lr
.global _fini
.type _fini,function
_fini:
BX lr // Return to caller
/* Workspace for Angel calls. */
.data
/* Data returned by monitor SWI. */
.global __stack_base__
HeapBase: .word 0
HeapLimit: .word 0
__stack_base__: .word 0
StackLimit: .word 0