mirror of
https://github.com/eclipse-threadx/threadx.git
synced 2026-09-22 21:44:07 +08:00
Release 6.1.11
This commit is contained in:
@@ -21,9 +21,6 @@
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/* Include macros for modifying the wait list. */
|
||||
#include "tx_thread_smp_protection_wait_list_macros.h"
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
@@ -31,7 +28,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_restore Cortex-A35-SMP/AC6 */
|
||||
/* 6.1.3 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Andres Mlinar, Microsoft Corporation */
|
||||
@@ -63,7 +60,10 @@
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 12-31-2020 Andres Mlinar Initial Version 6.1.3 */
|
||||
/* 12-31-2020 Andres Mlinar Initial Version 6.1.3 */
|
||||
/* 04-25-2022 William E. Lamie Modified comments, removed */
|
||||
/* FIFO queueing, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_context_restore(VOID)
|
||||
@@ -76,7 +76,7 @@ _tx_thread_context_restore:
|
||||
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR exit function to indicate an ISR is complete. */
|
||||
|
||||
@@ -101,13 +101,13 @@ _tx_thread_context_restore:
|
||||
LDR x3, =_tx_thread_system_state // Pickup address of system state var
|
||||
LDR w2, [x3, x8, LSL #2] // Pickup system state
|
||||
SUB w2, w2, #1 // Decrement the counter
|
||||
STR w2, [x3, x8, LSL #2] // Store the counter
|
||||
STR w2, [x3, x8, LSL #2] // Store the counter
|
||||
CMP w2, #0 // Was this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_restore // If so, not a nested restore
|
||||
|
||||
/* Interrupts are nested. */
|
||||
|
||||
/* Just recover the saved registers and return to the point of
|
||||
/* Just recover the saved registers and return to the point of
|
||||
interrupt. */
|
||||
|
||||
LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL
|
||||
@@ -151,7 +151,7 @@ __tx_thread_not_nested_restore:
|
||||
LDR x3, =_tx_thread_execute_ptr // Pickup address of execute thread ptr
|
||||
LDR x2, [x3, x8, LSL #3] // Pickup actual execute thread pointer
|
||||
CMP x0, x2 // Is the same thread highest priority?
|
||||
BEQ __tx_thread_no_preempt_restore // Same thread in the execute list,
|
||||
BEQ __tx_thread_no_preempt_restore // Same thread in the execute list,
|
||||
// no preemption needs to happen
|
||||
LDR x3, =_tx_thread_smp_protection // Build address to protection structure
|
||||
LDR w3, [x3, #4] // Pickup the owning core
|
||||
@@ -206,74 +206,6 @@ __tx_thread_no_preempt_restore:
|
||||
// {
|
||||
__tx_thread_preempt_restore:
|
||||
|
||||
/* Was the thread being preempted waiting for the lock? */
|
||||
// if (_tx_thread_smp_protect_wait_counts[this_core] != 0)
|
||||
// {
|
||||
|
||||
LDR x2, =_tx_thread_smp_protect_wait_counts // Load waiting count list
|
||||
LDR w3, [x2, x8, LSL #2] // Load waiting value for this core
|
||||
CMP w3, #0
|
||||
BEQ _nobody_waiting_for_lock // Is the core waiting for the lock?
|
||||
|
||||
/* Do we not have the lock? This means the ISR never got the inter-core lock. */
|
||||
// if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core)
|
||||
// {
|
||||
|
||||
LDR x2, =_tx_thread_smp_protection // Load address of protection structure
|
||||
LDR w3, [x2, #4] // Pickup the owning core
|
||||
CMP w8, w3 // Compare our core to the owning core
|
||||
BEQ _this_core_has_lock // Do we have the lock?
|
||||
|
||||
/* We don't have the lock. This core should be in the list. Remove it. */
|
||||
// _tx_thread_smp_protect_wait_list_remove(this_core);
|
||||
|
||||
_tx_thread_smp_protect_wait_list_remove // Call macro to remove core from the list
|
||||
B _nobody_waiting_for_lock // Leave
|
||||
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
/* We have the lock. This means the ISR got the inter-core lock, but
|
||||
never released it because it saw that there was someone waiting.
|
||||
Note this core is not in the list. */
|
||||
|
||||
_this_core_has_lock:
|
||||
|
||||
/* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */
|
||||
// _tx_thread_smp_protect_wait_counts[core]--;
|
||||
|
||||
LDR x2, =_tx_thread_smp_protect_wait_counts // Load waiting count list
|
||||
LDR w3, [x2, x8, LSL #2] // Load waiting value for this core
|
||||
SUB w3, w3, #1 // Decrement waiting value. Should be zero now
|
||||
STR w3, [x2, x8, LSL #2] // Store new waiting value
|
||||
|
||||
/* Now release the inter-core lock. */
|
||||
|
||||
/* Set protected core as invalid. */
|
||||
// _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF;
|
||||
|
||||
LDR x2, =_tx_thread_smp_protection // Load address of protection structure
|
||||
MOV w3, #0xFFFFFFFF // Build invalid value
|
||||
STR w3, [x2, #4] // Mark the protected core as invalid
|
||||
DMB ISH // Ensure that accesses to shared resource have completed
|
||||
|
||||
/* Release protection. */
|
||||
// _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0;
|
||||
|
||||
MOV w3, #0 // Build release protection value
|
||||
STR w3, [x2, #0] // Release the protection
|
||||
DSB ISH // To ensure update of the protection occurs before other CPUs awake
|
||||
|
||||
/* Wake up waiting processors. Note interrupts are already enabled. */
|
||||
|
||||
#ifdef TX_ENABLE_WFE
|
||||
SEV // Send event to other CPUs
|
||||
#endif
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
_nobody_waiting_for_lock:
|
||||
|
||||
LDR x4, [x0, #8] // Switch to thread stack pointer
|
||||
MOV sp, x4 //
|
||||
@@ -328,8 +260,8 @@ _skip_fp_save:
|
||||
CMP w2, #0 // Is it active?
|
||||
BEQ __tx_thread_dont_save_ts // No, don't save it
|
||||
|
||||
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
_tx_timer_time_slice = 0; */
|
||||
// _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
// _tx_timer_time_slice = 0;
|
||||
|
||||
STR w2, [x0, #36] // Save thread's time-slice
|
||||
MOV w2, #0 // Clear value
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_smp_protect Cortex-A35-SMP/AC6 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
@@ -63,11 +63,14 @@
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 10-15-2021 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* improved SMP code, */
|
||||
/* resulting in version 6.1.9 */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 10-15-2021 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* improved SMP code, */
|
||||
/* resulting in version 6.1.9 */
|
||||
/* 04-25-2022 William E. Lamie Modified comments, removed */
|
||||
/* FIFO queueing, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.global _tx_thread_smp_protect
|
||||
@@ -81,293 +84,49 @@ _tx_thread_smp_protect:
|
||||
|
||||
/* Pickup the CPU ID. */
|
||||
|
||||
MRS x1, MPIDR_EL1 // Pickup the core ID
|
||||
MRS x2, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x7, x1, #16, #8 // Isolate cluster ID
|
||||
UBFX x7, x2, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #8, #8 // Isolate core ID
|
||||
UBFX x2, x2, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x7, x1, #8, #8 // Isolate cluster ID
|
||||
UBFX x7, x2, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #0, #8 // Isolate core ID
|
||||
UBFX x2, x2, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x1, x1, x7, LSL #2 // Calculate CPU ID
|
||||
ADDS x2, x2, x7, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
|
||||
/* Do we already have protection? */
|
||||
// if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core)
|
||||
// {
|
||||
|
||||
LDR x2, =_tx_thread_smp_protection // Build address to protection structure
|
||||
LDR w3, [x2, #4] // Pickup the owning core
|
||||
CMP w1, w3 // Is it not this core?
|
||||
BNE _protection_not_owned // No, the protection is not already owned
|
||||
|
||||
/* We already have protection. */
|
||||
|
||||
/* Increment the protection count. */
|
||||
// _tx_thread_smp_protection.tx_thread_smp_protect_count++;
|
||||
|
||||
LDR w3, [x2, #8] // Pickup ownership count
|
||||
ADD w3, w3, #1 // Increment ownership count
|
||||
STR w3, [x2, #8] // Store ownership count
|
||||
DMB ISH
|
||||
|
||||
B _return
|
||||
|
||||
_protection_not_owned:
|
||||
|
||||
/* Is the lock available? */
|
||||
// if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0)
|
||||
// {
|
||||
|
||||
LDAXR w3, [x2, #0] // Pickup the protection flag
|
||||
CMP w3, #0
|
||||
BNE _start_waiting // No, protection not available
|
||||
|
||||
/* Is the list empty? */
|
||||
// if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail)
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_list_head
|
||||
LDR w3, [x3]
|
||||
LDR x4, =_tx_thread_smp_protect_wait_list_tail
|
||||
LDR w4, [x4]
|
||||
CMP w3, w4
|
||||
BNE _list_not_empty
|
||||
|
||||
/* Try to get the lock. */
|
||||
// if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS)
|
||||
// {
|
||||
|
||||
MOV w3, #1 // Build lock value
|
||||
STXR w4, w3, [x2, #0] // Attempt to get the protection
|
||||
CMP w4, #0
|
||||
BNE _start_waiting // Did it fail?
|
||||
|
||||
/* We got the lock! */
|
||||
// _tx_thread_smp_protect_lock_got();
|
||||
|
||||
DMB ISH // Ensure write to protection finishes
|
||||
_tx_thread_smp_protect_lock_got // Call the lock got function
|
||||
|
||||
B _return
|
||||
|
||||
_list_not_empty:
|
||||
|
||||
/* Are we at the front of the list? */
|
||||
// if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head])
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_list_head // Get the address of the head
|
||||
LDR w3, [x3] // Get the value of the head
|
||||
LDR x4, =_tx_thread_smp_protect_wait_list // Get the address of the list
|
||||
LDR w4, [x4, x3, LSL #2] // Get the value at the head index
|
||||
|
||||
CMP w1, w4
|
||||
BNE _start_waiting
|
||||
|
||||
/* Is the lock still available? */
|
||||
// if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0)
|
||||
// {
|
||||
|
||||
LDAXR w3, [x2, #0] // Pickup the protection flag
|
||||
CMP w3, #0
|
||||
BNE _start_waiting // No, protection not available
|
||||
|
||||
/* Get the lock. */
|
||||
// _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1;
|
||||
|
||||
MOV w3, #1 // Build lock value
|
||||
STXR w4, w3, [x2, #0] // Attempt to get the protection
|
||||
CMP w4, #0
|
||||
BNE _start_waiting // Did it fail?
|
||||
DMB ISH //
|
||||
|
||||
/* Got the lock. */
|
||||
// _tx_thread_smp_protect_lock_got();
|
||||
|
||||
_tx_thread_smp_protect_lock_got
|
||||
|
||||
/* Remove this core from the wait list. */
|
||||
// _tx_thread_smp_protect_remove_from_front_of_list();
|
||||
|
||||
_tx_thread_smp_protect_remove_from_front_of_list
|
||||
|
||||
B _return
|
||||
|
||||
_start_waiting:
|
||||
|
||||
/* For one reason or another, we didn't get the lock. */
|
||||
|
||||
/* Increment wait count. */
|
||||
// _tx_thread_smp_protect_wait_counts[this_core]++;
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_counts // Load wait list counts
|
||||
LDR w4, [x3, x1, LSL #2] // Load waiting value for this core
|
||||
ADD w4, w4, #1 // Increment wait value
|
||||
STR w4, [x3, x1, LSL #2] // Store new wait value
|
||||
|
||||
/* Have we not added ourselves to the list yet? */
|
||||
// if (_tx_thread_smp_protect_wait_counts[this_core] == 1)
|
||||
// {
|
||||
|
||||
CMP w4, #1
|
||||
BNE _already_in_list0 // Is this core already waiting?
|
||||
|
||||
/* Add ourselves to the list. */
|
||||
// _tx_thread_smp_protect_wait_list_add(this_core);
|
||||
|
||||
_tx_thread_smp_protect_wait_list_add // Call macro to add ourselves to the list
|
||||
|
||||
// }
|
||||
|
||||
_already_in_list0:
|
||||
|
||||
/* Restore interrupts. */
|
||||
LDR x1, =_tx_thread_smp_protection // Build address to protection structure
|
||||
LDR w3, [x1, #4] // Pickup the owning core
|
||||
CMP w3, w2 // Is it this core?
|
||||
BEQ _owned // Yes, the protection is already owned
|
||||
|
||||
LDAXR w4, [x1, #0] // Pickup the protection flag
|
||||
CBZ w4, _get_protection // Yes, get the protection
|
||||
MSR DAIF, x0 // Restore interrupts
|
||||
ISB //
|
||||
#ifdef TX_ENABLE_WFE
|
||||
WFE // Go into standby
|
||||
#endif
|
||||
B _tx_thread_smp_protect // On waking, restart the protection attempt
|
||||
|
||||
/* We do this until we have the lock. */
|
||||
// while (1)
|
||||
// {
|
||||
|
||||
_try_to_get_lock:
|
||||
|
||||
/* Disable interrupts so we don't get preempted. */
|
||||
|
||||
MRS x0, DAIF // Pickup current interrupt posture
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
|
||||
/* Pickup the CPU ID. */
|
||||
|
||||
MRS x1, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x7, x1, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x7, x1, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x1, x1, x7, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
|
||||
/* Do we already have protection? */
|
||||
// if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core)
|
||||
// {
|
||||
|
||||
LDR w3, [x2, #4] // Pickup the owning core
|
||||
CMP w3, w1 // Is it this core?
|
||||
BEQ _got_lock_after_waiting // Yes, the protection is already owned. This means
|
||||
// an ISR preempted us and got protection
|
||||
|
||||
// }
|
||||
|
||||
/* Are we at the front of the list? */
|
||||
// if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head])
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_list_head // Get the address of the head
|
||||
LDR w3, [x3] // Get the value of the head
|
||||
LDR x4, =_tx_thread_smp_protect_wait_list // Get the address of the list
|
||||
LDR w4, [x4, x3, LSL #2] // Get the value at the head index
|
||||
|
||||
CMP w1, w4
|
||||
BNE _did_not_get_lock
|
||||
|
||||
/* Is the lock still available? */
|
||||
// if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0)
|
||||
// {
|
||||
|
||||
LDAXR w3, [x2, #0] // Pickup the protection flag
|
||||
CMP w3, #0
|
||||
BNE _did_not_get_lock // No, protection not available
|
||||
|
||||
/* Get the lock. */
|
||||
// _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1;
|
||||
|
||||
MOV w3, #1 // Build lock value
|
||||
STXR w4, w3, [x2, #0] // Attempt to get the protection
|
||||
CMP w4, #0
|
||||
BNE _did_not_get_lock // Did it fail?
|
||||
DMB ISH //
|
||||
|
||||
/* Got the lock. */
|
||||
// _tx_thread_smp_protect_lock_got();
|
||||
|
||||
_tx_thread_smp_protect_lock_got
|
||||
|
||||
/* Remove this core from the wait list. */
|
||||
// _tx_thread_smp_protect_remove_from_front_of_list();
|
||||
|
||||
_tx_thread_smp_protect_remove_from_front_of_list
|
||||
|
||||
B _got_lock_after_waiting
|
||||
|
||||
_did_not_get_lock:
|
||||
|
||||
/* For one reason or another, we didn't get the lock. */
|
||||
|
||||
/* Were we removed from the list? This can happen if we're a thread
|
||||
and we got preempted. */
|
||||
// if (_tx_thread_smp_protect_wait_counts[this_core] == 0)
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_counts // Load wait list counts
|
||||
LDR w4, [x3, x1, LSL #2] // Load waiting value for this core
|
||||
CMP w4, #0
|
||||
BNE _already_in_list1 // Is this core already in the list?
|
||||
|
||||
/* Add ourselves to the list. */
|
||||
// _tx_thread_smp_protect_wait_list_add(this_core);
|
||||
|
||||
_tx_thread_smp_protect_wait_list_add // Call macro to add ourselves to the list
|
||||
|
||||
/* Our waiting count was also reset when we were preempted. Increment it again. */
|
||||
// _tx_thread_smp_protect_wait_counts[this_core]++;
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_counts // Load wait list counts
|
||||
LDR w4, [x3, x1, LSL #2] // Load waiting value for this core
|
||||
ADD w4, w4, #1 // Increment wait value
|
||||
STR w4, [x3, x1, LSL #2] // Store new wait value value
|
||||
|
||||
// }
|
||||
|
||||
_already_in_list1:
|
||||
|
||||
/* Restore interrupts and try again. */
|
||||
|
||||
_get_protection:
|
||||
MOV x4, #1 // Build lock value
|
||||
STXR w5, w4, [x1] // Attempt to get the protection
|
||||
CBZ w5, _got_protection // Did it succeed? w5 = 0 means success!
|
||||
MSR DAIF, x0 // Restore interrupts
|
||||
ISB //
|
||||
#ifdef TX_ENABLE_WFE
|
||||
WFE // Go into standby
|
||||
#endif
|
||||
B _try_to_get_lock // On waking, restart the protection attempt
|
||||
|
||||
_got_lock_after_waiting:
|
||||
|
||||
/* We're no longer waiting. */
|
||||
// _tx_thread_smp_protect_wait_counts[this_core]--;
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_counts // Load waiting list
|
||||
LDR w4, [x3, x1, LSL #2] // Load current wait value
|
||||
SUB w4, w4, #1 // Decrement wait value
|
||||
STR w4, [x3, x1, LSL #2] // Store new wait value value
|
||||
|
||||
/* Restore registers and return. */
|
||||
|
||||
_return:
|
||||
|
||||
B _tx_thread_smp_protect // Restart the protection attempt
|
||||
|
||||
_got_protection:
|
||||
DMB ISH //
|
||||
STR w2, [x1, #4] // Save owning core
|
||||
_owned:
|
||||
LDR w5, [x1, #8] // Pickup ownership count
|
||||
ADD w5, w5, #1 // Increment ownership count
|
||||
STR w5, [x1, #8] // Store ownership count
|
||||
DMB ISH //
|
||||
RET
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_smp_unprotect Cortex-A35-SMP/AC6 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
@@ -60,10 +60,13 @@
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 10-15-2021 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.9 */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 10-15-2021 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.9 */
|
||||
/* 04-25-2022 William E. Lamie Modified comments, removed */
|
||||
/* FIFO queueing, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.global _tx_thread_smp_unprotect
|
||||
@@ -105,11 +108,6 @@ _tx_thread_smp_unprotect:
|
||||
CMP w3, #0 // Is the preempt disable flag set?
|
||||
BNE _still_protected // Yes, skip the protection release
|
||||
|
||||
LDR x2,=_tx_thread_smp_protect_wait_counts // Build build address of wait counts
|
||||
LDR w3, [x2, x1, LSL #2] // Pickup wait list value
|
||||
CMP w3, #0 // Are any entities on this core waiting?
|
||||
BNE _still_protected // Yes, skip the protection release
|
||||
|
||||
LDR x2,=_tx_thread_smp_protection // Build address of protection structure
|
||||
MOV w3, #0xFFFFFFFF // Build invalid value
|
||||
STR w3, [x2, #4] // Mark the protected core as invalid
|
||||
|
||||
@@ -21,9 +21,6 @@
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/* Include macros for modifying the wait list. */
|
||||
#include "tx_thread_smp_protection_wait_list_macros.h"
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
@@ -31,7 +28,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_restore Cortex-A35-SMP/GNU */
|
||||
/* 6.1.3 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Andres Mlinar, Microsoft Corporation */
|
||||
@@ -63,7 +60,10 @@
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 12-31-2020 Andres Mlinar Initial Version 6.1.3 */
|
||||
/* 12-31-2020 Andres Mlinar Initial Version 6.1.3 */
|
||||
/* 04-25-2022 William E. Lamie Modified comments, removed */
|
||||
/* FIFO queueing, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_context_restore(VOID)
|
||||
@@ -76,7 +76,7 @@ _tx_thread_context_restore:
|
||||
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR exit function to indicate an ISR is complete. */
|
||||
|
||||
@@ -101,13 +101,13 @@ _tx_thread_context_restore:
|
||||
LDR x3, =_tx_thread_system_state // Pickup address of system state var
|
||||
LDR w2, [x3, x8, LSL #2] // Pickup system state
|
||||
SUB w2, w2, #1 // Decrement the counter
|
||||
STR w2, [x3, x8, LSL #2] // Store the counter
|
||||
STR w2, [x3, x8, LSL #2] // Store the counter
|
||||
CMP w2, #0 // Was this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_restore // If so, not a nested restore
|
||||
|
||||
/* Interrupts are nested. */
|
||||
|
||||
/* Just recover the saved registers and return to the point of
|
||||
/* Just recover the saved registers and return to the point of
|
||||
interrupt. */
|
||||
|
||||
LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL
|
||||
@@ -151,7 +151,7 @@ __tx_thread_not_nested_restore:
|
||||
LDR x3, =_tx_thread_execute_ptr // Pickup address of execute thread ptr
|
||||
LDR x2, [x3, x8, LSL #3] // Pickup actual execute thread pointer
|
||||
CMP x0, x2 // Is the same thread highest priority?
|
||||
BEQ __tx_thread_no_preempt_restore // Same thread in the execute list,
|
||||
BEQ __tx_thread_no_preempt_restore // Same thread in the execute list,
|
||||
// no preemption needs to happen
|
||||
LDR x3, =_tx_thread_smp_protection // Build address to protection structure
|
||||
LDR w3, [x3, #4] // Pickup the owning core
|
||||
@@ -206,74 +206,6 @@ __tx_thread_no_preempt_restore:
|
||||
// {
|
||||
__tx_thread_preempt_restore:
|
||||
|
||||
/* Was the thread being preempted waiting for the lock? */
|
||||
// if (_tx_thread_smp_protect_wait_counts[this_core] != 0)
|
||||
// {
|
||||
|
||||
LDR x2, =_tx_thread_smp_protect_wait_counts // Load waiting count list
|
||||
LDR w3, [x2, x8, LSL #2] // Load waiting value for this core
|
||||
CMP w3, #0
|
||||
BEQ _nobody_waiting_for_lock // Is the core waiting for the lock?
|
||||
|
||||
/* Do we not have the lock? This means the ISR never got the inter-core lock. */
|
||||
// if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core)
|
||||
// {
|
||||
|
||||
LDR x2, =_tx_thread_smp_protection // Load address of protection structure
|
||||
LDR w3, [x2, #4] // Pickup the owning core
|
||||
CMP w8, w3 // Compare our core to the owning core
|
||||
BEQ _this_core_has_lock // Do we have the lock?
|
||||
|
||||
/* We don't have the lock. This core should be in the list. Remove it. */
|
||||
// _tx_thread_smp_protect_wait_list_remove(this_core);
|
||||
|
||||
_tx_thread_smp_protect_wait_list_remove // Call macro to remove core from the list
|
||||
B _nobody_waiting_for_lock // Leave
|
||||
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
/* We have the lock. This means the ISR got the inter-core lock, but
|
||||
never released it because it saw that there was someone waiting.
|
||||
Note this core is not in the list. */
|
||||
|
||||
_this_core_has_lock:
|
||||
|
||||
/* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */
|
||||
// _tx_thread_smp_protect_wait_counts[core]--;
|
||||
|
||||
LDR x2, =_tx_thread_smp_protect_wait_counts // Load waiting count list
|
||||
LDR w3, [x2, x8, LSL #2] // Load waiting value for this core
|
||||
SUB w3, w3, #1 // Decrement waiting value. Should be zero now
|
||||
STR w3, [x2, x8, LSL #2] // Store new waiting value
|
||||
|
||||
/* Now release the inter-core lock. */
|
||||
|
||||
/* Set protected core as invalid. */
|
||||
// _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF;
|
||||
|
||||
LDR x2, =_tx_thread_smp_protection // Load address of protection structure
|
||||
MOV w3, #0xFFFFFFFF // Build invalid value
|
||||
STR w3, [x2, #4] // Mark the protected core as invalid
|
||||
DMB ISH // Ensure that accesses to shared resource have completed
|
||||
|
||||
/* Release protection. */
|
||||
// _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0;
|
||||
|
||||
MOV w3, #0 // Build release protection value
|
||||
STR w3, [x2, #0] // Release the protection
|
||||
DSB ISH // To ensure update of the protection occurs before other CPUs awake
|
||||
|
||||
/* Wake up waiting processors. Note interrupts are already enabled. */
|
||||
|
||||
#ifdef TX_ENABLE_WFE
|
||||
SEV // Send event to other CPUs
|
||||
#endif
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
_nobody_waiting_for_lock:
|
||||
|
||||
LDR x4, [x0, #8] // Switch to thread stack pointer
|
||||
MOV sp, x4 //
|
||||
@@ -328,8 +260,8 @@ _skip_fp_save:
|
||||
CMP w2, #0 // Is it active?
|
||||
BEQ __tx_thread_dont_save_ts // No, don't save it
|
||||
|
||||
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
_tx_timer_time_slice = 0; */
|
||||
// _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
// _tx_timer_time_slice = 0;
|
||||
|
||||
STR w2, [x0, #36] // Save thread's time-slice
|
||||
MOV w2, #0 // Clear value
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_smp_protect Cortex-A35-SMP/GCC */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
@@ -63,11 +63,14 @@
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 10-15-2021 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* improved SMP code, */
|
||||
/* resulting in version 6.1.9 */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 10-15-2021 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* improved SMP code, */
|
||||
/* resulting in version 6.1.9 */
|
||||
/* 04-25-2022 William E. Lamie Modified comments, removed */
|
||||
/* FIFO queueing, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.global _tx_thread_smp_protect
|
||||
@@ -81,293 +84,49 @@ _tx_thread_smp_protect:
|
||||
|
||||
/* Pickup the CPU ID. */
|
||||
|
||||
MRS x1, MPIDR_EL1 // Pickup the core ID
|
||||
MRS x2, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x7, x1, #16, #8 // Isolate cluster ID
|
||||
UBFX x7, x2, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #8, #8 // Isolate core ID
|
||||
UBFX x2, x2, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x7, x1, #8, #8 // Isolate cluster ID
|
||||
UBFX x7, x2, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #0, #8 // Isolate core ID
|
||||
UBFX x2, x2, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x1, x1, x7, LSL #2 // Calculate CPU ID
|
||||
ADDS x2, x2, x7, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
|
||||
/* Do we already have protection? */
|
||||
// if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core)
|
||||
// {
|
||||
|
||||
LDR x2, =_tx_thread_smp_protection // Build address to protection structure
|
||||
LDR w3, [x2, #4] // Pickup the owning core
|
||||
CMP w1, w3 // Is it not this core?
|
||||
BNE _protection_not_owned // No, the protection is not already owned
|
||||
|
||||
/* We already have protection. */
|
||||
|
||||
/* Increment the protection count. */
|
||||
// _tx_thread_smp_protection.tx_thread_smp_protect_count++;
|
||||
|
||||
LDR w3, [x2, #8] // Pickup ownership count
|
||||
ADD w3, w3, #1 // Increment ownership count
|
||||
STR w3, [x2, #8] // Store ownership count
|
||||
DMB ISH
|
||||
|
||||
B _return
|
||||
|
||||
_protection_not_owned:
|
||||
|
||||
/* Is the lock available? */
|
||||
// if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0)
|
||||
// {
|
||||
|
||||
LDAXR w3, [x2, #0] // Pickup the protection flag
|
||||
CMP w3, #0
|
||||
BNE _start_waiting // No, protection not available
|
||||
|
||||
/* Is the list empty? */
|
||||
// if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail)
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_list_head
|
||||
LDR w3, [x3]
|
||||
LDR x4, =_tx_thread_smp_protect_wait_list_tail
|
||||
LDR w4, [x4]
|
||||
CMP w3, w4
|
||||
BNE _list_not_empty
|
||||
|
||||
/* Try to get the lock. */
|
||||
// if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS)
|
||||
// {
|
||||
|
||||
MOV w3, #1 // Build lock value
|
||||
STXR w4, w3, [x2, #0] // Attempt to get the protection
|
||||
CMP w4, #0
|
||||
BNE _start_waiting // Did it fail?
|
||||
|
||||
/* We got the lock! */
|
||||
// _tx_thread_smp_protect_lock_got();
|
||||
|
||||
DMB ISH // Ensure write to protection finishes
|
||||
_tx_thread_smp_protect_lock_got // Call the lock got function
|
||||
|
||||
B _return
|
||||
|
||||
_list_not_empty:
|
||||
|
||||
/* Are we at the front of the list? */
|
||||
// if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head])
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_list_head // Get the address of the head
|
||||
LDR w3, [x3] // Get the value of the head
|
||||
LDR x4, =_tx_thread_smp_protect_wait_list // Get the address of the list
|
||||
LDR w4, [x4, x3, LSL #2] // Get the value at the head index
|
||||
|
||||
CMP w1, w4
|
||||
BNE _start_waiting
|
||||
|
||||
/* Is the lock still available? */
|
||||
// if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0)
|
||||
// {
|
||||
|
||||
LDAXR w3, [x2, #0] // Pickup the protection flag
|
||||
CMP w3, #0
|
||||
BNE _start_waiting // No, protection not available
|
||||
|
||||
/* Get the lock. */
|
||||
// _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1;
|
||||
|
||||
MOV w3, #1 // Build lock value
|
||||
STXR w4, w3, [x2, #0] // Attempt to get the protection
|
||||
CMP w4, #0
|
||||
BNE _start_waiting // Did it fail?
|
||||
DMB ISH //
|
||||
|
||||
/* Got the lock. */
|
||||
// _tx_thread_smp_protect_lock_got();
|
||||
|
||||
_tx_thread_smp_protect_lock_got
|
||||
|
||||
/* Remove this core from the wait list. */
|
||||
// _tx_thread_smp_protect_remove_from_front_of_list();
|
||||
|
||||
_tx_thread_smp_protect_remove_from_front_of_list
|
||||
|
||||
B _return
|
||||
|
||||
_start_waiting:
|
||||
|
||||
/* For one reason or another, we didn't get the lock. */
|
||||
|
||||
/* Increment wait count. */
|
||||
// _tx_thread_smp_protect_wait_counts[this_core]++;
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_counts // Load wait list counts
|
||||
LDR w4, [x3, x1, LSL #2] // Load waiting value for this core
|
||||
ADD w4, w4, #1 // Increment wait value
|
||||
STR w4, [x3, x1, LSL #2] // Store new wait value
|
||||
|
||||
/* Have we not added ourselves to the list yet? */
|
||||
// if (_tx_thread_smp_protect_wait_counts[this_core] == 1)
|
||||
// {
|
||||
|
||||
CMP w4, #1
|
||||
BNE _already_in_list0 // Is this core already waiting?
|
||||
|
||||
/* Add ourselves to the list. */
|
||||
// _tx_thread_smp_protect_wait_list_add(this_core);
|
||||
|
||||
_tx_thread_smp_protect_wait_list_add // Call macro to add ourselves to the list
|
||||
|
||||
// }
|
||||
|
||||
_already_in_list0:
|
||||
|
||||
/* Restore interrupts. */
|
||||
LDR x1, =_tx_thread_smp_protection // Build address to protection structure
|
||||
LDR w3, [x1, #4] // Pickup the owning core
|
||||
CMP w3, w2 // Is it this core?
|
||||
BEQ _owned // Yes, the protection is already owned
|
||||
|
||||
LDAXR w4, [x1, #0] // Pickup the protection flag
|
||||
CBZ w4, _get_protection // Yes, get the protection
|
||||
MSR DAIF, x0 // Restore interrupts
|
||||
ISB //
|
||||
#ifdef TX_ENABLE_WFE
|
||||
WFE // Go into standby
|
||||
#endif
|
||||
B _tx_thread_smp_protect // On waking, restart the protection attempt
|
||||
|
||||
/* We do this until we have the lock. */
|
||||
// while (1)
|
||||
// {
|
||||
|
||||
_try_to_get_lock:
|
||||
|
||||
/* Disable interrupts so we don't get preempted. */
|
||||
|
||||
MRS x0, DAIF // Pickup current interrupt posture
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
|
||||
/* Pickup the CPU ID. */
|
||||
|
||||
MRS x1, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x7, x1, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x7, x1, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x1, x1, x7, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
|
||||
/* Do we already have protection? */
|
||||
// if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core)
|
||||
// {
|
||||
|
||||
LDR w3, [x2, #4] // Pickup the owning core
|
||||
CMP w3, w1 // Is it this core?
|
||||
BEQ _got_lock_after_waiting // Yes, the protection is already owned. This means
|
||||
// an ISR preempted us and got protection
|
||||
|
||||
// }
|
||||
|
||||
/* Are we at the front of the list? */
|
||||
// if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head])
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_list_head // Get the address of the head
|
||||
LDR w3, [x3] // Get the value of the head
|
||||
LDR x4, =_tx_thread_smp_protect_wait_list // Get the address of the list
|
||||
LDR w4, [x4, x3, LSL #2] // Get the value at the head index
|
||||
|
||||
CMP w1, w4
|
||||
BNE _did_not_get_lock
|
||||
|
||||
/* Is the lock still available? */
|
||||
// if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0)
|
||||
// {
|
||||
|
||||
LDAXR w3, [x2, #0] // Pickup the protection flag
|
||||
CMP w3, #0
|
||||
BNE _did_not_get_lock // No, protection not available
|
||||
|
||||
/* Get the lock. */
|
||||
// _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1;
|
||||
|
||||
MOV w3, #1 // Build lock value
|
||||
STXR w4, w3, [x2, #0] // Attempt to get the protection
|
||||
CMP w4, #0
|
||||
BNE _did_not_get_lock // Did it fail?
|
||||
DMB ISH //
|
||||
|
||||
/* Got the lock. */
|
||||
// _tx_thread_smp_protect_lock_got();
|
||||
|
||||
_tx_thread_smp_protect_lock_got
|
||||
|
||||
/* Remove this core from the wait list. */
|
||||
// _tx_thread_smp_protect_remove_from_front_of_list();
|
||||
|
||||
_tx_thread_smp_protect_remove_from_front_of_list
|
||||
|
||||
B _got_lock_after_waiting
|
||||
|
||||
_did_not_get_lock:
|
||||
|
||||
/* For one reason or another, we didn't get the lock. */
|
||||
|
||||
/* Were we removed from the list? This can happen if we're a thread
|
||||
and we got preempted. */
|
||||
// if (_tx_thread_smp_protect_wait_counts[this_core] == 0)
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_counts // Load wait list counts
|
||||
LDR w4, [x3, x1, LSL #2] // Load waiting value for this core
|
||||
CMP w4, #0
|
||||
BNE _already_in_list1 // Is this core already in the list?
|
||||
|
||||
/* Add ourselves to the list. */
|
||||
// _tx_thread_smp_protect_wait_list_add(this_core);
|
||||
|
||||
_tx_thread_smp_protect_wait_list_add // Call macro to add ourselves to the list
|
||||
|
||||
/* Our waiting count was also reset when we were preempted. Increment it again. */
|
||||
// _tx_thread_smp_protect_wait_counts[this_core]++;
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_counts // Load wait list counts
|
||||
LDR w4, [x3, x1, LSL #2] // Load waiting value for this core
|
||||
ADD w4, w4, #1 // Increment wait value
|
||||
STR w4, [x3, x1, LSL #2] // Store new wait value value
|
||||
|
||||
// }
|
||||
|
||||
_already_in_list1:
|
||||
|
||||
/* Restore interrupts and try again. */
|
||||
|
||||
_get_protection:
|
||||
MOV x4, #1 // Build lock value
|
||||
STXR w5, w4, [x1] // Attempt to get the protection
|
||||
CBZ w5, _got_protection // Did it succeed? w5 = 0 means success!
|
||||
MSR DAIF, x0 // Restore interrupts
|
||||
ISB //
|
||||
#ifdef TX_ENABLE_WFE
|
||||
WFE // Go into standby
|
||||
#endif
|
||||
B _try_to_get_lock // On waking, restart the protection attempt
|
||||
|
||||
_got_lock_after_waiting:
|
||||
|
||||
/* We're no longer waiting. */
|
||||
// _tx_thread_smp_protect_wait_counts[this_core]--;
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_counts // Load waiting list
|
||||
LDR w4, [x3, x1, LSL #2] // Load current wait value
|
||||
SUB w4, w4, #1 // Decrement wait value
|
||||
STR w4, [x3, x1, LSL #2] // Store new wait value value
|
||||
|
||||
/* Restore registers and return. */
|
||||
|
||||
_return:
|
||||
|
||||
B _tx_thread_smp_protect // Restart the protection attempt
|
||||
|
||||
_got_protection:
|
||||
DMB ISH //
|
||||
STR w2, [x1, #4] // Save owning core
|
||||
_owned:
|
||||
LDR w5, [x1, #8] // Pickup ownership count
|
||||
ADD w5, w5, #1 // Increment ownership count
|
||||
STR w5, [x1, #8] // Store ownership count
|
||||
DMB ISH //
|
||||
RET
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_smp_unprotect Cortex-A35-SMP/GCC */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
@@ -60,10 +60,13 @@
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 10-15-2021 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.9 */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 10-15-2021 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.9 */
|
||||
/* 04-25-2022 William E. Lamie Modified comments, removed */
|
||||
/* FIFO queueing, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.global _tx_thread_smp_unprotect
|
||||
@@ -105,11 +108,6 @@ _tx_thread_smp_unprotect:
|
||||
CMP w3, #0 // Is the preempt disable flag set?
|
||||
BNE _still_protected // Yes, skip the protection release
|
||||
|
||||
LDR x2,=_tx_thread_smp_protect_wait_counts // Build build address of wait counts
|
||||
LDR w3, [x2, x1, LSL #2] // Pickup wait list value
|
||||
CMP w3, #0 // Are any entities on this core waiting?
|
||||
BNE _still_protected // Yes, skip the protection release
|
||||
|
||||
LDR x2,=_tx_thread_smp_protection // Build address of protection structure
|
||||
MOV w3, #0xFFFFFFFF // Build invalid value
|
||||
STR w3, [x2, #4] // Mark the protected core as invalid
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M0+/AC6 */
|
||||
/* 6.1.10 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 01-31-2022 Scott Larson Initial Version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -123,13 +126,13 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
@@ -473,7 +476,8 @@ __attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_i
|
||||
{
|
||||
unsigned int interrupt_save;
|
||||
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_ipsr_value() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M0+/AC6 */
|
||||
/* 6.1.10 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -63,6 +63,8 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 01-31-2022 Scott Larson Initial Version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -338,14 +340,23 @@ __tx_ts_restore:
|
||||
CMP r0, #0
|
||||
BEQ skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
MOV r8, r1 // Copy thread ptr
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CMP r1, #0
|
||||
MOVS r6, #0x8C
|
||||
LDR r2, [r0, r6] // Pickup MPU region 5 address
|
||||
CMP r2, #0
|
||||
BEQ skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOVS r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
MOVS r6, #0x10
|
||||
BICS r2, r2, r6 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Initialize loop to configure MPU registers
|
||||
// Order doesn't matter, so txm_module_instance_mpu_registers[0]
|
||||
// will be in region 7 and txm_module_instance_mpu_registers[7] will be in region 0.
|
||||
MOVS r3, #0x64 // Index of MPU register settings in thread control block
|
||||
ADD r0, r0, r3 // Build address of MPU register start in thread control block
|
||||
MOVS r5, #0 // Select region 0
|
||||
@@ -359,7 +370,7 @@ _tx_mpu_loop:
|
||||
ADDS r5, r5, #1 // Increment to next region
|
||||
CMP r5, #8 // Check if all regions have been set
|
||||
BNE _tx_mpu_loop
|
||||
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOVS r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M0+/GNU */
|
||||
/* 6.1.10 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 01-31-2022 Scott Larson Initial Version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -138,13 +141,13 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
@@ -305,7 +308,7 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -487,7 +490,8 @@ __attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_i
|
||||
{
|
||||
unsigned int interrupt_save;
|
||||
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_ipsr_value() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M0+/GNU */
|
||||
/* 6.1.10 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -63,6 +63,8 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 01-31-2022 Scott Larson Initial Version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -338,14 +340,23 @@ __tx_ts_restore:
|
||||
CMP r0, #0
|
||||
BEQ skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
MOV r8, r1 // Copy thread ptr
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CMP r1, #0
|
||||
MOVS r6, #0x8C
|
||||
LDR r2, [r0, r6] // Pickup MPU region 5 address
|
||||
CMP r2, #0
|
||||
BEQ skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOVS r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
MOVS r6, #0x10
|
||||
BICS r2, r2, r6 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Initialize loop to configure MPU registers
|
||||
// Order doesn't matter, so txm_module_instance_mpu_registers[0]
|
||||
// will be in region 7 and txm_module_instance_mpu_registers[7] will be in region 0.
|
||||
MOVS r3, #0x64 // Index of MPU register settings in thread control block
|
||||
ADD r0, r0, r3 // Build address of MPU register start in thread control block
|
||||
MOVS r5, #0 // Select region 0
|
||||
@@ -359,7 +370,7 @@ _tx_mpu_loop:
|
||||
ADDS r5, r5, #1 // Increment to next region
|
||||
CMP r5, #8 // Check if all regions have been set
|
||||
BNE _tx_mpu_loop
|
||||
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOVS r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -58,9 +58,9 @@ __vector_table
|
||||
|
||||
DC32 NMI_Handler ; NMI
|
||||
DC32 HardFault_Handler ; HardFault
|
||||
DC32 MemManage_Handler ; MemManage
|
||||
DC32 0 ; BusFault
|
||||
DC32 0 ; UsageFault
|
||||
DC32 HardFault_Handler ; MemManage
|
||||
DC32 HardFault_Handler ; BusFault
|
||||
DC32 HardFault_Handler ; UsageFault
|
||||
DC32 0 ; 7
|
||||
DC32 0 ; 8
|
||||
DC32 0 ; 9
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M0+/IAR */
|
||||
/* 6.1.10 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 01-31-2022 Scott Larson Initial Version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -142,14 +145,14 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#else
|
||||
ULONG _tx_misra_time_stamp_get(VOID);
|
||||
@@ -361,7 +364,7 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -532,7 +535,7 @@ static void _tx_thread_system_return_inline(void)
|
||||
__istate_t interrupt_save;
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_IPSR() == 0)
|
||||
{
|
||||
interrupt_save = __get_interrupt_state();
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M0+/IAR */
|
||||
/* 6.1.10 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -69,6 +69,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 01-31-2022 Scott Larson Initial Version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* change handler name, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -103,12 +106,8 @@ __tx_wait_here:
|
||||
|
||||
/* Memory Exception Handler. */
|
||||
|
||||
PUBLIC MemManage_Handler
|
||||
PUBLIC BusFault_Handler
|
||||
PUBLIC UsageFault_Handler
|
||||
MemManage_Handler:
|
||||
BusFault_Handler:
|
||||
UsageFault_Handler:
|
||||
PUBLIC HardFault_Handler
|
||||
HardFault_Handler:
|
||||
|
||||
CPSID i // Disable interrupts
|
||||
|
||||
@@ -326,14 +325,23 @@ __tx_ts_restore:
|
||||
CMP r0, #0
|
||||
BEQ skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
MOV r8, r1 // Copy thread ptr
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CMP r1, #0
|
||||
MOVS r6, #0x8C
|
||||
LDR r2, [r0, r6] // Pickup MPU region 5 address
|
||||
CMP r2, #0
|
||||
BEQ skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOVS r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
MOVS r6, #0x10
|
||||
BICS r2, r2, r6 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Initialize loop to configure MPU registers
|
||||
// Order doesn't matter, so txm_module_instance_mpu_registers[0]
|
||||
// will be in region 7 and txm_module_instance_mpu_registers[7] will be in region 0.
|
||||
MOVS r3, #0x64 // Index of MPU register settings in thread control block
|
||||
ADD r0, r0, r3 // Build address of MPU register start in thread control block
|
||||
MOVS r5, #0 // Select region 0
|
||||
@@ -347,7 +355,7 @@ _tx_mpu_loop:
|
||||
ADDS r5, r5, #1 // Increment to next region
|
||||
CMP r5, #8 // Check if all regions have been set
|
||||
BNE _tx_mpu_loop
|
||||
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOVS r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M23/AC6 */
|
||||
/* 6.1.6 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 04-02-2021 Scott Larson Initial Version 6.1.6 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -163,7 +166,7 @@ UINT _tx_thread_secure_stack_free(struct TX_THREAD_STRUCT *tx_thread);
|
||||
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
|
||||
#endif
|
||||
|
||||
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
|
||||
#endif
|
||||
|
||||
@@ -175,17 +178,17 @@ UINT _tx_thread_secure_stack_free(struct TX_THREAD_STRUCT *tx_thread);
|
||||
|
||||
|
||||
/* Define the clock source for trace event entry time stamp. The following two item are port specific.
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#else
|
||||
ULONG _tx_misra_time_stamp_get(VOID);
|
||||
@@ -214,7 +217,7 @@ ULONG _tx_misra_time_stamp_get(VOID);
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
|
||||
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
|
||||
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
|
||||
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
|
||||
define is negated, thereby forcing the stack fill which is necessary for the stack checking
|
||||
@@ -228,7 +231,7 @@ ULONG _tx_misra_time_stamp_get(VOID);
|
||||
|
||||
|
||||
/* Define the TX_THREAD control block extensions for this port. The main reason
|
||||
for the multiple macros is so that backward compatibility can be maintained with
|
||||
for the multiple macros is so that backward compatibility can be maintained with
|
||||
existing ThreadX kernel awareness modules. */
|
||||
|
||||
#define TX_THREAD_EXTENSION_0
|
||||
@@ -284,7 +287,7 @@ ULONG _tx_misra_time_stamp_get(VOID);
|
||||
VOID (*tx_timer_module_expiration_function)(ULONG id);
|
||||
|
||||
|
||||
/* Define the user extension field of the thread control block. Nothing
|
||||
/* Define the user extension field of the thread control block. Nothing
|
||||
additional is needed for this port so it is defined as white space. */
|
||||
|
||||
#ifndef TX_THREAD_USER_EXTENSION
|
||||
@@ -362,9 +365,9 @@ static void _set_control(unsigned int _control)
|
||||
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _get_control(); \
|
||||
_tx_vfp_state = _get_control(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_set_control(_tx_vfp_state);; \
|
||||
_set_control(_tx_vfp_state);; \
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -392,26 +395,26 @@ void _tx_vfp_access(void);
|
||||
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
|
||||
{ \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _get_control(); \
|
||||
_tx_vfp_state = _get_control(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_set_control(_tx_vfp_state); \
|
||||
_set_control(_tx_vfp_state); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _get_control(); \
|
||||
_tx_vfp_state = _get_control(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
|
||||
_tx_vfp_access(); \
|
||||
if (_tx_vfp_state == ((ULONG) 0)) \
|
||||
{ \
|
||||
_tx_vfp_state = _get_control(); \
|
||||
_tx_vfp_state = _get_control(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_set_control(_tx_vfp_state); \
|
||||
_set_control(_tx_vfp_state); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
@@ -481,7 +484,7 @@ void _tx_vfp_access(void);
|
||||
|
||||
|
||||
/* Define the get system state macro. */
|
||||
|
||||
|
||||
#ifndef TX_THREAD_GET_SYSTEM_STATE
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _get_ipsr())
|
||||
@@ -507,15 +510,12 @@ extern void _tx_thread_secure_stack_initialize(void);
|
||||
#define TX_INITIALIZE_KERNEL_ENTER_EXTENSION _tx_thread_secure_stack_initialize();
|
||||
#endif
|
||||
|
||||
/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
|
||||
/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
|
||||
prevent early scheduling on Cortex-M parts. */
|
||||
|
||||
|
||||
#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
|
||||
|
||||
|
||||
/* Determine if the ARM architecture has the CLZ instruction. This is available on
|
||||
architectures v5 and above. If available, redefine the macro for calculating the
|
||||
lowest bit set. */
|
||||
|
||||
#ifndef TX_DISABLE_INLINE
|
||||
|
||||
@@ -557,7 +557,7 @@ unsigned int was_masked;
|
||||
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (_get_ipsr() == 0)
|
||||
{
|
||||
was_masked = __disable_irq();
|
||||
@@ -572,8 +572,8 @@ unsigned int was_masked;
|
||||
/* Define the version ID of ThreadX. This may be utilized by the application. */
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M23/AC6 Version 6.1.9 *";
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M23/AC6 Version 6.1.11 *";
|
||||
#else
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
extern CHAR _tx_version_id[100];
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M23/AC6 */
|
||||
/* 6.1.6 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -63,6 +63,8 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 04-02-2021 Scott Larson Initial Version 6.1.6 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -373,12 +375,20 @@ _skip_secure_restore:
|
||||
LDR r0, [r1, r2] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
MOV r8, r1 // Copy thread ptr
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
MOVS r2, #0x74 // Index of MPU data region
|
||||
LDR r2, [r0, r2] // Pickup MPU data region address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOVS r1, #2 // Select MPU region 2
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 2
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 2
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Initialize loop to configure MPU registers
|
||||
// Order doesn't matter, so txm_module_instance_mpu_registers[0]
|
||||
// will be in region 7 and txm_module_instance_mpu_registers[7] will be in region 0.
|
||||
MOVS r3, #0x64 // Index of MPU register settings in thread control block
|
||||
ADD r0, r0, r3 // Build address of MPU register start in thread control block
|
||||
MOVS r5, #0 // Select region 0
|
||||
@@ -392,7 +402,7 @@ _tx_mpu_loop:
|
||||
ADDS r5, r5, #1 // Increment to next region
|
||||
CMP r5, #8 // Check if all regions have been set
|
||||
BNE _tx_mpu_loop
|
||||
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOVS r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M23/GNU */
|
||||
/* 6.1.7 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -58,6 +58,9 @@
|
||||
/* added symbol to enable */
|
||||
/* stack error handler, */
|
||||
/* resulting in version 6.1.7 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -172,7 +175,7 @@ UINT _tx_thread_secure_stack_free(struct TX_THREAD_STRUCT *tx_thread);
|
||||
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
|
||||
#endif
|
||||
|
||||
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
|
||||
#endif
|
||||
|
||||
@@ -184,17 +187,17 @@ UINT _tx_thread_secure_stack_free(struct TX_THREAD_STRUCT *tx_thread);
|
||||
|
||||
|
||||
/* Define the clock source for trace event entry time stamp. The following two item are port specific.
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#else
|
||||
ULONG _tx_misra_time_stamp_get(VOID);
|
||||
@@ -223,7 +226,7 @@ ULONG _tx_misra_time_stamp_get(VOID);
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
|
||||
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
|
||||
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
|
||||
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
|
||||
define is negated, thereby forcing the stack fill which is necessary for the stack checking
|
||||
@@ -237,7 +240,7 @@ ULONG _tx_misra_time_stamp_get(VOID);
|
||||
|
||||
|
||||
/* Define the TX_THREAD control block extensions for this port. The main reason
|
||||
for the multiple macros is so that backward compatibility can be maintained with
|
||||
for the multiple macros is so that backward compatibility can be maintained with
|
||||
existing ThreadX kernel awareness modules. */
|
||||
|
||||
#define TX_THREAD_EXTENSION_0
|
||||
@@ -293,7 +296,7 @@ ULONG _tx_misra_time_stamp_get(VOID);
|
||||
VOID (*tx_timer_module_expiration_function)(ULONG id);
|
||||
|
||||
|
||||
/* Define the user extension field of the thread control block. Nothing
|
||||
/* Define the user extension field of the thread control block. Nothing
|
||||
additional is needed for this port so it is defined as white space. */
|
||||
|
||||
#ifndef TX_THREAD_USER_EXTENSION
|
||||
@@ -359,7 +362,7 @@ inline static unsigned int _get_ipsr(void)
|
||||
|
||||
|
||||
/* Define the get system state macro. */
|
||||
|
||||
|
||||
#ifndef TX_THREAD_GET_SYSTEM_STATE
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _get_ipsr())
|
||||
@@ -385,15 +388,12 @@ extern void _tx_thread_secure_stack_initialize(void);
|
||||
#define TX_INITIALIZE_KERNEL_ENTER_EXTENSION _tx_thread_secure_stack_initialize();
|
||||
#endif
|
||||
|
||||
/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
|
||||
/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to
|
||||
prevent early scheduling on Cortex-M parts. */
|
||||
|
||||
|
||||
#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
|
||||
|
||||
|
||||
/* Determine if the ARM architecture has the CLZ instruction. This is available on
|
||||
architectures v5 and above. If available, redefine the macro for calculating the
|
||||
lowest bit set. */
|
||||
|
||||
#ifndef TX_DISABLE_INLINE
|
||||
|
||||
@@ -449,7 +449,8 @@ __attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_i
|
||||
{
|
||||
unsigned int interrupt_save;
|
||||
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (_get_ipsr() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
@@ -482,8 +483,8 @@ unsigned int interrupt_save;
|
||||
/* Define the version ID of ThreadX. This may be utilized by the application. */
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M23/GNU Version 6.1.9 *";
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M23/GNU Version 6.1.11 *";
|
||||
#else
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
extern CHAR _tx_version_id[100];
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M23/GNU */
|
||||
/* 6.1.6 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -59,6 +59,8 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 04-02-2021 Scott Larson Initial Version 6.1.6 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -369,12 +371,20 @@ _skip_secure_restore:
|
||||
LDR r0, [r1, r2] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
MOV r8, r1 // Copy thread ptr
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
MOVS r2, #0x74 // Index of MPU data region
|
||||
LDR r2, [r0, r2] // Pickup MPU data region address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOVS r1, #2 // Select MPU region 2
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 2
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 2
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Initialize loop to configure MPU registers
|
||||
// Order doesn't matter, so txm_module_instance_mpu_registers[0]
|
||||
// will be in region 7 and txm_module_instance_mpu_registers[7] will be in region 0.
|
||||
MOVS r3, #0x64 // Index of MPU register settings in thread control block
|
||||
ADD r0, r0, r3 // Build address of MPU register start in thread control block
|
||||
MOVS r5, #0 // Select region 0
|
||||
@@ -388,7 +398,7 @@ _tx_mpu_loop:
|
||||
ADDS r5, r5, #1 // Increment to next region
|
||||
CMP r5, #8 // Check if all regions have been set
|
||||
BNE _tx_mpu_loop
|
||||
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOVS r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h ARMv8-M */
|
||||
/* 6.1.6 */
|
||||
/* tx_port.h Cortex-M23/IAR */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 04-02-2021 Scott Larson Initial Version 6.1.6 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -179,7 +182,7 @@ UINT _tx_thread_secure_stack_free(struct TX_THREAD_STRUCT *tx_thread);
|
||||
#endif
|
||||
|
||||
|
||||
/* Define various constants for the ThreadX Cortex-M port. */
|
||||
/* Define various constants for the ThreadX Cortex-M23 port. */
|
||||
|
||||
#define TX_INT_DISABLE 1 /* Disable interrupts */
|
||||
#define TX_INT_ENABLE 0 /* Enable interrupts */
|
||||
@@ -189,14 +192,14 @@ UINT _tx_thread_secure_stack_free(struct TX_THREAD_STRUCT *tx_thread);
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#else
|
||||
ULONG _tx_misra_time_stamp_get(VOID);
|
||||
@@ -464,7 +467,7 @@ __attribute__( ( always_inline ) ) static inline void __set_CONTROL(ULONG contro
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -644,7 +647,7 @@ __attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_i
|
||||
unsigned int interrupt_save;
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_IPSR() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
@@ -665,7 +668,7 @@ static void _tx_thread_system_return_inline(void)
|
||||
__istate_t interrupt_save;
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_IPSR() == 0)
|
||||
{
|
||||
interrupt_save = __get_interrupt_state();
|
||||
@@ -701,7 +704,7 @@ VOID _tx_thread_interrupt_restore(UIN
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Modules ARMv8-M Version 6.1.9 *";
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M23/IAR Version 6.1.11 *";
|
||||
#else
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
extern CHAR _tx_version_id[100];
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M23/IAR */
|
||||
/* 6.1.6 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -75,6 +75,8 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 04-02-2021 Scott Larson Initial Version 6.1.6 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -370,12 +372,20 @@ _skip_secure_restore:
|
||||
LDR r0, [r1, r2] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
MOV r8, r1 // Copy thread ptr
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
MOVS r2, #0x74 // Index of MPU data region
|
||||
LDR r2, [r0, r2] // Pickup MPU data region address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOVS r1, #2 // Select MPU region 2
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 2
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 2
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Initialize loop to configure MPU registers
|
||||
// Order doesn't matter, so txm_module_instance_mpu_registers[0]
|
||||
// will be in region 7 and txm_module_instance_mpu_registers[7] will be in region 0.
|
||||
MOVS r3, #0x64 // Index of MPU register settings in thread control block
|
||||
ADD r0, r0, r3 // Build address of MPU register start in thread control block
|
||||
MOVS r5, #0 // Select region 0
|
||||
@@ -389,7 +399,7 @@ _tx_mpu_loop:
|
||||
ADDS r5, r5, #1 // Increment to next region
|
||||
CMP r5, #8 // Check if all regions have been set
|
||||
BNE _tx_mpu_loop
|
||||
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOVS r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M3/AC5 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -123,13 +126,13 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
@@ -282,7 +285,7 @@ void _tx_vfp_access(void);
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -435,7 +438,7 @@ unsigned int was_masked;
|
||||
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (_ipsr == 0)
|
||||
{
|
||||
was_masked = __disable_irq();
|
||||
@@ -458,7 +461,7 @@ void tx_thread_fpu_disable(void);
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M3/AC5 Version 6.1.9 *";
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M3/AC5 Version 6.1.11 *";
|
||||
#else
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
extern CHAR _tx_version_id[100];
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M3/AC5 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -67,13 +67,15 @@
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -125,7 +127,12 @@ __tx_wait_here
|
||||
|
||||
EXPORT MemManage_Handler
|
||||
MemManage_Handler
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -208,7 +215,12 @@ MemManage_Handler
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
MOV lr, #0xFFFFFFFD // Load exception return code
|
||||
BX lr // Return from exception
|
||||
|
||||
@@ -226,12 +238,22 @@ __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
|
||||
#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
|
||||
@@ -276,7 +298,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -285,7 +312,12 @@ __tx_ts_new
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -293,7 +325,12 @@ __tx_ts_wait
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -310,7 +347,12 @@ __tx_ts_restore
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -346,27 +388,34 @@ __tx_ts_restore
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
BIC r2, r2, #0x10 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
ADD r0, r0, #100 // Build address of MPU register start in thread control block
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
|
||||
LDM r0!,{r2-r9} // Load MPU regions 0-3
|
||||
STM r1,{r2-r9} // Store MPU regions 0-3
|
||||
LDM r0!,{r2-r9} // Load MPU regions 4-7
|
||||
STM r1,{r2-r9} // Store MPU regions 4-7
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
LDM r0!,{r2-r9} // Load MPU regions 8-11
|
||||
STM r1,{r2-r9} // Store MPU regions 8-11
|
||||
LDM r0,{r2-r9} // Load MPU regions 12-15
|
||||
STM r1,{r2-r9} // Store MPU regions 12-15
|
||||
#else
|
||||
LDM r0!,{r2-r9} // Load first four MPU regions
|
||||
STM r1,{r2-r9} // Store first four MPU regions
|
||||
LDM r0,{r2-r9} // Load second four MPU regions
|
||||
STM r1,{r2-r9} // Store second four MPU regions
|
||||
#endif
|
||||
_tx_enable_mpu
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M3/AC6 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -123,13 +126,13 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
@@ -291,7 +294,7 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -467,7 +470,8 @@ __attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_i
|
||||
{
|
||||
unsigned int interrupt_save;
|
||||
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_ipsr_value() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
@@ -497,7 +501,7 @@ unsigned int interrupt_save;
|
||||
#endif
|
||||
|
||||
|
||||
/* Define FPU extension for the Cortex-M7. Each is assumed to be called in the context of the executing
|
||||
/* Define FPU extension for the Cortex-M3. Each is assumed to be called in the context of the executing
|
||||
thread. These are no longer needed, but are preserved for backward compatibility only. */
|
||||
|
||||
void tx_thread_fpu_enable(void);
|
||||
@@ -508,7 +512,7 @@ void tx_thread_fpu_disable(void);
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M3/AC6 Version 6.1.9 *";
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M3/AC6 Version 6.1.11 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M3/AC6 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -69,13 +69,15 @@
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -135,7 +137,12 @@ BusFault_Handler:
|
||||
.thumb_func
|
||||
UsageFault_Handler:
|
||||
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -197,7 +204,7 @@ UsageFault_Handler:
|
||||
LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
|
||||
LDR r1, [r0] // Load FPCCR
|
||||
BIC r1, r1, #1 // Clear the lazy preservation active bit
|
||||
STR r1, [r0] // Store the value
|
||||
STR r1, [r0] // Save FPCCR
|
||||
#endif
|
||||
|
||||
BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
|
||||
@@ -218,7 +225,12 @@ UsageFault_Handler:
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
MOV lr, #0xFFFFFFFD // Load exception return code
|
||||
BX lr // Return from exception
|
||||
|
||||
@@ -239,12 +251,22 @@ __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
|
||||
#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
|
||||
@@ -289,7 +311,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -298,7 +325,12 @@ __tx_ts_new:
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -306,7 +338,12 @@ __tx_ts_wait:
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -323,7 +360,12 @@ __tx_ts_restore:
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -359,27 +401,34 @@ __tx_ts_restore:
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
BIC r2, r2, #0x10 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
ADD r0, r0, #100 // Build address of MPU register start in thread control block
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
|
||||
LDM r0!,{r2-r9} // Load MPU regions 0-3
|
||||
STM r1,{r2-r9} // Store MPU regions 0-3
|
||||
LDM r0!,{r2-r9} // Load MPU regions 4-7
|
||||
STM r1,{r2-r9} // Store MPU regions 4-7
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
LDM r0!,{r2-r9} // Load MPU regions 8-11
|
||||
STM r1,{r2-r9} // Store MPU regions 8-11
|
||||
LDM r0,{r2-r9} // Load MPU regions 12-15
|
||||
STM r1,{r2-r9} // Store MPU regions 12-15
|
||||
#else
|
||||
LDM r0!,{r2-r9} // Load first four MPU regions
|
||||
STM r1,{r2-r9} // Store first four MPU regions
|
||||
LDM r0,{r2-r9} // Load second four MPU regions
|
||||
STM r1,{r2-r9} // Store second four MPU regions
|
||||
#endif
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
@@ -538,14 +587,14 @@ _tx_no_lazy_clear:
|
||||
#endif
|
||||
|
||||
/* Copy kernel hardware stack to module thread stack. */
|
||||
LDM r3!, {r1-r2}
|
||||
STM r0!, {r1-r2}
|
||||
LDM r3!, {r1-r2}
|
||||
STM r0!, {r1-r2}
|
||||
LDM r3!, {r1-r2}
|
||||
STM r0!, {r1-r2}
|
||||
LDM r3!, {r1-r2}
|
||||
STM r0!, {r1-r2}
|
||||
LDM r3!, {r1-r2} // Get r0, r1 from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r0, r1 into thread stack
|
||||
LDM r3!, {r1-r2} // Get r2, r3 from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r2, r3 into thread stack
|
||||
LDM r3!, {r1-r2} // Get r12, lr from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r12, lr into thread stack
|
||||
LDM r3!, {r1-r2} // Get pc, xpsr from kernel stack
|
||||
STM r0!, {r1-r2} // Insert pc, xpsr into thread stack
|
||||
SUB r0, r0, #32 // Subtract 32 to get back to top of stack
|
||||
MSR PSP, r0 // Set thread stack pointer
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M3/GNU */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -123,13 +126,13 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
@@ -291,7 +294,7 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -461,7 +464,8 @@ __attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_i
|
||||
{
|
||||
unsigned int interrupt_save;
|
||||
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_ipsr_value() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
@@ -491,8 +495,8 @@ unsigned int interrupt_save;
|
||||
#endif
|
||||
|
||||
|
||||
/* Define FPU extension for the Cortex-M7. Each is assumed to be called in the context of the executing
|
||||
thread. This is for legacy only, and not needed any longer. */
|
||||
/* Define FPU extension for the Cortex-M3. Each is assumed to be called in the context of the executing
|
||||
thread. These are no longer needed, but are preserved for backward compatibility only. */
|
||||
|
||||
void tx_thread_fpu_enable(void);
|
||||
void tx_thread_fpu_disable(void);
|
||||
@@ -502,7 +506,7 @@ void tx_thread_fpu_disable(void);
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M3/GNU Version 6.1.9 *";
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M3/GNU Version 6.1.11 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M3/GNU */
|
||||
/* 6.1.10 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -67,7 +67,6 @@
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
@@ -76,6 +75,9 @@
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 01-31-2022 Scott Larson Fixed predefined macro name, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -135,7 +137,12 @@ BusFault_Handler:
|
||||
.thumb_func
|
||||
UsageFault_Handler:
|
||||
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -197,7 +204,7 @@ UsageFault_Handler:
|
||||
LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
|
||||
LDR r1, [r0] // Load FPCCR
|
||||
BIC r1, r1, #1 // Clear the lazy preservation active bit
|
||||
STR r1, [r0] // Store the value
|
||||
STR r1, [r0] // Save FPCCR
|
||||
#endif
|
||||
|
||||
BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
|
||||
@@ -218,7 +225,12 @@ UsageFault_Handler:
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
MOV lr, #0xFFFFFFFD // Load exception return code
|
||||
BX lr // Return from exception
|
||||
|
||||
@@ -239,12 +251,22 @@ __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
|
||||
#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
|
||||
@@ -289,7 +311,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -298,7 +325,12 @@ __tx_ts_new:
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -306,7 +338,12 @@ __tx_ts_wait:
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -323,7 +360,12 @@ __tx_ts_restore:
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -359,27 +401,34 @@ __tx_ts_restore:
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
BIC r2, r2, #0x10 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
ADD r0, r0, #100 // Build address of MPU register start in thread control block
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
|
||||
LDM r0!,{r2-r9} // Load MPU regions 0-3
|
||||
STM r1,{r2-r9} // Store MPU regions 0-3
|
||||
LDM r0!,{r2-r9} // Load MPU regions 4-7
|
||||
STM r1,{r2-r9} // Store MPU regions 4-7
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
LDM r0!,{r2-r9} // Load MPU regions 8-11
|
||||
STM r1,{r2-r9} // Store MPU regions 8-11
|
||||
LDM r0,{r2-r9} // Load MPU regions 12-15
|
||||
STM r1,{r2-r9} // Store MPU regions 12-15
|
||||
#else
|
||||
LDM r0!,{r2-r9} // Load first four MPU regions
|
||||
STM r1,{r2-r9} // Store first four MPU regions
|
||||
LDM r0,{r2-r9} // Load second four MPU regions
|
||||
STM r1,{r2-r9} // Store second four MPU regions
|
||||
#endif
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M3/IAR */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -127,14 +130,14 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#else
|
||||
ULONG _tx_misra_time_stamp_get(VOID);
|
||||
@@ -325,7 +328,7 @@ void _tx_misra_vfp_touch(void);
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -476,7 +479,7 @@ static void _tx_thread_system_return_inline(void)
|
||||
__istate_t interrupt_save;
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_IPSR() == 0)
|
||||
{
|
||||
interrupt_save = __get_interrupt_state();
|
||||
@@ -488,7 +491,7 @@ __istate_t interrupt_save;
|
||||
#endif
|
||||
|
||||
|
||||
/* Define FPU extension for the Cortex-M7. Each is assumed to be called in the context of the executing
|
||||
/* Define FPU extension for the Cortex-M3. Each is assumed to be called in the context of the executing
|
||||
thread. These are no longer needed, but are preserved for backward compatibility only. */
|
||||
|
||||
void tx_thread_fpu_enable(void);
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M3/IAR */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -63,13 +63,15 @@
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -125,8 +127,12 @@ __tx_wait_here:
|
||||
MemManage_Handler:
|
||||
BusFault_Handler:
|
||||
UsageFault_Handler:
|
||||
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -209,7 +215,12 @@ UsageFault_Handler:
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
MOV lr, #0xFFFFFFFD // Load exception return code
|
||||
BX lr // Return from exception
|
||||
|
||||
@@ -227,12 +238,22 @@ __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
|
||||
#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
|
||||
@@ -277,7 +298,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -286,7 +312,12 @@ __tx_ts_new:
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -294,7 +325,12 @@ __tx_ts_wait:
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -311,7 +347,12 @@ __tx_ts_restore:
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -347,27 +388,34 @@ __tx_ts_restore:
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
BIC r2, r2, #0x10 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
ADD r0, r0, #100 // Build address of MPU register start in thread control block
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
|
||||
LDM r0!,{r2-r9} // Load MPU regions 0-3
|
||||
STM r1,{r2-r9} // Store MPU regions 0-3
|
||||
LDM r0!,{r2-r9} // Load MPU regions 4-7
|
||||
STM r1,{r2-r9} // Store MPU regions 4-7
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
LDM r0!,{r2-r9} // Load MPU regions 8-11
|
||||
STM r1,{r2-r9} // Store MPU regions 8-11
|
||||
LDM r0,{r2-r9} // Load MPU regions 12-15
|
||||
STM r1,{r2-r9} // Store MPU regions 12-15
|
||||
#else
|
||||
LDM r0!,{r2-r9} // Load first four MPU regions
|
||||
STM r1,{r2-r9} // Store first four MPU regions
|
||||
LDM r0,{r2-r9} // Load second four MPU regions
|
||||
STM r1,{r2-r9} // Store second four MPU regions
|
||||
#endif
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M33 */
|
||||
/* 6.1.10 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -61,13 +61,16 @@
|
||||
/* added symbol to enable */
|
||||
/* stack error handler, */
|
||||
/* resulting in version 6.1.7 */
|
||||
/* 10-15-2021 Scott Larson Modified comment(s), improved */
|
||||
/* 10-15-2021 Scott Larson Modified comment(s), improved */
|
||||
/* stack check error handling, */
|
||||
/* resulting in version 6.1.9 */
|
||||
/* 01-31-2022 Scott Larson Modified comment(s), unified */
|
||||
/* this file across compilers, */
|
||||
/* fixed predefined macro, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -196,14 +199,14 @@ UINT _tx_thread_secure_stack_free(struct TX_THREAD_STRUCT *tx_thread);
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#else
|
||||
ULONG _tx_misra_time_stamp_get(VOID);
|
||||
@@ -429,9 +432,9 @@ __attribute__( ( always_inline ) ) static inline void _tx_control_set(ULONG cont
|
||||
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -456,26 +459,26 @@ __attribute__( ( always_inline ) ) static inline void _tx_control_set(ULONG cont
|
||||
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
|
||||
{ \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
|
||||
TX_VFP_TOUCH(); \
|
||||
if (_tx_vfp_state == ((ULONG) 0)) \
|
||||
{ \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
@@ -657,7 +660,7 @@ __attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_i
|
||||
UINT interrupt_save;
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (_tx_ipsr_get() == 0)
|
||||
{
|
||||
interrupt_save = __get_interrupt_posture();
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M33/MPU/AC6 */
|
||||
/* 6.1.7 */
|
||||
/* _tx_thread_schedule Cortex-M33/AC6 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -69,6 +69,9 @@
|
||||
/* 06-02-2021 Scott Larson Fixed extended stack handling */
|
||||
/* when calling kernel APIs, */
|
||||
/* resulting in version 6.1.7 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -128,7 +131,12 @@ MemManage_Handler:
|
||||
.thumb_func
|
||||
BusFault_Handler:
|
||||
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -195,7 +203,7 @@ BusFault_Handler:
|
||||
|
||||
BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
#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. */
|
||||
CPSID i // Disable interrupts
|
||||
BL _tx_execution_thread_exit // Call the thread exit function
|
||||
@@ -211,7 +219,12 @@ BusFault_Handler:
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
#ifdef TX_SINGLE_MODE_SECURE
|
||||
LDR lr, =0xFFFFFFFD // Exception return to secure
|
||||
#else
|
||||
@@ -235,12 +248,22 @@ __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
|
||||
#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
|
||||
@@ -296,7 +319,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -305,7 +333,12 @@ __tx_ts_new:
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -313,7 +346,12 @@ __tx_ts_wait:
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -330,7 +368,12 @@ __tx_ts_restore:
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -378,9 +421,17 @@ _skip_secure_restore:
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
LDR r2, [r0, #0x74] // Pickup MPU address of data region
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #2 // Select MPU region 2
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 2
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 2
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
LDR r2, =0xE000ED98 // Get region register
|
||||
@@ -393,6 +444,7 @@ _skip_secure_restore:
|
||||
STR r2, [r3] // Set region to 4
|
||||
LDM r0, {r2-r9} // Load second four MPU regions
|
||||
STM r1, {r2-r9} // Store second four MPU regions
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M33 */
|
||||
/* 6.1.10 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -61,13 +61,16 @@
|
||||
/* added symbol to enable */
|
||||
/* stack error handler, */
|
||||
/* resulting in version 6.1.7 */
|
||||
/* 10-15-2021 Scott Larson Modified comment(s), improved */
|
||||
/* 10-15-2021 Scott Larson Modified comment(s), improved */
|
||||
/* stack check error handling, */
|
||||
/* resulting in version 6.1.9 */
|
||||
/* 01-31-2022 Scott Larson Modified comment(s), unified */
|
||||
/* this file across compilers, */
|
||||
/* fixed predefined macro, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -196,14 +199,14 @@ UINT _tx_thread_secure_stack_free(struct TX_THREAD_STRUCT *tx_thread);
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#else
|
||||
ULONG _tx_misra_time_stamp_get(VOID);
|
||||
@@ -429,9 +432,9 @@ __attribute__( ( always_inline ) ) static inline void _tx_control_set(ULONG cont
|
||||
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -456,26 +459,26 @@ __attribute__( ( always_inline ) ) static inline void _tx_control_set(ULONG cont
|
||||
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
|
||||
{ \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
|
||||
TX_VFP_TOUCH(); \
|
||||
if (_tx_vfp_state == ((ULONG) 0)) \
|
||||
{ \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
@@ -657,7 +660,7 @@ __attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_i
|
||||
UINT interrupt_save;
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (_tx_ipsr_get() == 0)
|
||||
{
|
||||
interrupt_save = __get_interrupt_posture();
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M33/MPU/GNU */
|
||||
/* 6.1.10 */
|
||||
/* _tx_thread_schedule Cortex-M33/GNU */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -70,6 +70,9 @@
|
||||
/* resulting in version 6.1.7 */
|
||||
/* 01-31-2022 Scott Larson Fixed predefined macro name, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -129,7 +132,12 @@ MemManage_Handler:
|
||||
.thumb_func
|
||||
BusFault_Handler:
|
||||
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -196,7 +204,7 @@ BusFault_Handler:
|
||||
|
||||
BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
#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. */
|
||||
CPSID i // Disable interrupts
|
||||
BL _tx_execution_thread_exit // Call the thread exit function
|
||||
@@ -212,7 +220,12 @@ BusFault_Handler:
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
#ifdef TX_SINGLE_MODE_SECURE
|
||||
LDR lr, =0xFFFFFFFD // Exception return to secure
|
||||
#else
|
||||
@@ -236,12 +249,22 @@ __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
|
||||
#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
|
||||
@@ -297,7 +320,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -306,7 +334,12 @@ __tx_ts_new:
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -314,7 +347,12 @@ __tx_ts_wait:
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -331,7 +369,12 @@ __tx_ts_restore:
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -379,9 +422,17 @@ _skip_secure_restore:
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
LDR r2, [r0, #0x74] // Pickup MPU address of data region
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #2 // Select MPU region 2
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 2
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 2
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
LDR r2, =0xE000ED98 // Get region register
|
||||
@@ -394,6 +445,7 @@ _skip_secure_restore:
|
||||
STR r2, [r3] // Set region to 4
|
||||
LDM r0, {r2-r9} // Load second four MPU regions
|
||||
STM r1, {r2-r9} // Store second four MPU regions
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M33 */
|
||||
/* 6.1.10 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -61,13 +61,16 @@
|
||||
/* added symbol to enable */
|
||||
/* stack error handler, */
|
||||
/* resulting in version 6.1.7 */
|
||||
/* 10-15-2021 Scott Larson Modified comment(s), improved */
|
||||
/* 10-15-2021 Scott Larson Modified comment(s), improved */
|
||||
/* stack check error handling, */
|
||||
/* resulting in version 6.1.9 */
|
||||
/* 01-31-2022 Scott Larson Modified comment(s), unified */
|
||||
/* this file across compilers, */
|
||||
/* fixed predefined macro, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -196,14 +199,14 @@ UINT _tx_thread_secure_stack_free(struct TX_THREAD_STRUCT *tx_thread);
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#else
|
||||
ULONG _tx_misra_time_stamp_get(VOID);
|
||||
@@ -429,9 +432,9 @@ __attribute__( ( always_inline ) ) static inline void _tx_control_set(ULONG cont
|
||||
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -456,26 +459,26 @@ __attribute__( ( always_inline ) ) static inline void _tx_control_set(ULONG cont
|
||||
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
|
||||
{ \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
ULONG _tx_vfp_state; \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
|
||||
TX_VFP_TOUCH(); \
|
||||
if (_tx_vfp_state == ((ULONG) 0)) \
|
||||
{ \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_control_get(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
_tx_control_set(_tx_vfp_state); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
@@ -657,7 +660,7 @@ __attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_i
|
||||
UINT interrupt_save;
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (_tx_ipsr_get() == 0)
|
||||
{
|
||||
interrupt_save = __get_interrupt_posture();
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M33/IAR */
|
||||
/* 6.1.8 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -81,6 +81,9 @@
|
||||
/* 06-02-2021 Scott Larson Fixed extended stack handling */
|
||||
/* when calling kernel APIs, */
|
||||
/* resulting in version 6.1.7 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -132,7 +135,12 @@ __tx_wait_here:
|
||||
MemManage_Handler:
|
||||
BusFault_Handler:
|
||||
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -199,7 +207,7 @@ BusFault_Handler:
|
||||
|
||||
BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
#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. */
|
||||
CPSID i // Disable interrupts
|
||||
BL _tx_execution_thread_exit // Call the thread exit function
|
||||
@@ -215,7 +223,12 @@ BusFault_Handler:
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
#ifdef TX_SINGLE_MODE_SECURE
|
||||
LDR lr, =0xFFFFFFFD // Exception return to secure
|
||||
#else
|
||||
@@ -232,12 +245,22 @@ __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
|
||||
#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
|
||||
@@ -293,7 +316,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -302,7 +330,12 @@ __tx_ts_new:
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -310,7 +343,12 @@ __tx_ts_wait:
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -327,7 +365,12 @@ __tx_ts_restore:
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -375,9 +418,17 @@ _skip_secure_restore:
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
LDR r2, [r0, #0x74] // Pickup MPU address of data region
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #2 // Select MPU region 2
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 2
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 2
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
LDR r2, =0xE000ED98 // Get region register
|
||||
@@ -390,6 +441,7 @@ _skip_secure_restore:
|
||||
STR r2, [r3] // Set region to 4
|
||||
LDM r0, {r2-r9} // Load second four MPU regions
|
||||
STM r1, {r2-r9} // Store second four MPU regions
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
@@ -412,8 +464,8 @@ _skip_vfp_restore:
|
||||
SVC_Handler:
|
||||
TST lr, #0x04 // Determine return stack from EXC_RETURN bit 2
|
||||
ITE EQ
|
||||
MRSEQ r0, MSP // Get MSP
|
||||
MRSNE r0, PSP // Get PSP
|
||||
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 r2, [r1,#-2] // Load SVC number
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M4/AC5 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -123,13 +126,13 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
@@ -282,7 +285,7 @@ void _tx_vfp_access(void);
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -435,7 +438,7 @@ unsigned int was_masked;
|
||||
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (_ipsr == 0)
|
||||
{
|
||||
was_masked = __disable_irq();
|
||||
@@ -458,7 +461,7 @@ void tx_thread_fpu_disable(void);
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M4/AC5 Version 6.1.9 *";
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M4/AC5 Version 6.1.11 *";
|
||||
#else
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
extern CHAR _tx_version_id[100];
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M4/AC5 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -67,13 +67,15 @@
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -125,7 +127,12 @@ __tx_wait_here
|
||||
|
||||
EXPORT MemManage_Handler
|
||||
MemManage_Handler
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -208,7 +215,12 @@ MemManage_Handler
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
MOV lr, #0xFFFFFFFD // Load exception return code
|
||||
BX lr // Return from exception
|
||||
|
||||
@@ -226,12 +238,22 @@ __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
|
||||
#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
|
||||
@@ -276,7 +298,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -285,7 +312,12 @@ __tx_ts_new
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -293,7 +325,12 @@ __tx_ts_wait
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -310,7 +347,12 @@ __tx_ts_restore
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -346,27 +388,34 @@ __tx_ts_restore
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
BIC r2, r2, #0x10 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
ADD r0, r0, #100 // Build address of MPU register start in thread control block
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
|
||||
LDM r0!,{r2-r9} // Load MPU regions 0-3
|
||||
STM r1,{r2-r9} // Store MPU regions 0-3
|
||||
LDM r0!,{r2-r9} // Load MPU regions 4-7
|
||||
STM r1,{r2-r9} // Store MPU regions 4-7
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
LDM r0!,{r2-r9} // Load MPU regions 8-11
|
||||
STM r1,{r2-r9} // Store MPU regions 8-11
|
||||
LDM r0,{r2-r9} // Load MPU regions 12-15
|
||||
STM r1,{r2-r9} // Store MPU regions 12-15
|
||||
#else
|
||||
LDM r0!,{r2-r9} // Load first four MPU regions
|
||||
STM r1,{r2-r9} // Store first four MPU regions
|
||||
LDM r0,{r2-r9} // Load second four MPU regions
|
||||
STM r1,{r2-r9} // Store second four MPU regions
|
||||
#endif
|
||||
_tx_enable_mpu
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M4/AC6 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -123,13 +126,13 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
@@ -291,7 +294,7 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -467,7 +470,8 @@ __attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_i
|
||||
{
|
||||
unsigned int interrupt_save;
|
||||
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_ipsr_value() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
@@ -497,7 +501,7 @@ unsigned int interrupt_save;
|
||||
#endif
|
||||
|
||||
|
||||
/* Define FPU extension for the Cortex-M7. Each is assumed to be called in the context of the executing
|
||||
/* Define FPU extension for the Cortex-M4. Each is assumed to be called in the context of the executing
|
||||
thread. These are no longer needed, but are preserved for backward compatibility only. */
|
||||
|
||||
void tx_thread_fpu_enable(void);
|
||||
@@ -508,7 +512,7 @@ void tx_thread_fpu_disable(void);
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M4/AC6 Version 6.1.9 *";
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M4/AC6 Version 6.1.11 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M4/AC6 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -69,13 +69,15 @@
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -135,7 +137,12 @@ BusFault_Handler:
|
||||
.thumb_func
|
||||
UsageFault_Handler:
|
||||
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -197,7 +204,7 @@ UsageFault_Handler:
|
||||
LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
|
||||
LDR r1, [r0] // Load FPCCR
|
||||
BIC r1, r1, #1 // Clear the lazy preservation active bit
|
||||
STR r1, [r0] // Store the value
|
||||
STR r1, [r0] // Save FPCCR
|
||||
#endif
|
||||
|
||||
BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
|
||||
@@ -218,7 +225,12 @@ UsageFault_Handler:
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
MOV lr, #0xFFFFFFFD // Load exception return code
|
||||
BX lr // Return from exception
|
||||
|
||||
@@ -239,12 +251,22 @@ __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
|
||||
#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
|
||||
@@ -289,7 +311,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -298,7 +325,12 @@ __tx_ts_new:
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -306,7 +338,12 @@ __tx_ts_wait:
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -323,7 +360,12 @@ __tx_ts_restore:
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -359,27 +401,34 @@ __tx_ts_restore:
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
BIC r2, r2, #0x10 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
ADD r0, r0, #100 // Build address of MPU register start in thread control block
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
|
||||
LDM r0!,{r2-r9} // Load MPU regions 0-3
|
||||
STM r1,{r2-r9} // Store MPU regions 0-3
|
||||
LDM r0!,{r2-r9} // Load MPU regions 4-7
|
||||
STM r1,{r2-r9} // Store MPU regions 4-7
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
LDM r0!,{r2-r9} // Load MPU regions 8-11
|
||||
STM r1,{r2-r9} // Store MPU regions 8-11
|
||||
LDM r0,{r2-r9} // Load MPU regions 12-15
|
||||
STM r1,{r2-r9} // Store MPU regions 12-15
|
||||
#else
|
||||
LDM r0!,{r2-r9} // Load first four MPU regions
|
||||
STM r1,{r2-r9} // Store first four MPU regions
|
||||
LDM r0,{r2-r9} // Load second four MPU regions
|
||||
STM r1,{r2-r9} // Store second four MPU regions
|
||||
#endif
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
@@ -538,14 +587,14 @@ _tx_no_lazy_clear:
|
||||
#endif
|
||||
|
||||
/* Copy kernel hardware stack to module thread stack. */
|
||||
LDM r3!, {r1-r2}
|
||||
STM r0!, {r1-r2}
|
||||
LDM r3!, {r1-r2}
|
||||
STM r0!, {r1-r2}
|
||||
LDM r3!, {r1-r2}
|
||||
STM r0!, {r1-r2}
|
||||
LDM r3!, {r1-r2}
|
||||
STM r0!, {r1-r2}
|
||||
LDM r3!, {r1-r2} // Get r0, r1 from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r0, r1 into thread stack
|
||||
LDM r3!, {r1-r2} // Get r2, r3 from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r2, r3 into thread stack
|
||||
LDM r3!, {r1-r2} // Get r12, lr from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r12, lr into thread stack
|
||||
LDM r3!, {r1-r2} // Get pc, xpsr from kernel stack
|
||||
STM r0!, {r1-r2} // Insert pc, xpsr into thread stack
|
||||
SUB r0, r0, #32 // Subtract 32 to get back to top of stack
|
||||
MSR PSP, r0 // Set thread stack pointer
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M4/GNU */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -123,13 +126,13 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
@@ -291,7 +294,7 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -461,7 +464,8 @@ __attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_i
|
||||
{
|
||||
unsigned int interrupt_save;
|
||||
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_ipsr_value() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
@@ -491,8 +495,8 @@ unsigned int interrupt_save;
|
||||
#endif
|
||||
|
||||
|
||||
/* Define FPU extension for the Cortex-M7. Each is assumed to be called in the context of the executing
|
||||
thread. This is for legacy only, and not needed any longer. */
|
||||
/* Define FPU extension for the Cortex-M4. Each is assumed to be called in the context of the executing
|
||||
thread. These are no longer needed, but are preserved for backward compatibility only. */
|
||||
|
||||
void tx_thread_fpu_enable(void);
|
||||
void tx_thread_fpu_disable(void);
|
||||
@@ -502,7 +506,7 @@ void tx_thread_fpu_disable(void);
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M4/GNU Version 6.1.9 *";
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M4/GNU Version 6.1.11 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M4/GNU */
|
||||
/* 6.1.10 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -67,7 +67,6 @@
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
@@ -76,6 +75,9 @@
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 01-31-2022 Scott Larson Fixed predefined macro name, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -135,7 +137,12 @@ BusFault_Handler:
|
||||
.thumb_func
|
||||
UsageFault_Handler:
|
||||
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -197,7 +204,7 @@ UsageFault_Handler:
|
||||
LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
|
||||
LDR r1, [r0] // Load FPCCR
|
||||
BIC r1, r1, #1 // Clear the lazy preservation active bit
|
||||
STR r1, [r0] // Store the value
|
||||
STR r1, [r0] // Save FPCCR
|
||||
#endif
|
||||
|
||||
BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
|
||||
@@ -218,7 +225,12 @@ UsageFault_Handler:
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
MOV lr, #0xFFFFFFFD // Load exception return code
|
||||
BX lr // Return from exception
|
||||
|
||||
@@ -239,12 +251,22 @@ __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
|
||||
#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
|
||||
@@ -289,7 +311,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -298,7 +325,12 @@ __tx_ts_new:
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -306,7 +338,12 @@ __tx_ts_wait:
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -323,7 +360,12 @@ __tx_ts_restore:
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -359,27 +401,34 @@ __tx_ts_restore:
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
BIC r2, r2, #0x10 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
ADD r0, r0, #100 // Build address of MPU register start in thread control block
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
|
||||
LDM r0!,{r2-r9} // Load MPU regions 0-3
|
||||
STM r1,{r2-r9} // Store MPU regions 0-3
|
||||
LDM r0!,{r2-r9} // Load MPU regions 4-7
|
||||
STM r1,{r2-r9} // Store MPU regions 4-7
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
LDM r0!,{r2-r9} // Load MPU regions 8-11
|
||||
STM r1,{r2-r9} // Store MPU regions 8-11
|
||||
LDM r0,{r2-r9} // Load MPU regions 12-15
|
||||
STM r1,{r2-r9} // Store MPU regions 12-15
|
||||
#else
|
||||
LDM r0!,{r2-r9} // Load first four MPU regions
|
||||
STM r1,{r2-r9} // Store first four MPU regions
|
||||
LDM r0,{r2-r9} // Load second four MPU regions
|
||||
STM r1,{r2-r9} // Store second four MPU regions
|
||||
#endif
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M4/IAR */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -127,14 +130,14 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#else
|
||||
ULONG _tx_misra_time_stamp_get(VOID);
|
||||
@@ -325,7 +328,7 @@ void _tx_misra_vfp_touch(void);
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -476,7 +479,7 @@ static void _tx_thread_system_return_inline(void)
|
||||
__istate_t interrupt_save;
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_IPSR() == 0)
|
||||
{
|
||||
interrupt_save = __get_interrupt_state();
|
||||
@@ -488,7 +491,7 @@ __istate_t interrupt_save;
|
||||
#endif
|
||||
|
||||
|
||||
/* Define FPU extension for the Cortex-M7. Each is assumed to be called in the context of the executing
|
||||
/* Define FPU extension for the Cortex-M4. Each is assumed to be called in the context of the executing
|
||||
thread. These are no longer needed, but are preserved for backward compatibility only. */
|
||||
|
||||
void tx_thread_fpu_enable(void);
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M4/IAR */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -63,13 +63,15 @@
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -125,8 +127,12 @@ __tx_wait_here:
|
||||
MemManage_Handler:
|
||||
BusFault_Handler:
|
||||
UsageFault_Handler:
|
||||
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -209,7 +215,12 @@ UsageFault_Handler:
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
MOV lr, #0xFFFFFFFD // Load exception return code
|
||||
BX lr // Return from exception
|
||||
|
||||
@@ -227,12 +238,22 @@ __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
|
||||
#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
|
||||
@@ -277,7 +298,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -286,7 +312,12 @@ __tx_ts_new:
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -294,7 +325,12 @@ __tx_ts_wait:
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -311,7 +347,12 @@ __tx_ts_restore:
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -347,27 +388,34 @@ __tx_ts_restore:
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
BIC r2, r2, #0x10 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
ADD r0, r0, #100 // Build address of MPU register start in thread control block
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
|
||||
LDM r0!,{r2-r9} // Load MPU regions 0-3
|
||||
STM r1,{r2-r9} // Store MPU regions 0-3
|
||||
LDM r0!,{r2-r9} // Load MPU regions 4-7
|
||||
STM r1,{r2-r9} // Store MPU regions 4-7
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
LDM r0!,{r2-r9} // Load MPU regions 8-11
|
||||
STM r1,{r2-r9} // Store MPU regions 8-11
|
||||
LDM r0,{r2-r9} // Load MPU regions 12-15
|
||||
STM r1,{r2-r9} // Store MPU regions 12-15
|
||||
#else
|
||||
LDM r0!,{r2-r9} // Load first four MPU regions
|
||||
STM r1,{r2-r9} // Store first four MPU regions
|
||||
LDM r0,{r2-r9} // Load second four MPU regions
|
||||
STM r1,{r2-r9} // Store second four MPU regions
|
||||
#endif
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M7/AC5 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -123,13 +126,13 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
@@ -282,7 +285,7 @@ void _tx_vfp_access(void);
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -435,7 +438,7 @@ unsigned int was_masked;
|
||||
|
||||
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (_ipsr == 0)
|
||||
{
|
||||
was_masked = __disable_irq();
|
||||
@@ -458,7 +461,7 @@ void tx_thread_fpu_disable(void);
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M7/AC5 Version 6.1.9 *";
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M7/AC5 Version 6.1.11 *";
|
||||
#else
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
extern CHAR _tx_version_id[100];
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M7/AC5 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -67,13 +67,15 @@
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -125,7 +127,12 @@ __tx_wait_here
|
||||
|
||||
EXPORT MemManage_Handler
|
||||
MemManage_Handler
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -208,7 +215,12 @@ MemManage_Handler
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
MOV lr, #0xFFFFFFFD // Load exception return code
|
||||
BX lr // Return from exception
|
||||
|
||||
@@ -226,12 +238,22 @@ __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
|
||||
#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
|
||||
@@ -276,7 +298,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -285,7 +312,12 @@ __tx_ts_new
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -293,7 +325,12 @@ __tx_ts_wait
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -310,7 +347,12 @@ __tx_ts_restore
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -346,27 +388,34 @@ __tx_ts_restore
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
BIC r2, r2, #0x10 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
ADD r0, r0, #100 // Build address of MPU register start in thread control block
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
|
||||
LDM r0!,{r2-r9} // Load MPU regions 0-3
|
||||
STM r1,{r2-r9} // Store MPU regions 0-3
|
||||
LDM r0!,{r2-r9} // Load MPU regions 4-7
|
||||
STM r1,{r2-r9} // Store MPU regions 4-7
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
LDM r0!,{r2-r9} // Load MPU regions 8-11
|
||||
STM r1,{r2-r9} // Store MPU regions 8-11
|
||||
LDM r0,{r2-r9} // Load MPU regions 12-15
|
||||
STM r1,{r2-r9} // Store MPU regions 12-15
|
||||
#else
|
||||
LDM r0!,{r2-r9} // Load first four MPU regions
|
||||
STM r1,{r2-r9} // Store first four MPU regions
|
||||
LDM r0,{r2-r9} // Load second four MPU regions
|
||||
STM r1,{r2-r9} // Store second four MPU regions
|
||||
#endif
|
||||
_tx_enable_mpu
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M7/AC6 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -123,13 +126,13 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
@@ -291,7 +294,7 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -467,7 +470,8 @@ __attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_i
|
||||
{
|
||||
unsigned int interrupt_save;
|
||||
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_ipsr_value() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
@@ -497,7 +501,7 @@ unsigned int interrupt_save;
|
||||
#endif
|
||||
|
||||
|
||||
/* Define FPU extension for the Cortex-M7. Each is assumed to be called in the context of the executing
|
||||
/* Define FPU extension for the Cortex-M7. Each is assumed to be called in the context of the executing
|
||||
thread. These are no longer needed, but are preserved for backward compatibility only. */
|
||||
|
||||
void tx_thread_fpu_enable(void);
|
||||
@@ -508,7 +512,7 @@ void tx_thread_fpu_disable(void);
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M7/AC6 Version 6.1.9 *";
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M7/AC6 Version 6.1.11 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M7/AC6 */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -69,13 +69,15 @@
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -135,7 +137,12 @@ BusFault_Handler:
|
||||
.thumb_func
|
||||
UsageFault_Handler:
|
||||
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -197,7 +204,7 @@ UsageFault_Handler:
|
||||
LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
|
||||
LDR r1, [r0] // Load FPCCR
|
||||
BIC r1, r1, #1 // Clear the lazy preservation active bit
|
||||
STR r1, [r0] // Store the value
|
||||
STR r1, [r0] // Save FPCCR
|
||||
#endif
|
||||
|
||||
BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
|
||||
@@ -218,7 +225,12 @@ UsageFault_Handler:
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
MOV lr, #0xFFFFFFFD // Load exception return code
|
||||
BX lr // Return from exception
|
||||
|
||||
@@ -239,12 +251,22 @@ __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
|
||||
#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
|
||||
@@ -289,7 +311,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -298,7 +325,12 @@ __tx_ts_new:
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -306,7 +338,12 @@ __tx_ts_wait:
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -323,7 +360,12 @@ __tx_ts_restore:
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -359,27 +401,34 @@ __tx_ts_restore:
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
BIC r2, r2, #0x10 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
ADD r0, r0, #100 // Build address of MPU register start in thread control block
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
|
||||
LDM r0!,{r2-r9} // Load MPU regions 0-3
|
||||
STM r1,{r2-r9} // Store MPU regions 0-3
|
||||
LDM r0!,{r2-r9} // Load MPU regions 4-7
|
||||
STM r1,{r2-r9} // Store MPU regions 4-7
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
LDM r0!,{r2-r9} // Load MPU regions 8-11
|
||||
STM r1,{r2-r9} // Store MPU regions 8-11
|
||||
LDM r0,{r2-r9} // Load MPU regions 12-15
|
||||
STM r1,{r2-r9} // Store MPU regions 12-15
|
||||
#else
|
||||
LDM r0!,{r2-r9} // Load first four MPU regions
|
||||
STM r1,{r2-r9} // Store first four MPU regions
|
||||
LDM r0,{r2-r9} // Load second four MPU regions
|
||||
STM r1,{r2-r9} // Store second four MPU regions
|
||||
#endif
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
@@ -538,14 +587,14 @@ _tx_no_lazy_clear:
|
||||
#endif
|
||||
|
||||
/* Copy kernel hardware stack to module thread stack. */
|
||||
LDM r3!, {r1-r2}
|
||||
STM r0!, {r1-r2}
|
||||
LDM r3!, {r1-r2}
|
||||
STM r0!, {r1-r2}
|
||||
LDM r3!, {r1-r2}
|
||||
STM r0!, {r1-r2}
|
||||
LDM r3!, {r1-r2}
|
||||
STM r0!, {r1-r2}
|
||||
LDM r3!, {r1-r2} // Get r0, r1 from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r0, r1 into thread stack
|
||||
LDM r3!, {r1-r2} // Get r2, r3 from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r2, r3 into thread stack
|
||||
LDM r3!, {r1-r2} // Get r12, lr from kernel stack
|
||||
STM r0!, {r1-r2} // Insert r12, lr into thread stack
|
||||
LDM r3!, {r1-r2} // Get pc, xpsr from kernel stack
|
||||
STM r0!, {r1-r2} // Insert pc, xpsr into thread stack
|
||||
SUB r0, r0, #32 // Subtract 32 to get back to top of stack
|
||||
MSR PSP, r0 // Set thread stack pointer
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M7/GNU */
|
||||
/* 6.1.9 */
|
||||
/* 6.1.11 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
@@ -48,6 +48,9 @@
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 04-25-2022 Scott Larson Modified comments and added */
|
||||
/* volatile to registers, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -123,13 +126,13 @@ typedef unsigned short USHORT;
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
@@ -291,7 +294,7 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
|
||||
else \
|
||||
{ \
|
||||
ULONG _tx_fpccr; \
|
||||
_tx_fpccr = *((ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = *((volatile ULONG *) 0xE000EF34); \
|
||||
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
|
||||
if (_tx_fpccr == ((ULONG) 0x01)) \
|
||||
{ \
|
||||
@@ -461,7 +464,8 @@ __attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_i
|
||||
{
|
||||
unsigned int interrupt_save;
|
||||
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
/* Set PendSV to invoke ThreadX scheduler. */
|
||||
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_ipsr_value() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
@@ -491,8 +495,8 @@ unsigned int interrupt_save;
|
||||
#endif
|
||||
|
||||
|
||||
/* Define FPU extension for the Cortex-M7. Each is assumed to be called in the context of the executing
|
||||
thread. This is for legacy only, and not needed any longer. */
|
||||
/* Define FPU extension for the Cortex-M7. Each is assumed to be called in the context of the executing
|
||||
thread. These are no longer needed, but are preserved for backward compatibility only. */
|
||||
|
||||
void tx_thread_fpu_enable(void);
|
||||
void tx_thread_fpu_disable(void);
|
||||
@@ -502,7 +506,7 @@ void tx_thread_fpu_disable(void);
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M7/GNU Version 6.1.9 *";
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M7/GNU Version 6.1.11 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-M7/GNU */
|
||||
/* 6.1.10 */
|
||||
/* 6.1.11 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Scott Larson, Microsoft Corporation */
|
||||
@@ -67,7 +67,6 @@
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
@@ -76,6 +75,9 @@
|
||||
/* 10-15-2021 Scott Larson Initial Version 6.1.9 */
|
||||
/* 01-31-2022 Scott Larson Fixed predefined macro name, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 04-25-2022 Scott Larson Optimized MPU configuration, */
|
||||
/* added BASEPRI support, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
@@ -135,7 +137,12 @@ BusFault_Handler:
|
||||
.thumb_func
|
||||
UsageFault_Handler:
|
||||
|
||||
#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 */
|
||||
|
||||
/* Now pickup and store all the fault related information. */
|
||||
|
||||
@@ -197,7 +204,7 @@ UsageFault_Handler:
|
||||
LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address
|
||||
LDR r1, [r0] // Load FPCCR
|
||||
BIC r1, r1, #1 // Clear the lazy preservation active bit
|
||||
STR r1, [r0] // Store the value
|
||||
STR r1, [r0] // Save FPCCR
|
||||
#endif
|
||||
|
||||
BL _txm_module_manager_memory_fault_handler // Call memory manager fault handler
|
||||
@@ -218,7 +225,12 @@ UsageFault_Handler:
|
||||
LDR r1, =0x10000000 // Set PENDSVSET bit
|
||||
STR r1, [r0] // Store ICSR
|
||||
DSB // Wait for memory access to complete
|
||||
#ifdef TX_PORT_USE_BASEPRI
|
||||
MOV r0, 0 // Disable BASEPRI masking (enable interrupts)
|
||||
MSR BASEPRI, r0
|
||||
#else
|
||||
CPSIE i // Enable interrupts
|
||||
#endif
|
||||
MOV lr, #0xFFFFFFFD // Load exception return code
|
||||
BX lr // Return from exception
|
||||
|
||||
@@ -239,12 +251,22 @@ __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
|
||||
#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
|
||||
@@ -289,7 +311,12 @@ __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?
|
||||
CBNZ r1, __tx_ts_restore // Yes, schedule it
|
||||
|
||||
@@ -298,7 +325,12 @@ __tx_ts_new:
|
||||
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
|
||||
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
@@ -306,7 +338,12 @@ __tx_ts_wait:
|
||||
WFI // Wait for interrupt
|
||||
ISB // Ensure pipeline is flushed
|
||||
#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
|
||||
@@ -323,7 +360,12 @@ __tx_ts_restore:
|
||||
and enable interrupts. */
|
||||
|
||||
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. */
|
||||
|
||||
@@ -359,27 +401,34 @@ __tx_ts_restore:
|
||||
STR r3, [r0] // Disable MPU
|
||||
LDR r0, [r1, #0x90] // Pickup the module instance pointer
|
||||
CBZ r0, skip_mpu_setup // Is this thread owned by a module? No, skip MPU setup
|
||||
LDR r1, [r0, #0x64] // Pickup MPU register[0]
|
||||
CBZ r1, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
LDR r1, =0xE000ED9C // Build address of MPU base register
|
||||
|
||||
LDR r2, [r0, #0x8C] // Pickup MPU region 5 address
|
||||
CBZ r2, skip_mpu_setup // Is protection required for this module? No, skip MPU setup
|
||||
|
||||
// Is the MPU already set up for this module?
|
||||
MOV r1, #5 // Select region 5 from MPU
|
||||
LDR r3, =0xE000ED98 // MPU_RNR register address
|
||||
STR r1, [r3] // Set region to 5
|
||||
LDR r1, =0xE000ED9C // MPU_RBAR register address
|
||||
LDR r3, [r1] // Load address stored in MPU region 5
|
||||
BIC r2, r2, #0x10 // Clear VALID bit
|
||||
CMP r2, r3 // Is module already loaded?
|
||||
BEQ _tx_enable_mpu // Yes - skip MPU reconfiguration
|
||||
|
||||
// Use alias registers to quickly load MPU
|
||||
ADD r0, r0, #100 // Build address of MPU register start in thread control block
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
|
||||
LDM r0!,{r2-r9} // Load MPU regions 0-3
|
||||
STM r1,{r2-r9} // Store MPU regions 0-3
|
||||
LDM r0!,{r2-r9} // Load MPU regions 4-7
|
||||
STM r1,{r2-r9} // Store MPU regions 4-7
|
||||
#ifdef TXM_MODULE_MANAGER_16_MPU
|
||||
LDM r0!,{r2-r9} // Load MPU regions 8-11
|
||||
STM r1,{r2-r9} // Store MPU regions 8-11
|
||||
LDM r0,{r2-r9} // Load MPU regions 12-15
|
||||
STM r1,{r2-r9} // Store MPU regions 12-15
|
||||
#else
|
||||
LDM r0!,{r2-r9} // Load first four MPU regions
|
||||
STM r1,{r2-r9} // Store first four MPU regions
|
||||
LDM r0,{r2-r9} // Load second four MPU regions
|
||||
STM r1,{r2-r9} // Store second four MPU regions
|
||||
#endif
|
||||
_tx_enable_mpu:
|
||||
LDR r0, =0xE000ED94 // Build MPU control reg address
|
||||
MOV r1, #5 // Build enable value with background region enabled
|
||||
STR r1, [r0] // Enable MPU
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,119 +0,0 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2011, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \section Purpose
|
||||
*
|
||||
* Utility for BMP
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BMP_H
|
||||
#define BMP_H
|
||||
|
||||
/** BMP magic number ('BM'). */
|
||||
#define BMP_TYPE 0x4D42
|
||||
|
||||
/** headerSize must be set to 40 */
|
||||
#define BITMAPINFOHEADER 40
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported types
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#pragma pack( 1 )
|
||||
|
||||
/** BMP (Windows) Header Format */
|
||||
typedef struct _BMPHeader{
|
||||
/* signature, must be 4D42 hex */
|
||||
uint16_t type;
|
||||
/* size of BMP file in bytes (unreliable) */
|
||||
uint32_t fileSize;
|
||||
/* reserved, must be zero */
|
||||
uint16_t reserved1;
|
||||
/* reserved, must be zero */
|
||||
uint16_t reserved2;
|
||||
/* offset to start of image data in bytes */
|
||||
uint32_t offset;
|
||||
/* size of BITMAPINFOHEADER structure, must be 40 */
|
||||
uint32_t headerSize;
|
||||
/* image width in pixels */
|
||||
uint32_t width;
|
||||
/* image height in pixels */
|
||||
uint32_t height;
|
||||
/* number of planes in the image, must be 1 */
|
||||
uint16_t planes;
|
||||
/* number of bits per pixel (1, 4, 8, 16, 24, 32) */
|
||||
uint16_t bits;
|
||||
/* compression type (0=none, 1=RLE-8, 2=RLE-4) */
|
||||
uint32_t compression;
|
||||
/* size of image data in bytes (including padding) */
|
||||
uint32_t imageSize;
|
||||
/* horizontal resolution in pixels per meter (unreliable) */
|
||||
uint32_t xresolution;
|
||||
/* vertical resolution in pixels per meter (unreliable) */
|
||||
uint32_t yresolution;
|
||||
/* number of colors in image, or zero */
|
||||
uint32_t ncolours;
|
||||
/* number of important colors, or zero */
|
||||
uint32_t importantcolours;
|
||||
} BMPHeader;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
extern uint8_t BMP_IsValid(void *file);
|
||||
extern uint32_t BMP_GetFileSize(void *file);
|
||||
|
||||
extern uint8_t BMP_Decode(
|
||||
void *file,
|
||||
uint8_t *buffer,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint8_t bpp );
|
||||
|
||||
extern void WriteBMPheader(
|
||||
uint32_t *pAddressHeader,
|
||||
uint32_t bmpHSize,
|
||||
uint32_t bmpVSize,
|
||||
uint8_t nbByte_Pixels );
|
||||
|
||||
extern void BMP_displayHeader(uint32_t* pAddressHeader);
|
||||
extern void RGB565toBGR555(
|
||||
uint8_t *fileSource,
|
||||
uint8_t *fileDestination,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint8_t bpp );
|
||||
|
||||
#endif //#ifndef BMP_H
|
||||
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Interface for the low-level initialization function.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BOARD_LOWLEVEL_H
|
||||
#define BOARD_LOWLEVEL_H
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern void LowLevelInit( void );
|
||||
extern void _SetupMemoryRegion( void );
|
||||
|
||||
#endif /* BOARD_LOWLEVEL_H */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user