diff options
Diffstat (limited to 'test/tx/cmake/module_qemu/src')
| -rw-r--r-- | test/tx/cmake/module_qemu/src/harness.c | 252 | ||||
| -rw-r--r-- | test/tx/cmake/module_qemu/src/harness.h | 70 | ||||
| -rw-r--r-- | test/tx/cmake/module_qemu/src/manager.ld | 77 | ||||
| -rw-r--r-- | test/tx/cmake/module_qemu/src/module_blob.S.in | 26 | ||||
| -rw-r--r-- | test/tx/cmake/module_qemu/src/module_preamble.S | 53 | ||||
| -rw-r--r-- | test/tx/cmake/module_qemu/src/module_shared.h | 68 | ||||
| -rw-r--r-- | test/tx/cmake/module_qemu/src/startup.S | 93 | ||||
| -rw-r--r-- | test/tx/cmake/module_qemu/src/tx_initialize_low_level.S | 87 |
8 files changed, 726 insertions, 0 deletions
diff --git a/test/tx/cmake/module_qemu/src/harness.c b/test/tx/cmake/module_qemu/src/harness.c new file mode 100644 index 00000000..1285de13 --- /dev/null +++ b/test/tx/cmake/module_qemu/src/harness.c @@ -0,0 +1,252 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module execution harness: manager side */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* The part of every manager image that is not the test: startup into ThreadX, + the Module Manager's memory, the fault notification, and reporting. + + Output and exit go through Arm semihosting rather than the board's UART, so + the same image reports identically on any QEMU machine with semihosting + enabled, and the simulation's exit status carries the verdict as well as the + result line the runner matches. Semihosting is only ever called from the + privileged manager thread or from a fault handler, never from a module. + + MISRA C:2023 deviations, confined to this test scaffolding: Rule 1.2 and + Directive 4.3 (inline assembly for the semihosting trap), and Rule 11.4 + (integer addresses of the shared area and of semihosting arguments). */ + +#include "harness.h" +#include "module_shared.h" + +#define HARNESS_STACK_SIZE ((ULONG) 2048UL) + +#define SEMIHOSTING_SYS_WRITE0 ((ULONG) 0x04UL) +#define SEMIHOSTING_SYS_EXIT ((ULONG) 0x18UL) +#define SEMIHOSTING_EXIT_SUCCESS ((ULONG) 0x20026UL) /* ADP_Stopped_ApplicationExit */ +#define SEMIHOSTING_EXIT_FAILURE ((ULONG) 0x20023UL) /* ADP_Stopped_RunTimeErrorUnknown */ + +UCHAR harness_module_memory[HARNESS_MODULE_MEMORY_SIZE]; +UCHAR harness_object_memory[HARNESS_OBJECT_MEMORY_SIZE]; + +volatile ULONG harness_fault_count; +TX_THREAD * volatile harness_fault_thread; +TXM_MODULE_INSTANCE * volatile harness_fault_module; +volatile ULONG harness_fault_address; +volatile ULONG harness_fault_status; + +static TX_THREAD harness_thread; +static ULONG harness_checks; +static ULONG harness_failures; + +extern TXM_MODULE_MANAGER_MEMORY_FAULT_INFO _txm_module_manager_memory_fault_info; + +int main(void); +VOID harness_hard_fault(VOID); +VOID harness_unexpected_exception(VOID); + + +/* Issue a semihosting call. */ +static ULONG harness_semihost(ULONG operation, ULONG parameter) +{ +register ULONG r0 __asm__("r0") = operation; +register ULONG r1 __asm__("r1") = parameter; + + __asm__ volatile ("bkpt 0xab" : "+r"(r0) : "r"(r1) : "memory"); + return(r0); +} + + +VOID harness_print(const CHAR *text) +{ + (VOID) harness_semihost(SEMIHOSTING_SYS_WRITE0, (ULONG) text); +} + + +VOID harness_value(const CHAR *label, ULONG value) +{ +static const CHAR digits[] = "0123456789abcdef"; +CHAR text[11]; +UINT index; + + text[0] = '0'; + text[1] = 'x'; + for (index = 0U; index < 8U; index++) + { + text[2U + index] = digits[(value >> (28U - (index * 4U))) & 0xFUL]; + } + text[10] = '\0'; + + harness_print(label); + harness_print(" = "); + harness_print(text); + harness_print("\n"); +} + + +VOID harness_expect(const CHAR *description, ULONG actual, ULONG expected) +{ + harness_checks++; + + if (actual != expected) + { + harness_failures++; + harness_print("FAIL: "); + harness_print(description); + harness_print("\n"); + harness_value(" expected", expected); + harness_value(" actual ", actual); + } +} + + +VOID harness_finish(VOID) +{ + harness_value("checks", harness_checks); + harness_value("failures", harness_failures); + + if ((harness_failures == 0UL) && (harness_checks != 0UL)) + { + harness_print("ALL CHECKS PASSED\n"); + (VOID) harness_semihost(SEMIHOSTING_SYS_EXIT, SEMIHOSTING_EXIT_SUCCESS); + } + else + { + harness_print("RESULT: FAILED\n"); + (VOID) harness_semihost(SEMIHOSTING_SYS_EXIT, SEMIHOSTING_EXIT_FAILURE); + } + + for (;;) + { + } +} + + +/* A fault the module port does not handle is a harness failure, whatever the + test was doing. */ +VOID harness_hard_fault(VOID) +{ + harness_print("[FAULT] HardFault\n"); + harness_print("RESULT: FAILED\n"); + (VOID) harness_semihost(SEMIHOSTING_SYS_EXIT, SEMIHOSTING_EXIT_FAILURE); + for (;;) + { + } +} + + +VOID harness_unexpected_exception(VOID) +{ + harness_print("[FAULT] unexpected exception\n"); + harness_print("RESULT: FAILED\n"); + (VOID) harness_semihost(SEMIHOSTING_SYS_EXIT, SEMIHOSTING_EXIT_FAILURE); + for (;;) + { + } +} + + +/* Called by the Module Manager after it has terminated a faulting module thread. */ +VOID harness_fault_notify(TX_THREAD *thread_ptr, TXM_MODULE_INSTANCE *module_instance) +{ + harness_fault_thread = thread_ptr; + harness_fault_module = module_instance; + harness_fault_address = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_mmfar; + harness_fault_status = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_cfsr; + harness_fault_count++; +} + + +VOID harness_shared_clear(VOID) +{ +ULONG index; + + for (index = 0UL; index < MODULE_SHARED_WORDS; index++) + { + MODULE_SHARED[index] = 0UL; + } +} + + +UINT harness_shared_grant(TXM_MODULE_INSTANCE *module_instance) +{ + return(txm_module_manager_external_memory_enable(module_instance, (VOID *) MODULE_SHARED_BASE, + MODULE_SHARED_SIZE, TXM_MODULE_MANAGER_SHARED_ATTRIBUTE_WRITE)); +} + + +UINT harness_wait_for_module(ULONG limit_ticks) +{ +ULONG start; +UINT done; + + start = tx_time_get(); + done = TX_FALSE; + while ((done == TX_FALSE) && ((tx_time_get() - start) < limit_ticks)) + { + if (MODULE_SHARED[MODULE_DONE] == MODULE_DONE_MAGIC) + { + done = TX_TRUE; + } + else + { + tx_thread_sleep(1); + } + } + + return(done); +} + + +static VOID harness_thread_entry(ULONG thread_input) +{ + (VOID) thread_input; + + harness_expect("txm_module_manager_initialize", + (ULONG) txm_module_manager_initialize((VOID *) harness_module_memory, HARNESS_MODULE_MEMORY_SIZE), + (ULONG) TX_SUCCESS); + harness_expect("txm_module_manager_object_pool_create", + (ULONG) txm_module_manager_object_pool_create(harness_object_memory, HARNESS_OBJECT_MEMORY_SIZE), + (ULONG) TX_SUCCESS); + harness_expect("txm_module_manager_memory_fault_notify", + (ULONG) txm_module_manager_memory_fault_notify(harness_fault_notify), + (ULONG) TX_SUCCESS); + + harness_test(); + harness_finish(); +} + + +int main(void) +{ + tx_kernel_enter(); + return(0); +} + + +VOID tx_application_define(VOID *first_unused_memory) +{ + (VOID) tx_thread_create(&harness_thread, "Module Manager Thread", harness_thread_entry, 0UL, + first_unused_memory, HARNESS_STACK_SIZE, 1U, 1U, TX_NO_TIME_SLICE, TX_AUTO_START); +} diff --git a/test/tx/cmake/module_qemu/src/harness.h b/test/tx/cmake/module_qemu/src/harness.h new file mode 100644 index 00000000..9145531b --- /dev/null +++ b/test/tx/cmake/module_qemu/src/harness.h @@ -0,0 +1,70 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module execution harness: manager-side reporting */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifndef HARNESS_H +#define HARNESS_H + +#include "tx_api.h" +#include "txm_module.h" + +/* Record one expectation; a failed one is printed and makes the image fail. */ +VOID harness_expect(const CHAR *description, ULONG actual, ULONG expected); + +/* Print a line, or a labelled value, over semihosting. */ +VOID harness_print(const CHAR *text); +VOID harness_value(const CHAR *label, ULONG value); + +/* Print the verdict and end the simulation; never returns. */ +VOID harness_finish(VOID); + +/* Wait, in ticks, until a module writes the done word or the limit passes. + Returns TX_TRUE if the module finished. */ +UINT harness_wait_for_module(ULONG limit_ticks); + +/* Clear the shared area and grant it to a module. */ +VOID harness_shared_clear(VOID); +UINT harness_shared_grant(TXM_MODULE_INSTANCE *module_instance); + +/* What the memory fault notification has seen. */ +extern volatile ULONG harness_fault_count; +extern TX_THREAD * volatile harness_fault_thread; +extern TXM_MODULE_INSTANCE * volatile harness_fault_module; +extern volatile ULONG harness_fault_address; +extern volatile ULONG harness_fault_status; + +VOID harness_fault_notify(TX_THREAD *thread_ptr, TXM_MODULE_INSTANCE *module_instance); + +/* The memory handed to the Module Manager, shared by every test image. */ +extern UCHAR harness_module_memory[]; +extern UCHAR harness_object_memory[]; + +#define HARNESS_MODULE_MEMORY_SIZE ((ULONG) 65536UL) +#define HARNESS_OBJECT_MEMORY_SIZE ((ULONG) 16384UL) + +/* Each test image defines this; it runs on the manager thread. */ +VOID harness_test(VOID); + +#endif diff --git a/test/tx/cmake/module_qemu/src/manager.ld b/test/tx/cmake/module_qemu/src/manager.ld new file mode 100644 index 00000000..9f6580e9 --- /dev/null +++ b/test/tx/cmake/module_qemu/src/manager.ld @@ -0,0 +1,77 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Module manager image for QEMU's MPS2 AN385 and AN386. Code, read-only data + and the embedded module images go in the 4 MB SSRAM1 at address 0, which the + board boots from; data, the main stack and the memory ThreadX hands out go + in the first megabyte of SSRAM2 at 0x20000000. The megabyte above that holds + the area the manager shares with its modules (module_shared.h), and nothing + the linker places reaches it. */ + +MEMORY +{ + CODE (rx) : ORIGIN = 0x00000000, LENGTH = 0x00400000 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00100000 +} + +ENTRY(reset_handler) + +SECTIONS +{ + .vectors : + { + KEEP(*(.vectors)) + } > CODE + + .text : + { + *(.text .text.*) + *(.rodata .rodata.*) + . = ALIGN(4); + } > CODE + + .ARM.exidx : + { + *(.ARM.exidx*) + } > CODE + + __data_load_start__ = LOADADDR(.data); + + .data : ALIGN(4) + { + __data_start__ = .; + *(.data .data.*) + . = ALIGN(4); + __data_end__ = .; + } > RAM AT > CODE + + .bss (NOLOAD) : ALIGN(4) + { + __bss_start__ = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .stack (NOLOAD) : ALIGN(8) + { + __stack_start__ = .; + . = . + 2048; + __stack_end__ = .; + } > RAM + + __RAM_segment_used_end__ = .; +} diff --git a/test/tx/cmake/module_qemu/src/module_blob.S.in b/test/tx/cmake/module_qemu/src/module_blob.S.in new file mode 100644 index 00000000..cd395df5 --- /dev/null +++ b/test/tx/cmake/module_qemu/src/module_blob.S.in @@ -0,0 +1,26 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +// Generated by CMake from module_blob.S.in: embeds one module's raw image in +// the manager image, as bytes rather than objects, so none of the module's +// symbols enter the manager's link. The manager loads it from here with +// txm_module_manager_memory_load. + + .section .rodata.@BLOB_SYMBOL@, "a" + .align 4 + .global @BLOB_SYMBOL@ +@BLOB_SYMBOL@: + .incbin "@BLOB_FILE@" + .align 4 diff --git a/test/tx/cmake/module_qemu/src/module_preamble.S b/test/tx/cmake/module_qemu/src/module_preamble.S new file mode 100644 index 00000000..4991544e --- /dev/null +++ b/test/tx/cmake/module_qemu/src/module_preamble.S @@ -0,0 +1,53 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +@ Module preamble shared by every test module. The property word comes from +@ the build, as TEST_MODULE_PROPERTIES, so one source serves the protected and +@ the privileged modules; everything else is the layout the Cortex-M module +@ ports document. Every module names its start function module_start. + +#ifndef TEST_MODULE_PROPERTIES +#error "TEST_MODULE_PROPERTIES must be defined by the build" +#endif + + .syntax unified + .section .preamble, "ax" + .align 4 + + .global __txm_module_preamble + .global module_start + .global _txm_module_thread_shell_entry + .global _txm_module_callback_request_thread_entry + +__txm_module_preamble: + .dc.l 0x4D4F4455 @ Module ID + .dc.l 0x6 @ Module major version + .dc.l 0x1 @ Module minor version + .dc.l 32 @ Preamble size in 32-bit words + .dc.l 0x7E57C0DE @ Application-defined module ID + .dc.l TEST_MODULE_PROPERTIES @ Properties: GNU, and the test's mode + .dc.l _txm_module_thread_shell_entry - . - 0 @ Shell entry + .dc.l module_start - . - 0 @ Start thread entry + .dc.l 0 @ Stop thread entry, none + .dc.l 1 @ Start/stop thread priority + .dc.l 1024 @ Start/stop thread stack size + .dc.l _txm_module_callback_request_thread_entry - . - 0 @ Callback thread entry + .dc.l 1 @ Callback thread priority + .dc.l 1024 @ Callback thread stack size + .dc.l __code_size__ @ Code size, from the link + .dc.l __data_size__ @ Data size, from the link + .rept 16 + .dc.l 0 @ Reserved + .endr diff --git a/test/tx/cmake/module_qemu/src/module_shared.h b/test/tx/cmake/module_qemu/src/module_shared.h new file mode 100644 index 00000000..7d239ce6 --- /dev/null +++ b/test/tx/cmake/module_qemu/src/module_shared.h @@ -0,0 +1,68 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module execution harness: manager/module shared area */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* A module reports what it did through a small area of RAM that the manager + grants it with txm_module_manager_external_memory_enable. The area is at a + fixed address, outside everything the manager image links, so that both + images can name it without either knowing the other's layout. Its base and + size meet the Cortex-M MPU's rule that a region is a power of two in size + and aligned to that size. */ + +#ifndef MODULE_SHARED_H +#define MODULE_SHARED_H + +#define MODULE_SHARED_BASE ((ULONG) 0x20100000UL) +#define MODULE_SHARED_SIZE ((ULONG) 256UL) +#define MODULE_SHARED_WORDS (MODULE_SHARED_SIZE / ((ULONG) sizeof(ULONG))) + +#define MODULE_SHARED ((volatile ULONG *) MODULE_SHARED_BASE) + +/* Word indices. The manager writes the inputs before it starts a module; the + module writes the rest. A module writes MODULE_DONE_MAGIC to MODULE_DONE + last, after every other word it reports. */ + +#define MODULE_IN_KERNEL_WORD ((ULONG) 0UL) /* Address of a kernel-only word */ +#define MODULE_IN_CYCLE ((ULONG) 1UL) /* Load cycle number, from 1 */ + +#define MODULE_OUT_STARTED ((ULONG) 8UL) /* Start thread ran */ +#define MODULE_OUT_OBJECT_STATUS ((ULONG) 9UL) /* Worst object allocation status */ +#define MODULE_OUT_CREATE_STATUS ((ULONG) 10UL) /* Worst object creation status */ +#define MODULE_OUT_QUEUE_VALUE ((ULONG) 11UL) /* Message received back */ +#define MODULE_OUT_SEMAPHORE_STATUS ((ULONG) 12UL) /* Semaphore get status */ +#define MODULE_OUT_SLEEP_TICKS ((ULONG) 13UL) /* Ticks elapsed across tx_thread_sleep */ +#define MODULE_OUT_WORKER_RUNS ((ULONG) 14UL) /* Worker thread iterations */ +#define MODULE_OUT_CYCLE_SEEN ((ULONG) 15UL) /* Load cycle the module observed */ +#define MODULE_OUT_KERNEL_READ_TRY ((ULONG) 16UL) /* Kernel word read about to happen */ +#define MODULE_OUT_KERNEL_READ_DONE ((ULONG) 17UL) /* Kernel word read completed */ +#define MODULE_OUT_KERNEL_VALUE ((ULONG) 18UL) /* Value read from the kernel word */ +#define MODULE_OUT_CONTROL ((ULONG) 19UL) /* CONTROL as seen by the start thread */ +#define MODULE_DONE ((ULONG) 31UL) + +#define MODULE_DONE_MAGIC ((ULONG) 0x0D0E0D0EUL) +#define MODULE_STARTED_MAGIC ((ULONG) 0x57A27EDUL) +#define MODULE_QUEUE_MESSAGE ((ULONG) 0x12345678UL) + +#endif diff --git a/test/tx/cmake/module_qemu/src/startup.S b/test/tx/cmake/module_qemu/src/startup.S new file mode 100644 index 00000000..f2f8442b --- /dev/null +++ b/test/tx/cmake/module_qemu/src/startup.S @@ -0,0 +1,93 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +@ Vector table and reset handler for the module execution harness on QEMU's +@ MPS2 boards. The fault vectors go to the module port's handlers, which is +@ the point: a module's MemManage fault has to reach the Module Manager for the +@ fault-notification test to mean anything. HardFault is never expected and +@ goes to the harness, which reports it and fails the image. + + .syntax unified + .thumb + + .section .vectors, "a" + .align 2 + .global _vectors +_vectors: + .word __stack_end__ @ Initial main stack pointer + .word reset_handler @ Reset + .word harness_unexpected_exception @ NMI + .word harness_hard_fault @ HardFault + .word MemManage_Handler @ MemManage, module port + .word BusFault_Handler @ BusFault, module port + .word UsageFault_Handler @ UsageFault, module port + .word 0 + .word 0 + .word 0 + .word 0 + .word __tx_SVCallHandler @ SVCall, module port + .word harness_unexpected_exception @ Debug monitor + .word 0 + .word __tx_PendSVHandler @ PendSV, module port + .word __tx_SysTickHandler @ SysTick, tx_initialize_low_level.S + .rept 32 + .word harness_unexpected_exception @ External interrupts, none enabled + .endr + + .section .text.reset_handler, "ax" + .align 2 + .global reset_handler + .thumb_func +reset_handler: + + @ Copy initialised data from its load address to RAM. + + LDR r0, =__data_load_start__ + LDR r1, =__data_start__ + LDR r2, =__data_end__ +copy_data: + CMP r1, r2 + BHS copy_data_done + LDR r3, [r0], #4 + STR r3, [r1], #4 + B copy_data +copy_data_done: + + @ Zero the uninitialised data. + + LDR r1, =__bss_start__ + LDR r2, =__bss_end__ + MOV r3, #0 +zero_bss: + CMP r1, r2 + BHS zero_bss_done + STR r3, [r1], #4 + B zero_bss +zero_bss_done: + +#ifdef __ARM_FP + @ Grant full access to CP10 and CP11 before anything touches the FPU. + + LDR r0, =0xE000ED88 @ CPACR + LDR r1, [r0] + ORR r1, r1, #(0xF << 20) + STR r1, [r0] + DSB + ISB +#endif + + BL main +reset_hang: + B reset_hang diff --git a/test/tx/cmake/module_qemu/src/tx_initialize_low_level.S b/test/tx/cmake/module_qemu/src/tx_initialize_low_level.S new file mode 100644 index 00000000..2e6ecfdf --- /dev/null +++ b/test/tx/cmake/module_qemu/src/tx_initialize_low_level.S @@ -0,0 +1,87 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +@ Low-level initialisation for the module execution harness on QEMU's MPS2 +@ AN385 (Cortex-M3) and AN386 (Cortex-M4) boards, both clocked at 25 MHz. + + .syntax unified + .thumb + + .global _tx_initialize_unused_memory + .global _tx_timer_interrupt + .global __RAM_segment_used_end__ + +SYSTEM_CLOCK = 25000000 +SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) - 1) + + .text + .align 2 + +@ VOID _tx_initialize_low_level(VOID) + + .global _tx_initialize_low_level + .thumb_func +_tx_initialize_low_level: + + CPSID i @ Interrupts stay off until the scheduler starts + + @ First free memory follows everything the image uses. + + LDR r0, =_tx_initialize_unused_memory + LDR r1, =__RAM_segment_used_end__ + ADD r1, r1, #4 + STR r1, [r0] + + @ Vector table base, in case the board boots with another. + + LDR r0, =0xE000ED08 @ VTOR + LDR r1, =_vectors + STR r1, [r0] + + @ SysTick at 100 Hz. + + LDR r0, =0xE000E000 + MOV r1, #0 + STR r1, [r0, #0x10] @ SysTick control: off + STR r1, [r0, #0x18] @ SysTick current value + LDR r1, =SYSTICK_CYCLES + STR r1, [r0, #0x14] @ SysTick reload + MOV r1, #0x7 + STR r1, [r0, #0x10] @ SysTick control: on, interrupt, core clock + + @ Handler priorities: the faults highest, SVCall and PendSV lowest, as the + @ module port requires. + + LDR r1, =0x00000000 @ Reserved, UsageFault, BusFault, MemManage + STR r1, [r0, #0xD18] + LDR r1, =0xFF000000 @ SVCall, reserved x3 + STR r1, [r0, #0xD1C] + LDR r1, =0x40FF0000 @ SysTick, PendSV, reserved, debug monitor + STR r1, [r0, #0xD20] + + BX lr + +@ SysTick: drive the ThreadX timer. + + .global __tx_SysTickHandler + .global SysTick_Handler + .thumb_func +__tx_SysTickHandler: + .thumb_func +SysTick_Handler: + PUSH {r0, lr} + BL _tx_timer_interrupt + POP {r0, lr} + BX lr |
