diff options
Diffstat (limited to 'ports/cortex_m52/gnu/src')
16 files changed, 3032 insertions, 0 deletions
diff --git a/ports/cortex_m52/gnu/src/tx_misra.S b/ports/cortex_m52/gnu/src/tx_misra.S new file mode 100644 index 00000000..10548671 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_misra.S @@ -0,0 +1,723 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ThreadX MISRA Compliance */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + #define SHT_PROGBITS 0x1 + + .global __aeabi_memset + .global _tx_thread_current_ptr + .global _tx_thread_interrupt_disable + .global _tx_thread_interrupt_restore + .global _tx_thread_stack_analyze + .global _tx_thread_stack_error_handler + .global _tx_thread_system_state +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_trace_buffer_current_ptr + .global _tx_trace_buffer_end_ptr + .global _tx_trace_buffer_start_ptr + .global _tx_trace_event_enable_bits + .global _tx_trace_full_notify_function + .global _tx_trace_header_ptr +#endif + + .global _tx_misra_always_true + .global _tx_misra_block_pool_to_uchar_pointer_convert + .global _tx_misra_byte_pool_to_uchar_pointer_convert + .global _tx_misra_char_to_uchar_pointer_convert + .global _tx_misra_const_char_to_char_pointer_convert +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_entry_to_uchar_pointer_convert +#endif + .global _tx_misra_indirect_void_to_uchar_pointer_convert + .global _tx_misra_memset + .global _tx_misra_message_copy +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_object_to_uchar_pointer_convert +#endif + .global _tx_misra_pointer_to_ulong_convert + .global _tx_misra_status_get + .global _tx_misra_thread_stack_check +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_time_stamp_get +#endif + .global _tx_misra_timer_indirect_to_void_pointer_convert + .global _tx_misra_timer_pointer_add + .global _tx_misra_timer_pointer_dif +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_trace_event_insert +#endif + .global _tx_misra_uchar_pointer_add + .global _tx_misra_uchar_pointer_dif + .global _tx_misra_uchar_pointer_sub + .global _tx_misra_uchar_to_align_type_pointer_convert + .global _tx_misra_uchar_to_block_pool_pointer_convert +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_uchar_to_entry_pointer_convert + .global _tx_misra_uchar_to_header_pointer_convert +#endif + .global _tx_misra_uchar_to_indirect_byte_pool_pointer_convert + .global _tx_misra_uchar_to_indirect_uchar_pointer_convert +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_uchar_to_object_pointer_convert +#endif + .global _tx_misra_uchar_to_void_pointer_convert + .global _tx_misra_ulong_pointer_add + .global _tx_misra_ulong_pointer_dif + .global _tx_misra_ulong_pointer_sub + .global _tx_misra_ulong_to_pointer_convert + .global _tx_misra_ulong_to_thread_pointer_convert + .global _tx_misra_user_timer_pointer_get + .global _tx_misra_void_to_block_pool_pointer_convert + .global _tx_misra_void_to_byte_pool_pointer_convert + .global _tx_misra_void_to_event_flags_pointer_convert + .global _tx_misra_void_to_indirect_uchar_pointer_convert + .global _tx_misra_void_to_mutex_pointer_convert + .global _tx_misra_void_to_queue_pointer_convert + .global _tx_misra_void_to_semaphore_pointer_convert + .global _tx_misra_void_to_thread_pointer_convert + .global _tx_misra_void_to_uchar_pointer_convert + .global _tx_misra_void_to_ulong_pointer_convert + .global _tx_misra_ipsr_get + .global _tx_misra_control_get + .global _tx_misra_control_set +#ifdef __ARM_FP + .global _tx_misra_fpccr_get + .global _tx_misra_vfp_touch +#endif + + .global _tx_misra_event_flags_group_not_used + .global _tx_misra_event_flags_set_notify_not_used + .global _tx_misra_queue_not_used + .global _tx_misra_queue_send_notify_not_used + .global _tx_misra_semaphore_not_used + .global _tx_misra_semaphore_put_notify_not_used + .global _tx_misra_thread_entry_exit_notify_not_used + .global _tx_misra_thread_not_used + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .align 4 + .syntax unified + .thumb_func +_tx_misra_memset: + PUSH {R4,LR} + MOVS R4,R0 + MOVS R0,R2 + MOVS R2,R1 + MOVS R1,R0 + MOVS R0,R4 + BL __aeabi_memset + POP {R4,PC} // return + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_uchar_pointer_add: + ADD R0,R0,R1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_uchar_pointer_sub: + RSBS R1,R1,#+0 + ADD R0,R0,R1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_uchar_pointer_dif: + SUBS R0,R0,R1 + BX LR // return + + +/************************************************************************************************************************************/ +/************************************************************************************************************************************/ +/** */ +/** This single function serves all of the below prototypes. */ +/** */ +/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */ +/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */ +/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */ +/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */ +/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */ +/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */ +/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */ +/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */ +/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */ +/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */ +/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */ +/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */ +/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */ +/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */ +/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */ +/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */ +/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */ +/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */ +/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */ +/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */ +/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */ +/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */ +/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */ +/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */ +/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */ +/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */ +/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */ +/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */ +/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */ +/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */ +/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */ +/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */ +/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */ +/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */ +/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */ +/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */ +/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */ +/** */ +/************************************************************************************************************************************/ +/************************************************************************************************************************************/ + .text + .thumb_func +_tx_misra_pointer_to_ulong_convert: +_tx_misra_ulong_to_pointer_convert: +_tx_misra_indirect_void_to_uchar_pointer_convert: +_tx_misra_uchar_to_indirect_uchar_pointer_convert: +_tx_misra_block_pool_to_uchar_pointer_convert: +_tx_misra_void_to_block_pool_pointer_convert: +_tx_misra_void_to_uchar_pointer_convert: +_tx_misra_uchar_to_block_pool_pointer_convert: +_tx_misra_void_to_indirect_uchar_pointer_convert: +_tx_misra_void_to_byte_pool_pointer_convert: +_tx_misra_byte_pool_to_uchar_pointer_convert: +_tx_misra_uchar_to_align_type_pointer_convert: +_tx_misra_uchar_to_indirect_byte_pool_pointer_convert: +_tx_misra_void_to_event_flags_pointer_convert: +_tx_misra_void_to_ulong_pointer_convert: +_tx_misra_void_to_mutex_pointer_convert: +_tx_misra_void_to_queue_pointer_convert: +_tx_misra_void_to_semaphore_pointer_convert: +_tx_misra_uchar_to_void_pointer_convert: +_tx_misra_ulong_to_thread_pointer_convert: +_tx_misra_timer_indirect_to_void_pointer_convert: +_tx_misra_const_char_to_char_pointer_convert: +_tx_misra_void_to_thread_pointer_convert: +#ifdef TX_ENABLE_EVENT_TRACE +_tx_misra_object_to_uchar_pointer_convert: +_tx_misra_uchar_to_object_pointer_convert: +_tx_misra_uchar_to_header_pointer_convert: +_tx_misra_uchar_to_entry_pointer_convert: +_tx_misra_entry_to_uchar_pointer_convert: +#endif +_tx_misra_char_to_uchar_pointer_convert: +_tx_misra_event_flags_group_not_used: +_tx_misra_event_flags_set_notify_not_used: +_tx_misra_queue_not_used: +_tx_misra_queue_send_notify_not_used: +_tx_misra_semaphore_not_used: +_tx_misra_semaphore_put_notify_not_used: +_tx_misra_thread_entry_exit_notify_not_used: +_tx_misra_thread_not_used: + + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_ulong_pointer_add: + ADD R0,R0,R1, LSL #+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_ulong_pointer_sub: + MVNS R2,#+3 + MULS R1,R2,R1 + ADD R0,R0,R1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_ulong_pointer_dif: + SUBS R0,R0,R1 + ASRS R0,R0,#+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */ +/** UINT size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_message_copy: + PUSH {R4,R5} + LDR R3,[R0, #+0] + LDR R4,[R1, #+0] + LDR R5,[R3, #+0] + STR R5,[R4, #+0] + ADDS R4,R4,#+4 + ADDS R3,R3,#+4 + CMP R2,#+2 + BCC.N _tx_misra_message_copy_0 + SUBS R2,R2,#+1 + B.N _tx_misra_message_copy_1 +_tx_misra_message_copy_2: + LDR R5,[R3, #+0] + STR R5,[R4, #+0] + ADDS R4,R4,#+4 + ADDS R3,R3,#+4 + SUBS R2,R2,#+1 +_tx_misra_message_copy_1: + CMP R2,#+0 + BNE.N _tx_misra_message_copy_2 +_tx_misra_message_copy_0: + STR R3,[R0, #+0] + STR R4,[R1, #+0] + POP {R4,R5} + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */ +/** TX_TIMER_INTERNAL **ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_timer_pointer_dif: + SUBS R0,R0,R1 + ASRS R0,R0,#+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */ +/** **ptr1, ULONG size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_timer_pointer_add: + ADD R0,R0,R1, LSL #+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */ +/** *internal_timer, TX_TIMER **user_timer); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_user_timer_pointer_get: + SUBS R0,#8 + STR R0,[R1, #+0] + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */ +/** VOID **highest_stack); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_thread_stack_check: + PUSH {R3-R5,LR} + MOVS R4,R0 + MOVS R5,R1 + BL _tx_thread_interrupt_disable + CMP R4,#+0 + BEQ.N _tx_misra_thread_stack_check_0 + LDR R1,[R4, #+0] + LDR R2,=0x54485244 + CMP R1,R2 + BNE.N _tx_misra_thread_stack_check_0 + LDR R1,[R4, #+8] + LDR R2,[R5, #+0] + CMP R1,R2 + BCS.N _tx_misra_thread_stack_check_1 + LDR R1,[R4, #+8] + STR R1,[R5, #+0] +_tx_misra_thread_stack_check_1: + LDR R1,[R4, #+12] + LDR R1,[R1, #+0] + CMP R1,#-269488145 + BNE.N _tx_misra_thread_stack_check_2 + LDR R1,[R4, #+16] + LDR R1,[R1, #+1] + CMP R1,#-269488145 + BNE.N _tx_misra_thread_stack_check_2 + LDR R1,[R5, #+0] + LDR R2,[R4, #+12] + CMP R1,R2 + BCS.N _tx_misra_thread_stack_check_3 +_tx_misra_thread_stack_check_2: + BL _tx_thread_interrupt_restore + MOVS R0,R4 + BL _tx_thread_stack_error_handler + BL _tx_thread_interrupt_disable +_tx_misra_thread_stack_check_3: + LDR R1,[R5, #+0] + LDR R1,[R1, #-4] + CMP R1,#-269488145 + BEQ.N _tx_misra_thread_stack_check_0 + BL _tx_thread_interrupt_restore + MOVS R0,R4 + BL _tx_thread_stack_analyze + BL _tx_thread_interrupt_disable +_tx_misra_thread_stack_check_0: + BL _tx_thread_interrupt_restore + POP {R0,R4,R5,PC} // return + +#ifdef TX_ENABLE_EVENT_TRACE + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_trace_event_insert(ULONG event_id, */ +/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */ +/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_trace_event_insert: + PUSH {R3-R7,LR} + LDR.N R4,DataTable2_1 + LDR R4,[R4, #+0] + CMP R4,#+0 + BEQ.N _tx_misra_trace_event_insert_0 + LDR.N R5,DataTable2_2 + LDR R5,[R5, #+0] + LDR R6,[SP, #+28] + TST R5,R6 + BEQ.N _tx_misra_trace_event_insert_0 + LDR.N R5,DataTable2_3 + LDR R5,[R5, #+0] + LDR.N R6,DataTable2_4 + LDR R6,[R6, #+0] + CMP R5,#+0 + BNE.N _tx_misra_trace_event_insert_1 + LDR R5,[R6, #+44] + LDR R7,[R6, #+60] + LSLS R7,R7,#+16 + ORRS R7,R7,#0x80000000 + ORRS R5,R7,R5 + B.N _tx_misra_trace_event_insert_2 +_tx_misra_trace_event_insert_1: + CMP R5,#-252645136 + BCS.N _tx_misra_trace_event_insert_3 + MOVS R5,R6 + MOVS R6,#-1 + B.N _tx_misra_trace_event_insert_2 +_tx_misra_trace_event_insert_3: + MOVS R6,#-252645136 + MOVS R5,#+0 +_tx_misra_trace_event_insert_2: + STR R6,[R4, #+0] + STR R5,[R4, #+4] + STR R0,[R4, #+8] + LDR R0,[SP, #+32] + STR R0,[R4, #+12] + STR R1,[R4, #+16] + STR R2,[R4, #+20] + STR R3,[R4, #+24] + LDR R0,[SP, #+24] + STR R0,[R4, #+28] + ADDS R4,R4,#+32 + LDR.N R0,DataTable2_5 + LDR R0,[R0, #+0] + CMP R4,R0 + BCC.N _tx_misra_trace_event_insert_4 + LDR.N R0,DataTable2_6 + LDR R4,[R0, #+0] + LDR.N R0,DataTable2_1 + STR R4,[R0, #+0] + LDR.N R0,DataTable2_7 + LDR R0,[R0, #+0] + STR R4,[R0, #+32] + LDR.N R0,DataTable2_8 + LDR R0,[R0, #+0] + CMP R0,#+0 + BEQ.N _tx_misra_trace_event_insert_0 + LDR.N R0,DataTable2_7 + LDR R0,[R0, #+0] + LDR.N R1,DataTable2_8 + LDR R1,[R1, #+0] + BLX R1 + B.N _tx_misra_trace_event_insert_0 +_tx_misra_trace_event_insert_4: + LDR.N R0,DataTable2_1 + STR R4,[R0, #+0] + LDR.N R0,DataTable2_7 + LDR R0,[R0, #+0] + STR R4,[R0, #+32] +_tx_misra_trace_event_insert_0: + POP {R0,R4-R7,PC} // return + + + .data +DataTable2_1: + .word _tx_trace_buffer_current_ptr + + .data +DataTable2_2: + .word _tx_trace_event_enable_bits + + .data +DataTable2_5: + .word _tx_trace_buffer_end_ptr + + .data +DataTable2_6: + .word _tx_trace_buffer_start_ptr + + .data +DataTable2_7: + .word _tx_trace_header_ptr + + .data +DataTable2_8: + .word _tx_trace_full_notify_function + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_time_stamp_get(VOID); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_time_stamp_get: + MOVS R0,#+0 + BX LR // return + +#endif + + .data +DataTable2_3: + .word _tx_thread_system_state + + .data +DataTable2_4: + .word _tx_thread_current_ptr + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UINT _tx_misra_always_true(void); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_always_true: + MOVS R0,#+1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UINT _tx_misra_status_get(UINT status); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_status_get: + MOVS R0,#+0 + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_ipsr_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_ipsr_get: + MRS R0, IPSR + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_control_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_control_get: + MRS R0, CONTROL + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** void _tx_misra_control_set(ULONG value); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_control_set: + MSR CONTROL, R0 + BX LR // return + + +#ifdef __ARM_FP + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_fpccr_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_fpccr_get: + LDR r0, =0xE000EF34 // Build FPCCR address + LDR r0, [r0] // Load FPCCR value + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** void _tx_misra_vfp_touch(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_vfp_touch: + vmov.f32 s0, s0 + BX LR // return + +#endif + + + .data + .word 0 diff --git a/ports/cortex_m52/gnu/src/tx_thread_context_restore.S b/ports/cortex_m52/gnu/src/tx_thread_context_restore.S new file mode 100644 index 00000000..ffcfed46 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_context_restore.S @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + .global _tx_execution_isr_exit +#endif +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_context_restore Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is not needed for Cortex-M. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* [_tx_execution_isr_exit] Execution profiling ISR exit */ +/* */ +/* CALLED BY */ +/* */ +/* ISRs Interrupt Service Routines */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_context_restore(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_context_restore + .thumb_func +.type _tx_thread_context_restore, function +_tx_thread_context_restore: + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the ISR exit function to indicate an ISR is complete. */ + PUSH {r0, lr} // Save return address + BL _tx_execution_isr_exit // Call the ISR exit function + POP {r0, lr} // Recover return address +#endif + + BX lr +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_context_save.S b/ports/cortex_m52/gnu/src/tx_thread_context_save.S new file mode 100644 index 00000000..e1d44619 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_context_save.S @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + .global _tx_execution_isr_enter +#endif +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_context_save Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is not needed for Cortex-M. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* [_tx_execution_isr_enter] Execution profiling ISR enter */ +/* */ +/* CALLED BY */ +/* */ +/* ISRs */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_context_save(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_context_save + .thumb_func +.type _tx_thread_context_save, function +_tx_thread_context_save: + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the ISR enter function to indicate an ISR is starting. */ + PUSH {r0, lr} // Save return address + BL _tx_execution_isr_enter // Call the ISR enter function + POP {r0, lr} // Recover return address +#endif + + BX lr +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_interrupt_control.S b/ports/cortex_m52/gnu/src/tx_thread_interrupt_control.S new file mode 100644 index 00000000..2f304ba4 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_interrupt_control.S @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_control Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for changing the interrupt lockout */ +/* posture of the system. */ +/* */ +/* INPUT */ +/* */ +/* new_posture New interrupt lockout posture */ +/* */ +/* OUTPUT */ +/* */ +/* old_posture Old interrupt lockout posture */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// UINT _tx_thread_interrupt_control(UINT new_posture) +// { + .section .text + .balign 4 + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_interrupt_control + .thumb_func +.type _tx_thread_interrupt_control, function +_tx_thread_interrupt_control: +#ifdef TX_PORT_USE_BASEPRI + MRS r1, BASEPRI // Pickup current interrupt posture + MSR BASEPRI, r0 // Apply the new interrupt posture + MOV r0, r1 // Transfer old to return register +#else + MRS r1, PRIMASK // Pickup current interrupt lockout + MSR PRIMASK, r0 // Apply the new interrupt lockout + MOV r0, r1 // Transfer old to return register +#endif + BX lr // Return to caller +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_interrupt_disable.S b/ports/cortex_m52/gnu/src/tx_thread_interrupt_disable.S new file mode 100644 index 00000000..be6e1e87 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_interrupt_disable.S @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_disable Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for disabling interrupts and returning */ +/* the previous interrupt lockout posture. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* old_posture Old interrupt lockout posture */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// UINT _tx_thread_interrupt_disable(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_interrupt_disable + .thumb_func +.type _tx_thread_interrupt_disable, function +_tx_thread_interrupt_disable: + /* Return current interrupt lockout posture. */ +#ifdef TX_PORT_USE_BASEPRI + MRS r0, BASEPRI + LDR r1, =TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + MRS r0, PRIMASK + CPSID i +#endif + BX lr +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_interrupt_restore.S b/ports/cortex_m52/gnu/src/tx_thread_interrupt_restore.S new file mode 100644 index 00000000..994bc620 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_interrupt_restore.S @@ -0,0 +1,77 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_restore Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for restoring the previous */ +/* interrupt lockout posture. */ +/* */ +/* INPUT */ +/* */ +/* previous_posture Previous interrupt posture */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_interrupt_restore(UINT previous_posture) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_interrupt_restore + .thumb_func +.type _tx_thread_interrupt_restore, function +_tx_thread_interrupt_restore: + /* Restore previous interrupt lockout posture. */ +#ifdef TX_PORT_USE_BASEPRI + MSR BASEPRI, r0 +#else + MSR PRIMASK, r0 +#endif + BX lr +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_schedule.S b/ports/cortex_m52/gnu/src/tx_thread_schedule.S new file mode 100644 index 00000000..88ad944a --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_schedule.S @@ -0,0 +1,389 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ +// Portions of this file were generated with AI assistance. + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_schedule Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function waits for a thread control block pointer to appear in */ +/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ +/* in the variable, the corresponding thread is resumed. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* _tx_thread_system_return Return to system from thread */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_schedule(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_schedule + .thumb_func +.type _tx_thread_schedule, function +_tx_thread_schedule: + /* This function should only ever be called on Cortex-M + from the first schedule request. Subsequent scheduling occurs + from the PendSV handling routine below. */ + + /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */ + MOV r0, #0 // Build value for TX_FALSE + LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag + STR r0, [r2, #0] // Clear preempt disable flag + +#ifdef __ARM_FP + /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */ + MRS r0, CONTROL // Pickup current CONTROL register + BIC r0, r0, #4 // Clear the FPCA bit + MSR CONTROL, r0 // Setup new CONTROL register +#endif + + /* Enable interrupts */ + CPSIE i + + /* Enter the scheduler for the first time. */ + MOV r0, #0x10000000 // Load PENDSVSET bit + MOV r1, #0xE000E000 // Load NVIC base + STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB // Complete all memory accesses + ISB // Flush pipeline + + /* Wait here for the PendSV to take place. */ + +__tx_wait_here: + B __tx_wait_here // Wait for the PendSV to happen +// } + + /* Generic context switching PendSV handler. */ + + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global PendSV_Handler + .thumb_func +.type PendSV_Handler, function + /* Get current thread value and new thread pointer. */ +PendSV_Handler: +__tx_ts_handler: + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the thread exit function to indicate the thread is no longer executing. */ +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + CPSID i // Disable interrupts +#endif /* TX_PORT_USE_BASEPRI */ + PUSH {r0, lr} // Save LR (and r0 just for alignment) + BL _tx_execution_thread_exit // Call the thread exit function + POP {r0, lr} // Recover LR +#ifdef TX_PORT_USE_BASEPRI + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r0 +#else + CPSIE i // Enable interrupts +#endif /* TX_PORT_USE_BASEPRI */ +#endif /* EXECUTION PROFILE */ + + LDR r0, =_tx_thread_current_ptr // Build current thread pointer address + LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address + MOV r3, #0 // Build NULL value + LDR r1, [r0] // Pickup current thread pointer + + /* Determine if there is a current thread to finish preserving. */ + + CBZ r1, __tx_ts_new // If NULL, skip preservation + + /* Recover PSP and preserve current thread context. */ + + STR r3, [r0] // Set _tx_thread_current_ptr to NULL + MRS r12, PSP // Pickup PSP pointer (thread's stack pointer) + STMDB r12!, {r4-r11} // Save its remaining registers +#ifdef __ARM_FP + TST LR, #0x10 // Determine if the VFP extended frame is present + BNE _skip_vfp_save + VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers +_skip_vfp_save: +#endif + LDR r4, =_tx_timer_time_slice // Build address of time-slice variable + STMDB r12!, {LR} // Save LR on the stack + STR r12, [r1, #8] // Save the thread stack pointer + +#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)) + // Save secure context + LDR r5, [r1,#0x90] // Load secure stack index + CBZ r5, _skip_secure_save // Skip save if there is no secure context + PUSH {r0,r1,r2,r3} // Save scratch registers + MOV r0, r1 // Move thread ptr to r0 + BL _tx_thread_secure_stack_context_save // Save secure stack + POP {r0,r1,r2,r3} // Restore secure registers +_skip_secure_save: +#endif + + /* Determine if time-slice is active. If it isn't, skip time handling processing. */ + + LDR r5, [r4] // Pickup current time-slice + CBZ r5, __tx_ts_new // If not active, skip processing + + /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */ + + STR r5, [r1, #24] // Save current time-slice + + /* Clear the global time-slice. */ + + STR r3, [r4] // Clear time-slice + + /* Executing thread is now completely preserved!!! */ + +__tx_ts_new: + + /* Now we are looking for a new thread to execute! */ + +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + CPSID i // Disable interrupts +#endif + LDR r1, [r2] // Is there another thread ready to execute? + CBZ r1, __tx_ts_wait // No, skip to the wait processing + + /* Yes, another thread is ready for else, make the current thread the new thread. */ + + STR r1, [r0] // Setup the current thread pointer to the new thread +#ifdef TX_PORT_USE_BASEPRI + MOV r4, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r4 +#else + CPSIE i // Enable interrupts +#endif + + /* Increment the thread run count. */ + +__tx_ts_restore: + LDR r7, [r1, #4] // Pickup the current thread run count + LDR r4, =_tx_timer_time_slice // Build address of time-slice variable + LDR r5, [r1, #24] // Pickup thread's current time-slice + ADD r7, r7, #1 // Increment the thread run count + STR r7, [r1, #4] // Store the new run count + + /* Setup global time-slice with thread's current time-slice. */ + + STR r5, [r4] // Setup global time-slice + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the thread entry function to indicate the thread is executing. */ + PUSH {r0, r1} // Save r0 and r1 + BL _tx_execution_thread_enter // Call the thread execution enter function + POP {r0, r1} // Recover r0 and r1 +#endif + +#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)) + // Restore secure context + LDR r0, [r1,#0x90] // Load secure stack index + CBZ r0, _skip_secure_restore // Skip restore if there is no secure context + PUSH {r0,r1} // Save r1 (and dummy r0) + MOV r0, r1 // Move thread ptr to r0 + BL _tx_thread_secure_stack_context_restore // Restore secure stack + POP {r0,r1} // Restore r1 (and dummy r0) +_skip_secure_restore: +#endif + + /* Restore the thread context and PSP. */ + LDR r12, [r1, #12] // Get stack start + MSR PSPLIM, r12 // Set stack limit + LDR r12, [r1, #8] // Pickup thread's stack pointer + LDMIA r12!, {LR} // Pickup LR +#ifdef __ARM_FP + TST LR, #0x10 // Determine if the VFP extended frame is present + BNE _skip_vfp_restore // If not, skip VFP restore + VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers +_skip_vfp_restore: +#endif + LDMIA r12!, {r4-r11} // Recover thread's registers + MSR PSP, r12 // Setup the thread's stack pointer + + BX lr // Return to thread! + + /* The following is the idle wait processing... in this case, no threads are ready for execution and the + system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts + are disabled to allow use of WFI for waiting for a thread to arrive. */ + +__tx_ts_wait: +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + CPSID i // Disable interrupts +#endif + LDR r1, [r2] // Pickup the next thread to execute pointer + STR r1, [r0] // Store it in the current pointer + CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready! + +#ifdef TX_LOW_POWER + PUSH {r0-r3} + BL tx_low_power_enter // Possibly enter low power mode + POP {r0-r3} +#endif + +#ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif + DSB // Ensure no outstanding memory transactions + WFI // Wait for interrupt + ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif +#endif + +#ifdef TX_LOW_POWER + PUSH {r0-r3} + BL tx_low_power_exit // Exit low power mode + POP {r0-r3} +#endif + +#ifdef TX_PORT_USE_BASEPRI + MOV r4, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r4 +#else + CPSIE i // Enable interrupts +#endif + B __tx_ts_wait // Loop to continue waiting + + /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are + already in the handler! */ +__tx_ts_ready: + MOV r7, #0x08000000 // Build clear PendSV value + MOV r8, #0xE000E000 // Build base NVIC address + STR r7, [r8, #0xD04] // Clear any PendSV + + /* Re-enable interrupts and restore new thread. */ +#ifdef TX_PORT_USE_BASEPRI + MOV r4, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r4 +#else + CPSIE i // Enable interrupts +#endif + B __tx_ts_restore // Restore the thread +// } + + +#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)) + // SVC_Handler is not needed when ThreadX is running in single mode. + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global SVC_Handler + .thumb_func +.type SVC_Handler, function +SVC_Handler: + TST lr, #0x04 // Determine return stack from EXC_RETURN bit 2 + ITE EQ + MRSEQ r0, MSP // Get MSP if return stack is MSP + MRSNE r0, PSP // Get PSP if return stack is PSP + + LDR r1, [r0,#24] // Load saved PC from stack + LDRB r1, [r1,#-2] // Load SVC number + + CMP r1, #1 // Is it a secure stack allocate request? + BEQ _tx_svc_secure_alloc // Yes, go there + + CMP r1, #2 // Is it a secure stack free request? + BEQ _tx_svc_secure_free // Yes, go there + + CMP r1, #3 // Is it a secure stack init request? + BEQ _tx_svc_secure_init // Yes, go there + + // Unknown SVC argument - just return + BX lr + +_tx_svc_secure_alloc: + PUSH {r0,lr} // Save SP and EXC_RETURN + LDM r0, {r0-r3} // Load function parameters from stack + BL _tx_thread_secure_mode_stack_allocate + POP {r12,lr} // Restore SP and EXC_RETURN + STR r0,[r12] // Store function return value + BX lr +_tx_svc_secure_free: + PUSH {r0,lr} // Save SP and EXC_RETURN + LDM r0, {r0-r3} // Load function parameters from stack + BL _tx_thread_secure_mode_stack_free + POP {r12,lr} // Restore SP and EXC_RETURN + STR r0,[r12] // Store function return value + BX lr +_tx_svc_secure_init: + PUSH {r0,lr} // Save SP and EXC_RETURN + BL _tx_thread_secure_mode_stack_initialize + POP {r12,lr} // Restore SP and EXC_RETURN + BX lr +#endif // End of ifndef TX_SINGLE_MODE_SECURE, TX_SINGLE_MODE_NON_SECURE + + + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_vfp_access + .thumb_func +.type _tx_vfp_access, function +_tx_vfp_access: +#if TX_ENABLE_FPU_SUPPORT + VMOV.F32 s0, s0 // Simply access the VFP +#endif + BX lr // Return to caller +.end diff --git a/ports/cortex_m52/gnu/src/tx_thread_secure_stack.c b/ports/cortex_m52/gnu/src/tx_thread_secure_stack.c new file mode 100644 index 00000000..48a3381f --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_secure_stack.c @@ -0,0 +1,581 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +#include "tx_api.h" + +/* If TX_SINGLE_MODE_SECURE or TX_SINGLE_MODE_NON_SECURE is defined, + no secure stack functionality is needed. */ +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + +#define TX_SOURCE_CODE + +#include "tx_secure_interface.h" /* Interface for NS code. */ + +/* Minimum size of secure stack. */ +#ifndef TX_THREAD_SECURE_STACK_MINIMUM +#define TX_THREAD_SECURE_STACK_MINIMUM 256 +#endif +/* Maximum size of secure stack. */ +#ifndef TX_THREAD_SECURE_STACK_MAXIMUM +#define TX_THREAD_SECURE_STACK_MAXIMUM 1024 +#endif + +/* 8 bytes added to stack size to "seal" stack. */ +#define TX_THREAD_STACK_SEAL_SIZE 8 +#define TX_THREAD_STACK_SEAL_VALUE 0xFEF5EDA5 + +/* max number of Secure context */ +#ifndef TX_MAX_SECURE_CONTEXTS +#define TX_MAX_SECURE_CONTEXTS 32 +#endif +#define TX_INVALID_SECURE_CONTEXT_IDX (-1) + +/* Secure stack info struct to hold stack start, stack limit, + current stack pointer, and pointer to owning thread. + This will be allocated for each thread with a secure stack. */ +typedef struct TX_THREAD_SECURE_STACK_INFO_STRUCT +{ + VOID *tx_thread_secure_stack_ptr; /* Thread's secure stack current pointer */ + VOID *tx_thread_secure_stack_start; /* Thread's secure stack start address */ + VOID *tx_thread_secure_stack_limit; /* Thread's secure stack limit */ + TX_THREAD *tx_thread_ptr; /* Keep track of thread for error handling */ + INT tx_next_free_index; /* Next free index of free secure context */ +} TX_THREAD_SECURE_STACK_INFO; + +/* Static secure contexts */ +static TX_THREAD_SECURE_STACK_INFO tx_thread_secure_context[TX_MAX_SECURE_CONTEXTS]; +/* Head of free secure context */ +static INT tx_head_free_index = 0U; + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_mode_stack_initialize Cortex-M52/GNU */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes secure mode to use PSP stack. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry, optimize(0))) +UINT _tx_thread_secure_mode_stack_initialize(void) +{ +UINT status; +ULONG control; +ULONG ipsr; +INT index; + + /* Make sure function is called from interrupt (threads should not call). */ + asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */ + if (ipsr == 0) + { + status = TX_CALLER_ERROR; + } + else + { + /* Set secure mode to use PSP. */ + asm volatile("MRS %0, CONTROL" : "=r" (control)); /* Get CONTROL register. */ + control |= 2; /* Use PSP. */ + asm volatile("MSR CONTROL, %0" :: "r" (control)); /* Set CONTROL register. */ + + /* Set process stack pointer and stack limit to 0 to throw exception when a thread + without a secure stack calls a secure function that tries to use secure stack. */ + asm volatile("MSR PSPLIM, %0" :: "r" (0)); + asm volatile("MSR PSP, %0" :: "r" (0)); + + for (index = 0; index < TX_MAX_SECURE_CONTEXTS; index++) + { + + /* Check last index and mark next free to invalid index */ + if(index == (TX_MAX_SECURE_CONTEXTS - 1)) + { + tx_thread_secure_context[index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX; + } + else + { + tx_thread_secure_context[index].tx_next_free_index = index + 1; + } + } + + status = TX_SUCCESS; + } + return status; +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_mode_stack_allocate Cortex-M52/GNU */ +/* 6.1.11a */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function allocates a thread's secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* stack_size Size of stack to allocates */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_SIZE_ERROR Invalid stack size */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* malloc Compiler's malloc function */ +/* */ +/* CALLED BY */ +/* */ +/* SVC Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* added stack sealing, */ +/* resulting in version 6.1.1 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* 05-02-2022 Scott Larson Modified comment(s), added */ +/* TX_INTERRUPT_SAVE_AREA, */ +/* resulting in version 6.1.11a*/ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +UINT _tx_thread_secure_mode_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size) +{ +TX_INTERRUPT_SAVE_AREA +UINT status; +TX_THREAD_SECURE_STACK_INFO *info_ptr; +UCHAR *stack_mem; +ULONG ipsr; +ULONG psplim_ns; +INT secure_context_index; + + status = TX_SUCCESS; + + /* Make sure function is called from interrupt (threads should not call). */ + asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */ + if (ipsr == 0) + { + status = TX_CALLER_ERROR; + } + else if (stack_size < TX_THREAD_SECURE_STACK_MINIMUM || stack_size > TX_THREAD_SECURE_STACK_MAXIMUM) + { + status = TX_SIZE_ERROR; + } + + /* Check if thread already has secure stack allocated. */ + else if (thread_ptr -> tx_thread_secure_stack_context != 0) + { + status = TX_THREAD_ERROR; + } + + else + { + TX_DISABLE + + /* Allocate free index for secure stack info. */ + if(tx_head_free_index != TX_INVALID_SECURE_CONTEXT_IDX) + { + secure_context_index = tx_head_free_index; + tx_head_free_index = tx_thread_secure_context[tx_head_free_index].tx_next_free_index; + tx_thread_secure_context[secure_context_index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX; + } + else + { + secure_context_index = TX_INVALID_SECURE_CONTEXT_IDX; + } + + TX_RESTORE + + if(secure_context_index != TX_INVALID_SECURE_CONTEXT_IDX) + { + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* If stack info allocated, allocate a stack & seal. */ + stack_mem = malloc(stack_size + TX_THREAD_STACK_SEAL_SIZE); + + if(stack_mem != TX_NULL) + { + /* Secure stack has been allocated, save in the stack info struct. */ + info_ptr -> tx_thread_secure_stack_limit = stack_mem; + info_ptr -> tx_thread_secure_stack_start = stack_mem + stack_size; + info_ptr -> tx_thread_secure_stack_ptr = info_ptr -> tx_thread_secure_stack_start; + info_ptr -> tx_thread_ptr = thread_ptr; + + /* Seal bottom of stack. */ + *(ULONG*)info_ptr -> tx_thread_secure_stack_start = TX_THREAD_STACK_SEAL_VALUE; + + /* Save secure context id (i.e non-zero base index) in thread. */ + thread_ptr -> tx_thread_secure_stack_context = (VOID *)(secure_context_index + 1); + + /* Check if this thread is running by looking at its stack start and PSPLIM_NS */ + asm volatile("MRS %0, PSPLIM_NS" : "=r" (psplim_ns)); /* Get PSPLIM_NS register. */ + if(((ULONG) thread_ptr -> tx_thread_stack_start & 0xFFFFFFF8) == psplim_ns) + { + /* If this thread is running, set Secure PSP and PSPLIM. */ + asm volatile("MSR PSPLIM, %0" :: "r" ((ULONG)(info_ptr -> tx_thread_secure_stack_limit))); + asm volatile("MSR PSP, %0" :: "r" ((ULONG)(info_ptr -> tx_thread_secure_stack_ptr))); + } + } + + else + { + TX_DISABLE + + /* Stack not allocated, free the info struct. */ + tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index; + tx_head_free_index = secure_context_index; + TX_RESTORE + + status = TX_NO_MEMORY; + } + } + + else + { + status = TX_NO_MEMORY; + } + } + + return(status); +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_mode_stack_free Cortex-M52/GNU */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function frees a thread's secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* free Compiler's free() function */ +/* */ +/* CALLED BY */ +/* */ +/* SVC Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* resulting in version 6.1.1 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +UINT _tx_thread_secure_mode_stack_free(TX_THREAD *thread_ptr) +{ +TX_INTERRUPT_SAVE_AREA +UINT status; +TX_THREAD_SECURE_STACK_INFO *info_ptr; +ULONG ipsr; +INT secure_context_index; + + status = TX_SUCCESS; + + /* Pickup stack info id from thread. */ + secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1; + + /* Make sure function is called from interrupt (threads should not call). */ + asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */ + if (ipsr == 0) + { + status = TX_CALLER_ERROR; + } + + /* Check if secure context index is in valid range. */ + else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS) + { + status = TX_THREAD_ERROR; + } + else + { + + /* Pickup stack info from static array of secure contexts. */ + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* Check that this secure context is for this thread. */ + if (info_ptr -> tx_thread_ptr != thread_ptr) + { + status = TX_THREAD_ERROR; + } + + else + { + + /* Free secure stack. */ + free(info_ptr -> tx_thread_secure_stack_limit); + + TX_DISABLE + + /* Free info struct. */ + tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index; + tx_head_free_index = secure_context_index; + TX_RESTORE + + /* Clear secure context from thread. */ + thread_ptr -> tx_thread_secure_stack_context = 0; + } + } + + return(status); +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_context_save Cortex-M52/GNU */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function saves context of the secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* PendSV Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* resulting in version 6.1.1 */ +/* 06-02-2021 Scott Larson Fix stack pointer save, */ +/* resulting in version 6.1.7 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +void _tx_thread_secure_stack_context_save(TX_THREAD *thread_ptr) +{ +TX_THREAD_SECURE_STACK_INFO *info_ptr; +ULONG sp; +ULONG ipsr; +INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1; + + /* This function should be called from scheduler only. */ + asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */ + if (ipsr == 0) + { + return; + } + + /* Check if secure context index is in valid range. */ + else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS) + { + return; + } + + /* Pickup the secure context pointer. */ + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* Check that this secure context is for this thread. */ + if (info_ptr -> tx_thread_ptr != thread_ptr) + { + return; + } + + /* Check that stack pointer is in range */ + asm volatile("MRS %0, PSP" : "=r" (sp)); /* Get PSP register. */ + if ((sp < (ULONG)info_ptr -> tx_thread_secure_stack_limit) || + (sp > (ULONG)info_ptr -> tx_thread_secure_stack_start)) + { + return; + } + + /* Save stack pointer. */ + info_ptr -> tx_thread_secure_stack_ptr = (VOID *) sp; + + /* Set process stack pointer and stack limit to 0 to throw exception when a thread + without a secure stack calls a secure function that tries to use secure stack. */ + asm volatile("MSR PSPLIM, %0" :: "r" (0)); + asm volatile("MSR PSP, %0" :: "r" (0)); + + return; +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_context_restore Cortex-M52/GNU */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function restores context of the secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* PendSV Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* resulting in version 6.1.1 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +void _tx_thread_secure_stack_context_restore(TX_THREAD *thread_ptr) +{ +TX_THREAD_SECURE_STACK_INFO *info_ptr; +ULONG ipsr; +INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1; + + /* This function should be called from scheduler only. */ + asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */ + if (ipsr == 0) + { + return; + } + + /* Check if secure context index is in valid range. */ + else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS) + { + return; + } + + /* Pickup the secure context pointer. */ + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* Check that this secure context is for this thread. */ + if (info_ptr -> tx_thread_ptr != thread_ptr) + { + return; + } + + /* Set stack pointer and limit. */ + asm volatile("MSR PSPLIM, %0" :: "r" ((ULONG)info_ptr -> tx_thread_secure_stack_limit)); + asm volatile("MSR PSP, %0" :: "r" ((ULONG)info_ptr -> tx_thread_secure_stack_ptr)); + + return; +} + +#endif diff --git a/ports/cortex_m52/gnu/src/tx_thread_secure_stack_allocate.S b/ports/cortex_m52/gnu/src/tx_thread_secure_stack_allocate.S new file mode 100644 index 00000000..e49e3986 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_secure_stack_allocate.S @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_allocate Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enters the SVC handler to allocate a secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* stack_size Size of secure stack to */ +/* allocate */ +/* */ +/* OUTPUT */ +/* */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* SVC 1 */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// UINT _tx_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_secure_stack_allocate + .thumb_func +.type _tx_thread_secure_stack_allocate, function +_tx_thread_secure_stack_allocate: +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + MRS r3, PRIMASK // Save interrupt mask + CPSIE i // Enable interrupts for SVC call + SVC 1 + CMP r3, #0 // If interrupts enabled, just return + BEQ _alloc_return_interrupt_enabled + CPSID i // Otherwise, disable interrupts +#else + MOV r0, #0xFF // Feature not enabled +#endif +_alloc_return_interrupt_enabled: + BX lr + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_secure_stack_free.S b/ports/cortex_m52/gnu/src/tx_thread_secure_stack_free.S new file mode 100644 index 00000000..35f9b519 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_secure_stack_free.S @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_free Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enters the SVC handler to free a secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* SVC 2 */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// UINT _tx_thread_secure_stack_free(TX_THREAD *thread_ptr) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_secure_stack_free + .thumb_func +.type _tx_thread_secure_stack_free, function +_tx_thread_secure_stack_free: +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + MRS r3, PRIMASK // Save interrupt mask + CPSIE i // Enable interrupts for SVC call + SVC 2 + CMP r3, #0 // If interrupts enabled, just return + BEQ _free_return_interrupt_enabled + CPSID i // Otherwise, disable interrupts +#else + MOV r0, #0xFF // Feature not enabled +#endif +_free_return_interrupt_enabled: + BX lr + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_secure_stack_initialize.S b/ports/cortex_m52/gnu/src/tx_thread_secure_stack_initialize.S new file mode 100644 index 00000000..4dc61ea2 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_secure_stack_initialize.S @@ -0,0 +1,76 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_initialize Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enters the SVC handler to initialize a secure stack. */ +/* */ +/* INPUT */ +/* */ +/* none */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* SVC 3 */ +/* */ +/* CALLED BY */ +/* */ +/* TX_PORT_SPECIFIC_PRE_INITIALIZATION */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_secure_stack_initialize(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_secure_stack_initialize + .thumb_func +.type _tx_thread_secure_stack_initialize, function +_tx_thread_secure_stack_initialize: +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + CPSIE i // Enable interrupts for SVC call + SVC 3 + CPSID i // Disable interrupts +#else + MOV r0, #0xFF // Feature not enabled +#endif + BX lr + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_stack_build.S b/ports/cortex_m52/gnu/src/tx_thread_stack_build.S new file mode 100644 index 00000000..a61b5b12 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_stack_build.S @@ -0,0 +1,137 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_stack_build Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function builds a stack frame on the supplied thread's stack. */ +/* The stack frame results in a fake interrupt return to the supplied */ +/* function pointer. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread control blk */ +/* function_ptr Pointer to return function */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_create Create thread service */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_stack_build + .thumb_func +.type _tx_thread_stack_build, function +_tx_thread_stack_build: + /* Build a fake interrupt frame. The form of the fake interrupt stack + on the Cortex-M should look like the following after it is built: + + Stack Top: + LR Interrupted LR (LR at time of PENDSV) + r4 Initial value for r4 + r5 Initial value for r5 + r6 Initial value for r6 + r7 Initial value for r7 + r8 Initial value for r8 + r9 Initial value for r9 + r10 Initial value for r10 + r11 Initial value for r11 + r0 Initial value for r0 (Hardware stack starts here!!) + r1 Initial value for r1 + r2 Initial value for r2 + r3 Initial value for r3 + r12 Initial value for r12 + lr Initial value for lr + pc Initial value for pc + xPSR Initial value for xPSR + + Stack Bottom: (higher memory address) */ + + LDR r2, [r0, #16] // Pickup end of stack area + BIC r2, r2, #0x7 // Align frame for 8-byte alignment + SUB r2, r2, #68 // Subtract frame size +#ifdef TX_SINGLE_MODE_SECURE + LDR r3, =0xFFFFFFFD // Build initial LR value for secure mode +#else + LDR r3, =0xFFFFFFBC // Build initial LR value to return to non-secure PSP +#endif + STR r3, [r2, #0] // Save on the stack + + /* Actually build the stack frame. */ + + MOV r3, #0 // Build initial register value + STR r3, [r2, #4] // Store initial r4 + STR r3, [r2, #8] // Store initial r5 + STR r3, [r2, #12] // Store initial r6 + STR r3, [r2, #16] // Store initial r7 + STR r3, [r2, #20] // Store initial r8 + STR r3, [r2, #24] // Store initial r9 + STR r3, [r2, #28] // Store initial r10 + STR r3, [r2, #32] // Store initial r11 + + /* Hardware stack follows. */ + + STR r3, [r2, #36] // Store initial r0 + STR r3, [r2, #40] // Store initial r1 + STR r3, [r2, #44] // Store initial r2 + STR r3, [r2, #48] // Store initial r3 + STR r3, [r2, #52] // Store initial r12 + MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value + STR r3, [r2, #56] // Store initial lr + STR r1, [r2, #60] // Store initial pc + MOV r3, #0x01000000 // Only T-bit need be set + STR r3, [r2, #64] // Store initial xPSR + + /* Setup stack pointer. */ + // thread_ptr -> tx_thread_stack_ptr = r2; + + STR r2, [r0, #8] // Save stack pointer in thread's + // control block + BX lr // Return to caller +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_system_return.S b/ports/cortex_m52/gnu/src/tx_thread_system_return.S new file mode 100644 index 00000000..da5b7af8 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_system_return.S @@ -0,0 +1,99 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + +// Portions of this file were generated with AI assistance. + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_system_return Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is target processor specific. It is used to transfer */ +/* control from a thread back to the ThreadX system. Only a */ +/* minimal context is saved since the compiler assumes temp registers */ +/* are going to get slicked by a function call anyway. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_schedule Thread scheduling loop */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX components */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_system_return(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_system_return + .thumb_func +.type _tx_thread_system_return, function +_tx_thread_system_return: + /* Return to real scheduler via PendSV. Note that this routine is often + replaced with in-line assembly in tx_port.h to improved performance. */ + + MOV r0, #0x10000000 // Load PENDSVSET bit + MOV r1, #0xE000E000 // Load NVIC base + STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline + MRS r0, IPSR // Pickup IPSR + CMP r0, #0 // Is it a thread returning? + BNE _isr_context // If ISR, skip interrupt enable +#ifdef TX_PORT_USE_BASEPRI + MRS r1, BASEPRI // Thread context returning, pickup BASEPRI + MOV r0, #0 + MSR BASEPRI, r0 // Enable interrupts + MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline +#else + MRS r1, PRIMASK // Thread context returning, pickup PRIMASK + CPSIE i // Enable interrupts + MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline +#endif +_isr_context: + BX lr // Return to caller +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_timer_interrupt.S b/ports/cortex_m52/gnu/src/tx_timer_interrupt.S new file mode 100644 index 00000000..16af99fa --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_timer_interrupt.S @@ -0,0 +1,240 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_interrupt Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the hardware timer interrupt. This */ +/* processing includes incrementing the system clock and checking for */ +/* time slice and/or timer expiration. If either is found, the */ +/* expiration functions are called. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_expiration_process Timer expiration processing */ +/* _tx_thread_time_slice Time slice interrupted thread */ +/* */ +/* CALLED BY */ +/* */ +/* interrupt vector */ +/* */ +/**************************************************************************/ +// VOID _tx_timer_interrupt(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_timer_interrupt + .thumb_func +.type _tx_timer_interrupt, function +_tx_timer_interrupt: + + /* Upon entry to this routine, it is assumed that the compiler scratch registers are available + for use. */ + + /* Increment the system clock. */ + // _tx_timer_system_clock++; + + LDR r1, =_tx_timer_system_clock // Pickup address of system clock + LDR r0, [r1, #0] // Pickup system clock + ADD r0, r0, #1 // Increment system clock + STR r0, [r1, #0] // Store new system clock + + /* Test for time-slice expiration. */ + // if (_tx_timer_time_slice) + // { + + LDR r3, =_tx_timer_time_slice // Pickup address of time-slice + LDR r2, [r3, #0] // Pickup time-slice + CBZ r2, __tx_timer_no_time_slice // Is it non-active? + // Yes, skip time-slice processing + + /* Decrement the time_slice. */ + // _tx_timer_time_slice--; + + SUB r2, r2, #1 // Decrement the time-slice + STR r2, [r3, #0] // Store new time-slice value + + /* Check for expiration. */ + // if (__tx_timer_time_slice == 0) + + CBNZ r2, __tx_timer_no_time_slice // Has it expired? + // No, skip expiration processing + + /* Set the time-slice expired flag. */ + // _tx_timer_expired_time_slice = TX_TRUE; + + LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag + MOV r0, #1 // Build expired value + STR r0, [r3, #0] // Set time-slice expiration flag + + // } + +__tx_timer_no_time_slice: + + /* Test for timer expiration. */ + // if (*_tx_timer_current_ptr) + // { + + LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address + LDR r0, [r1, #0] // Pickup current timer + LDR r2, [r0, #0] // Pickup timer list entry + CBZ r2, __tx_timer_no_timer // Is there anything in the list? + // No, just increment the timer + + /* Set expiration flag. */ + // _tx_timer_expired = TX_TRUE; + + LDR r3, =_tx_timer_expired // Pickup expiration flag address + MOV r2, #1 // Build expired value + STR r2, [r3, #0] // Set expired flag + B __tx_timer_done // Finished timer processing + + // } + // else + // { +__tx_timer_no_timer: + + /* No timer expired, increment the timer pointer. */ + // _tx_timer_current_ptr++; + + ADD r0, r0, #4 // Move to next timer + + /* Check for wrap-around. */ + // if (_tx_timer_current_ptr == _tx_timer_list_end) + + LDR r3, =_tx_timer_list_end // Pickup addr of timer list end + LDR r2, [r3, #0] // Pickup list end + CMP r0, r2 // Are we at list end? + BNE __tx_timer_skip_wrap // No, skip wrap-around logic + + /* Wrap to beginning of list. */ + // _tx_timer_current_ptr = _tx_timer_list_start; + + LDR r3, =_tx_timer_list_start // Pickup addr of timer list start + LDR r0, [r3, #0] // Set current pointer to list start + +__tx_timer_skip_wrap: + + STR r0, [r1, #0] // Store new current timer pointer + // } + +__tx_timer_done: + + /* See if anything has expired. */ + // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) + // { + + LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag + LDR r2, [r3, #0] // Pickup time-slice expired flag + CBNZ r2, __tx_something_expired // Did a time-slice expire? + // If non-zero, time-slice expired + LDR r1, =_tx_timer_expired // Pickup addr of other expired flag + LDR r0, [r1, #0] // Pickup timer expired flag + CBZ r0, __tx_timer_nothing_expired // Did a timer expire? + // No, nothing expired + +__tx_something_expired: + + PUSH {r0, lr} // Save the lr register on the stack + // and save r0 just to keep 8-byte alignment + + /* Did a timer expire? */ + // if (_tx_timer_expired) + // { + + LDR r1, =_tx_timer_expired // Pickup addr of expired flag + LDR r0, [r1, #0] // Pickup timer expired flag + CBZ r0, __tx_timer_dont_activate // Check for timer expiration + // If not set, skip timer activation + + /* Process timer expiration. */ + // _tx_timer_expiration_process(); + + BL _tx_timer_expiration_process // Call the timer expiration handling routine + + // } +__tx_timer_dont_activate: + + /* Did time slice expire? */ + // if (_tx_timer_expired_time_slice) + // { + + LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired + LDR r2, [r3, #0] // Pickup the actual flag + CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set + // No, skip time-slice processing + + /* Time slice interrupted thread. */ + // _tx_thread_time_slice(); + + BL _tx_thread_time_slice // Call time-slice processing + LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag + LDR r1, [r0] // Is the preempt disable flag set? + CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic + LDR r0, =_tx_thread_current_ptr // Build current thread pointer address + LDR r1, [r0] // Pickup the current thread pointer + LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address + LDR r3, [r2] // Pickup the execute thread pointer + LDR r0, =0xE000ED04 // Build address of control register + LDR r2, =0x10000000 // Build value for PendSV bit + CMP r1, r3 // Are they the same? + BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed + STR r2, [r0] // Not the same, issue the PendSV for preemption +__tx_timer_skip_time_slice: + // } + +__tx_timer_not_ts_expiration: + + POP {r0, lr} // Recover lr register (r0 is just there for + // the 8-byte stack alignment + + // } + +__tx_timer_nothing_expired: + + DSB // Complete all memory access + BX lr // Return to caller +// } + .end diff --git a/ports/cortex_m52/gnu/src/txe_thread_secure_stack_allocate.c b/ports/cortex_m52/gnu/src/txe_thread_secure_stack_allocate.c new file mode 100644 index 00000000..a37436dd --- /dev/null +++ b/ports/cortex_m52/gnu/src/txe_thread_secure_stack_allocate.c @@ -0,0 +1,113 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_allocate Cortex-M52 */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the secure stack allocate */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* stack_size Size of secure stack to */ +/* allocate */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_secure_stack_allocate Actual stack alloc function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +UINT _txe_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size) +{ +#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE) + return(TX_FEATURE_NOT_ENABLED); +#else +UINT status; + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + /* Is call from an interrupt and not initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + /* Call actual secure stack allocate function. */ + status = _tx_thread_secure_stack_allocate(thread_ptr, stack_size); + } + + /* Return completion status. */ + return(status); +#endif +} diff --git a/ports/cortex_m52/gnu/src/txe_thread_secure_stack_free.c b/ports/cortex_m52/gnu/src/txe_thread_secure_stack_free.c new file mode 100644 index 00000000..b7e4b7d5 --- /dev/null +++ b/ports/cortex_m52/gnu/src/txe_thread_secure_stack_free.c @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_secure_stack_free Cortex-M52 */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the secure stack free */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_secure_stack_free Actual stack free function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +UINT _txe_thread_secure_stack_free(TX_THREAD *thread_ptr) +{ +#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE) + return(TX_FEATURE_NOT_ENABLED); +#else +UINT status; + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + /* Is call from an interrupt and not initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual secure stack allocate function. */ + status = _tx_thread_secure_stack_free(thread_ptr); + } + + /* Return completion status. */ + return(status); +#endif +} |
