Release 6.1.7

This commit is contained in:
Bo Chen
2021-06-02 06:45:05 +00:00
parent d759e6bb9e
commit f5056f4923
1269 changed files with 57325 additions and 55178 deletions

View File

@@ -26,11 +26,11 @@
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* tx_port.h Cortex-M4/AC5 */
/* 6.1.6 */
/* 6.1.7 */
/* */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
@@ -43,14 +43,14 @@
/* own special types that can be mapped to actual data types by this */
/* file to guarantee consistency in the interface and functionality. */
/* */
/* This file replaces the previous Cortex-M3/M4/M7 files. It unifies */
/* the ARMv7-M architecture and compilers into one common file. */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
/* 04-02-2021 Bhupendra Naphade Modified comment(s),updated */
/* macro definition, */
/* resulting in version 6.1.6 */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
@@ -62,7 +62,7 @@
#ifdef TX_INCLUDE_USER_DEFINE_FILE
/* Yes, include the user defines in tx_user.h. The defines in this file may
/* Yes, include the user defines in tx_user.h. The defines in this file may
alternately be defined on the command line. */
#include "tx_user.h"
@@ -74,6 +74,28 @@
#include <stdlib.h>
#include <string.h>
#ifdef __ICCARM__
#include <intrinsics.h> /* IAR Intrinsics */
#define __asm__ __asm /* Define to make all inline asm look similar */
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#include <yvals.h>
#endif
#endif /* __ICCARM__ */
#ifdef __ghs__
#include <arm_ghs.h>
#include "tx_ghs.h"
#endif /* __ghs__ */
#if !defined(__GNUC__) && !defined(__CC_ARM)
#define __get_control_value __get_CONTROL
#define __set_control_value __set_CONTROL
#endif
#ifndef __GNUC__
#define __get_ipsr_value __get_IPSR
#endif
/* Define ThreadX basic types for this port. */
@@ -84,9 +106,10 @@ typedef int INT;
typedef unsigned int UINT;
typedef long LONG;
typedef unsigned long ULONG;
typedef unsigned long long ULONG64;
typedef short SHORT;
typedef unsigned short USHORT;
#define ULONG64_DEFINED
/* Define the priority levels for ThreadX. Legal values range
from 32 to 1024 and MUST be evenly divisible by 32. */
@@ -111,19 +134,19 @@ typedef unsigned short USHORT;
#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
/* Define various constants for the ThreadX Cortex-M3 port. */
/* Define various constants for the ThreadX Cortex-M port. */
#define TX_INT_DISABLE 1 /* Disable interrupts */
#define TX_INT_ENABLE 0 /* Enable interrupts */
/* 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
/* 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
source constants would be:
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
@@ -133,7 +156,7 @@ typedef unsigned short USHORT;
#ifndef TX_MISRA_ENABLE
#ifndef TX_TRACE_TIME_SOURCE
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
#endif
#else
ULONG _tx_misra_time_stamp_get(VOID);
@@ -144,6 +167,20 @@ ULONG _tx_misra_time_stamp_get(VOID);
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
#endif
#ifdef __ghs__
/* Define constants for Green Hills EventAnalyzer. */
/* Define the number of ticks per second. This informs the EventAnalyzer what the timestamps
represent. By default, this is set to 1,000,000 i.e., one tick every microsecond. */
#define TX_EL_TICKS_PER_SECOND 1000000
/* Define the method of how to get the upper and lower 32-bits of the time stamp. By default, simply
simulate the time-stamp source with a counter. */
#define read_tbu() _tx_el_time_base_upper
#define read_tbl() ++_tx_el_time_base_lower
#endif /* __ghs__ */
/* Define the port specific options for the _tx_build_options variable. This variable indicates
how the ThreadX library was built. */
@@ -162,7 +199,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
@@ -176,13 +213,24 @@ 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
#define TX_THREAD_EXTENSION_1
#define TX_THREAD_EXTENSION_2
#define TX_THREAD_EXTENSION_3
#define TX_THREAD_EXTENSION_0
#define TX_THREAD_EXTENSION_1
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
#elif defined(__ghs__)
#define TX_THREAD_EXTENSION_2 VOID * tx_thread_eh_globals; \
int Errno; /* errno. */ \
char * strtok_saved_pos; /* strtok() position. */
#else
#define TX_THREAD_EXTENSION_2
#endif
#define TX_THREAD_EXTENSION_3
/* Define the port extensions of the remaining ThreadX objects. */
@@ -196,11 +244,11 @@ ULONG _tx_misra_time_stamp_get(VOID);
#define TX_TIMER_EXTENSION
/* 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
#define TX_THREAD_USER_EXTENSION
#define TX_THREAD_USER_EXTENSION
#endif
@@ -208,18 +256,28 @@ ULONG _tx_misra_time_stamp_get(VOID);
tx_thread_shell_entry, and tx_thread_terminate. */
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
#ifndef TX_MISRA_ENABLE
register unsigned int _ipsr __asm("ipsr");
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#if (__VER__ < 8000000)
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
#else
void *_tx_iar_create_per_thread_tls_area(void);
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
void __iar_Initlocks(void);
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
#endif
#else
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
#endif
#ifdef __TARGET_FPU_VFP
#if defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__TARGET_FPU_VFP) || defined(__VFP__)
#ifdef TX_MISRA_ENABLE
@@ -228,35 +286,71 @@ void _tx_misra_control_set(ULONG value);
ULONG _tx_misra_fpccr_get(void);
void _tx_misra_vfp_touch(void);
#else
#else /* TX_MISRA_ENABLE not defined */
#ifdef TX_SOURCE_CODE
/* Define some helper functions (these are intrinsics in some compilers). */
#ifdef __GNUC__ /* GCC and ARM Compiler 6 */
register ULONG _control __asm("control");
__attribute__( ( always_inline ) ) static inline ULONG __get_control_value(void)
{
ULONG control_value;
__asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) );
return(control_value);
}
__attribute__( ( always_inline ) ) static inline void __set_control_value(ULONG control_value)
{
__asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" );
}
#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
#elif defined(__CC_ARM) /* ARM Compiler 5 */
__attribute__( ( always_inline ) ) ULONG __get_control_value(void)
{
ULONG control_value;
__asm volatile ("MRS control_value,CONTROL");
return(control_value);
}
__attribute__( ( always_inline ) ) void __set_control_value(ULONG control_value)
{
__asm__ volatile ("MSR CONTROL,control_value");
}
/* Can't access VFP registers with inline asm, so define this in tx_thread_schedule. */
void _tx_vfp_access(void);
#define TX_VFP_TOUCH() _tx_vfp_access();
#elif defined(__ICCARM__) /* IAR */
#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
#endif /* Helper functions for different compilers */
#endif /* TX_MISRA_ENABLE */
#endif
#endif
/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA
in order to ensure no lazy stacking will occur. */
#ifndef TX_MISRA_ENABLE
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = _control; \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_control = _tx_vfp_state; \
}
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
}
#else
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
}
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
}
#endif
/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR.
@@ -266,78 +360,76 @@ register ULONG _control __asm("control");
#ifndef TX_MISRA_ENABLE
void _tx_vfp_access(void);
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _control; \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_control = _tx_vfp_state; \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = *((ULONG *) 0xE000EF34); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _control; \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
_tx_vfp_access(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = _control; \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_control = _tx_vfp_state; \
} \
} \
} \
}
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = *((ULONG *) 0xE000EF34); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
TX_VFP_TOUCH(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
} \
} \
} \
}
#else
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = _tx_misra_fpccr_get(); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
_tx_misra_vfp_touch(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
} \
} \
}
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = _tx_misra_fpccr_get(); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
_tx_misra_vfp_touch(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
} \
} \
}
#endif
#else
#else /* No VFP in use */
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
#endif
#endif /* defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) */
/* Define the ThreadX object creation extensions for the remaining objects. */
@@ -362,16 +454,38 @@ void _tx_vfp_access(void);
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
/* Define the get system state macro. */
/* Define the get system state macro. */
#ifndef TX_THREAD_GET_SYSTEM_STATE
#ifndef TX_MISRA_ENABLE
#ifdef __CC_ARM /* ARM Compiler 5 */
register unsigned int _ipsr __asm("ipsr");
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _ipsr)
#else
#elif defined(__GNUC__) /* GCC and ARM Compiler 6 */
__attribute__( ( always_inline ) ) static inline unsigned int __get_ipsr_value(void)
{
unsigned int ipsr_value;
__asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) );
return(ipsr_value);
}
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_ipsr_value())
#elif defined(__ICCARM__) /* IAR */
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_IPSR())
#endif /* TX_THREAD_GET_SYSTEM_STATE for different compilers */
#else /* TX_MISRA_ENABLE is defined, use MISRA function. */
ULONG _tx_misra_ipsr_get(VOID);
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
#endif
#endif
#endif /* TX_MISRA_ENABLE */
#endif /* TX_THREAD_GET_SYSTEM_STATE */
/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
@@ -380,35 +494,189 @@ ULONG _tx_misra_ipsr_get(VOID);
zero after initialization for Cortex-M ports. */
#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
#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
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __clz(__rbit((m)));
/* Define the TX_LOWEST_SET_BIT_CALCULATE macro for each compiler. */
#ifdef __ICCARM__ /* IAR Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __CLZ(__RBIT((m)));
#elif defined(__CC_ARM) /* AC5 Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __clz(__rbit((m)));
#elif defined(__GNUC__) /* GCC and AC6 Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \
__asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) );
#endif
/* Define ThreadX interrupt lockout and restore macros for protection on
access of critical kernel information. The restore interrupt macro must
restore the interrupt posture of the running thread prior to the value
present prior to the disable macro. In most cases, the save area macro
is used to define a local function save area for the disable and restore
macros. */
#ifdef TX_DISABLE_INLINE
/* Define the interrupt disable/restore macros for each compiler. */
#if defined(__GNUC__) || defined(__ICCARM__)
/*** GCC/AC6 and IAR ***/
__attribute__( ( always_inline ) ) static inline unsigned int __get_interrupt_posture(void)
{
unsigned int posture;
#ifdef TX_PORT_USE_BASEPRI
__asm__ volatile ("MRS %0, BASEPRI ": "=r" (posture));
#else
__asm__ volatile ("MRS %0, PRIMASK ": "=r" (posture));
#endif
return(posture);
}
#ifdef TX_PORT_USE_BASEPRI
__attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value)
{
__asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value));
}
#else
__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
{
__asm__ volatile ("CPSIE i": : : "memory");
}
#endif
__attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture)
{
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(int_posture);
//__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory");
#else
__asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory");
#endif
}
__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
{
unsigned int int_posture;
int_posture = __get_interrupt_posture();
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(TX_PORT_BASEPRI);
#else
__asm__ volatile ("CPSID i" : : : "memory");
#endif
return(int_posture);
}
__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
{
unsigned int interrupt_save;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (__get_ipsr_value() == 0)
{
interrupt_save = __get_interrupt_posture();
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(0);
#else
__enable_interrupts();
#endif
__restore_interrupt(interrupt_save);
}
}
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
#define TX_DISABLE interrupt_save = __disable_interrupts();
#define TX_RESTORE __restore_interrupt(interrupt_save);
/*** End GCC/AC6 and IAR ***/
#elif defined(__CC_ARM)
/*** AC5 ***/
static __inline unsigned int __get_interrupt_posture(void)
{
unsigned int posture;
#ifdef TX_PORT_USE_BASEPRI
__asm__ volatile ("MRS #posture, BASEPRI");
#else
__asm__ volatile ("MRS #posture, PRIMASK");
#endif
return(posture);
}
#ifdef TX_PORT_USE_BASEPRI
static __inline void __set_basepri_value(unsigned int basepri_value)
{
__asm__ volatile ("MSR BASEPRI, #basepri_value");
}
#endif
static __inline unsigned int __disable_interrupts(void)
{
unsigned int int_posture;
int_posture = __get_interrupt_posture();
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(TX_PORT_BASEPRI);
#else
__asm__ volatile ("CPSID i");
#endif
return(int_posture);
}
static __inline void __restore_interrupt(unsigned int int_posture)
{
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(int_posture);
#else
__asm__ volatile ("MSR PRIMASK, #int_posture");
#endif
}
static void _tx_thread_system_return_inline(void)
{
unsigned int interrupt_save;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (_ipsr == 0)
{
#ifdef TX_PORT_USE_BASEPRI
interrupt_save = __get_interrupt_posture();
__set_basepri_value(0);
__set_basepri_value(interrupt_save);
#else
interrupt_save = __disable_irq();
__enable_irq();
if (interrupt_save != 0)
__disable_irq();
#endif
}
}
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
#define TX_DISABLE interrupt_save = __disable_interrupts();
#define TX_RESTORE __restore_interrupt(interrupt_save);
/*** End AC5 ***/
#endif /* Interrupt disable/restore macros for each compiler. */
/* Redefine _tx_thread_system_return for improved performance. */
#define _tx_thread_system_return _tx_thread_system_return_inline
#else /* TX_DISABLE_INLINE is defined */
UINT _tx_thread_interrupt_disable(VOID);
VOID _tx_thread_interrupt_restore(UINT previous_posture);
@@ -416,37 +684,11 @@ VOID _tx_thread_interrupt_restore(UIN
#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
#else
#define TX_INTERRUPT_SAVE_AREA UINT was_masked;
#define TX_DISABLE was_masked = __disable_irq();
#define TX_RESTORE if (was_masked == 0) __enable_irq();
#define _tx_thread_system_return _tx_thread_system_return_inline
#endif /* TX_DISABLE_INLINE */
static void _tx_thread_system_return_inline(void)
{
unsigned int was_masked;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (_ipsr == 0)
{
was_masked = __disable_irq();
__enable_irq();
if (was_masked != 0)
__disable_irq();
}
}
#endif
/* Define FPU extension for the Cortex-M4. Each is assumed to be called in the context of the executing
/* Define FPU extension for the Cortex-M. 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);
@@ -456,8 +698,8 @@ void tx_thread_fpu_disable(void);
/* 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-M4/AC5 Version 6.1.6 *";
CHAR _tx_version_id[] =
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M4/AC5 Version 6.1.7 *";
#else
#ifdef TX_MISRA_ENABLE
extern CHAR _tx_version_id[100];
@@ -468,7 +710,3 @@ extern CHAR _tx_version_id[];
#endif

View File

@@ -1,15 +1,14 @@
Microsoft's Azure RTOS ThreadX for Cortex-M4
Using ARM Compiler 5 (AC5)
Microsoft's Azure RTOS ThreadX for ARMv7-M
(Cortex-M3, Cortex-M4, Cortex-M7)
Using ARM Compiler 5 (AC5)
1. Building the ThreadX run-time Library
First make sure you are in the "example_build" directory. Also, make sure that
Navigate to the "example_build" directory. Ensure that
you have setup your path and other environment variables necessary for the AC5
development environment. At this point you may run the build_threadx.bat batch
file. This will build the ThreadX run-time environment in the "example_build"
directory.
compiler. At this point you may run the build_threadx.bat batch file. This will
build the ThreadX run-time environment in the "example_build" directory.
You should observe assembly and compilation of a series of ThreadX source
files. At the end of the batch file, they are all combined into the
@@ -19,20 +18,21 @@ application in order to use ThreadX.
2. Demonstration System
The ThreadX demonstration is designed to execute under the ARM
Windows-based simulator.
The ThreadX demonstration is designed to execute under the ARM DS Cortex-M
simulator.
Building the demonstration is easy; simply execute the build_threadx_sample.bat
batch file while inside the "example_build" directory.
batch file while inside the "example_build" directory.
You should observe the compilation of sample_threadx.c (which is the demonstration
application) and linking with tx.a. The resulting file sample_threadx.axf
is a binary file that can be downloaded and executed on the ARM simulator.
is a binary file that can be downloaded and executed on the ARM DS Cortex-M
simulator.
3. System Initialization
The entry point in ThreadX for the Cortex-M4 using AC5 tools is at label
The entry point in ThreadX for the Cortex-M using AC5 tools is at label
__main. This is defined within the AC5 compiler's startup code. In
addition, this is where all static and global pre-set C variable
initialization processing takes place.
@@ -50,7 +50,7 @@ parameter to your application definition function, tx_application_define.
The following defines the saved context stack frames for context switches
that occur as a result of interrupt handling or from thread-level API calls.
All suspended threads have the same stack frame in the Cortex-M4 version of
All suspended threads have the same stack frame in the Cortex-M version of
ThreadX. The top of the suspended thread's stack is pointed to by
tx_thread_stack_ptr in the associated thread control block TX_THREAD.
@@ -58,7 +58,7 @@ Non-FPU Stack Frame:
Stack Offset Stack Contents
0x00 LR Interrupted LR (LR at time of PENDSV)
0x00 lr Interrupted lr (lr at time of PENDSV)
0x04 r4 Software stacked GP registers
0x08 r5
0x0C r6
@@ -80,7 +80,7 @@ FPU Stack Frame (only interrupted thread with FPU enabled):
Stack Offset Stack Contents
0x00 LR Interrupted LR (LR at time of PENDSV)
0x00 lr Interrupted lr (lr at time of PENDSV)
0x04 s16 Software stacked FPU registers
0x08 s17
0x0C s18
@@ -137,8 +137,8 @@ FPU Stack Frame (only interrupted thread with FPU enabled):
The distribution version of ThreadX is built without any compiler
optimizations. This makes it easy to debug because you can trace or set
breakpoints inside of ThreadX itself. Of course, this costs some
performance. To make it run faster, you can change the ThreadX_Library.Uv2
project to debugging and enable all compiler optimizations.
performance. To make it run faster, you can change the ThreadX library
project to enable various compiler optimizations.
In addition, you can eliminate the ThreadX basic API error checking by
compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING
@@ -147,14 +147,14 @@ defined.
6. Interrupt Handling
ThreadX provides complete and high-performance interrupt handling for Cortex-M4
ThreadX provides complete and high-performance interrupt handling for Cortex-M
targets. There are a certain set of requirements that are defined in the
following sub-sections:
6.1 Vector Area
The Cortex-M4 vectors start at the label __tx_vectors. The application may modify
The Cortex-M vectors start at the label __tx_vectors. The application may modify
the vector area according to its needs.
@@ -187,29 +187,21 @@ your_assembly_isr
7. FPU Support
ThreadX for Cortex-M4 supports automatic ("lazy") VFP support, which means that applications threads
ThreadX for Cortex-M supports automatic ("lazy") VFP support, which means that applications threads
can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread
context - no additional setup by the application.
8. Revision History
For generic code revision information, please refer to the readme_threadx_generic.txt
file, which is included in your distribution. The following details the revision
information associated with this specific port of ThreadX:
04-02-2021 Release 6.1.6 changes:
tx_port.h Updated macro definition
tx_thread_schedule.s Fix compilation error
03-02-2021 The following files were changed/added for version 6.1.5:
tx_thread_schedule.s Added low power feature
09-30-2020 Initial ThreadX 6.1 version for Cortex-M4 using AC5 tools.
06-02-2021 Initial ThreadX version 6.1.7 for Cortex-M using AC5 tools.
Copyright(c) 1996-2020 Microsoft Corporation
Copyright(c) 1996-2021 Microsoft Corporation
https://azure.com/rtos

View File

@@ -1,91 +1,83 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
IMPORT _tx_execution_isr_exit
ENDIF
;
;
#endif
AREA ||.text||, CODE, READONLY
PRESERVE8
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_context_restore Cortex-M4/AC5 */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function is only needed for legacy applications and it should */
;/* not be called in any new development on a Cortex-M. */
;/* This function restores the interrupt context if it is processing a */
;/* nested interrupt. If not, it returns to the interrupt thread if no */
;/* preemption is necessary. Otherwise, if preemption is necessary or */
;/* if no thread was running, the function returns to the scheduler. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* _tx_thread_schedule Thread scheduling routine */
;/* */
;/* CALLED BY */
;/* */
;/* ISRs Interrupt Service Routines */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;VOID _tx_thread_context_restore(VOID)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_context_restore Cortex-M4/AC5 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is only needed for legacy applications and it should */
/* not be called in any new development on a Cortex-M. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* [_tx_execution_isr_exit] Execution profiling ISR exit */
/* */
/* CALLED BY */
/* */
/* ISRs Interrupt Service Routines */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_context_restore(VOID)
// {
EXPORT _tx_thread_context_restore
_tx_thread_context_restore
IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
;
; /* Call the ISR exit function to indicate an ISR is complete. */
;
PUSH {r0,lr} ; Save ISR lr
BL _tx_execution_isr_exit ; Call the ISR exit function
POP {r0,lr} ; Restore ISR lr
ENDIF
;
POP {lr}
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the ISR exit function to indicate an ISR is complete. */
PUSH {r0, lr} // Save return address
BL _tx_execution_isr_exit // Call the ISR exit function
POP {r0, lr} // Recover return address
#endif
BX lr
;}
// }
ALIGN
LTORG
END

View File

@@ -1,91 +1,85 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
IMPORT _tx_execution_isr_enter
ENDIF
;
;
#endif
AREA ||.text||, CODE, READONLY
PRESERVE8
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_context_save Cortex-M4/AC5 */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function is only needed for legacy applications and it should */
;/* not be called in any new development on a Cortex-M. */
;/* This function saves the context of an executing thread in the */
;/* beginning of interrupt processing. The function also ensures that */
;/* the system stack is used upon return to the calling ISR. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* ISRs */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;VOID _tx_thread_context_save(VOID)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_context_save Cortex-M4/AC5 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is only needed for legacy applications and it should */
/* not be called in any new development on a Cortex-M. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* ISRs */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_context_save(VOID)
// {
EXPORT _tx_thread_context_save
_tx_thread_context_save
IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
;
; /* Call the ISR enter function to indicate an ISR is executing. */
;
PUSH {r0, lr} ; Save ISR lr
BL _tx_execution_isr_enter ; Call the ISR enter function
POP {r0, lr} ; Recover ISR lr
ENDIF
;
; /* Return to interrupt processing. */
;
BX lr ; Return to interrupt processing caller
;}
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the ISR enter function to indicate an ISR is starting. */
PUSH {r0, lr} // Save return address
BL _tx_execution_isr_enter // Call the ISR enter function
POP {r0, lr} // Recover return address
#endif
/* Context is already saved - just return. */
BX lr
// }
ALIGN
LTORG
END

View File

@@ -1,76 +1,77 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
AREA ||.text||, CODE, READONLY
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_interrupt_control Cortex-M4/AC5 */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function is responsible for changing the interrupt lockout */
;/* posture of the system. */
;/* */
;/* INPUT */
;/* */
;/* new_posture New interrupt lockout posture */
;/* */
;/* OUTPUT */
;/* */
;/* old_posture Old interrupt lockout posture */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* Application Code */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;UINT _tx_thread_interrupt_control(UINT new_posture)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_control Cortex-M4/AC5 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for changing the interrupt lockout */
/* posture of the system. */
/* */
/* INPUT */
/* */
/* new_posture New interrupt lockout posture */
/* */
/* OUTPUT */
/* */
/* old_posture Old interrupt lockout posture */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// UINT _tx_thread_interrupt_control(UINT new_posture)
// {
EXPORT _tx_thread_interrupt_control
_tx_thread_interrupt_control
;
; /* Pickup current interrupt lockout posture. */
;
MRS r1, PRIMASK
MSR PRIMASK, r0
MOV r0, r1
BX lr
;
;}
#ifdef TX_PORT_USE_BASEPRI
MRS r1, BASEPRI // Pickup current interrupt posture
MSR BASEPRI, r0 // Apply the new interrupt posture
MOV r0, r1 // Transfer old to return register
#else
MRS r1, PRIMASK // Pickup current interrupt lockout
MSR PRIMASK, r0 // Apply the new interrupt lockout
MOV r0, r1 // Transfer old to return register
#endif
BX lr // Return to caller
// }
END

View File

@@ -1,75 +1,77 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
AREA ||.text||, CODE, READONLY
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_interrupt_disable Cortex-M4/AC5 */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation. */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function is responsible for disabling interrupts and returning */
;/* the previous interrupt lockout posture. */
;/* */
;/* INPUT */
;/* */
;/* old_posture Old interrupt lockout posture */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* Application Code */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;UINT _tx_thread_interrupt_disable(UINT new_posture)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_disable Cortex-M4/AC5 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for disabling interrupts and returning */
/* the previous interrupt lockout posture. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* old_posture Old interrupt lockout posture */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// UINT _tx_thread_interrupt_disable(VOID)
// {
EXPORT _tx_thread_interrupt_disable
_tx_thread_interrupt_disable
;
; /* Return current interrupt lockout posture. */
;
/* Return current interrupt lockout posture. */
#ifdef TX_PORT_USE_BASEPRI
MRS r0, BASEPRI
LDR r1, =TX_PORT_BASEPRI
MSR BASEPRI, r1
#else
MRS r0, PRIMASK
CPSID i
#endif
BX lr
;
;}
// }
END

View File

@@ -1,74 +1,75 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
AREA ||.text||, CODE, READONLY
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_interrupt_restore Cortex-M4/AC5 */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation. */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function is responsible for restoring the previous */
;/* interrupt lockout posture. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* previous_posture Previous interrupt posture */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* Application Code */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;VOID _tx_thread_interrupt_restore(UINT new_posture)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_restore Cortex-M4/AC5 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for restoring the previous */
/* interrupt lockout posture. */
/* */
/* INPUT */
/* */
/* previous_posture Previous interrupt posture */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_interrupt_restore(UINT previous_posture)
// {
EXPORT _tx_thread_interrupt_restore
_tx_thread_interrupt_restore
;
; /* Restore previous interrupt lockout posture. */
;
/* Restore previous interrupt lockout posture. */
#ifdef TX_PORT_USE_BASEPRI
MSR BASEPRI, r0
#else
MSR PRIMASK, r0
#endif
BX lr
;
;}
// }
END

View File

@@ -1,308 +1,285 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
IMPORT _tx_thread_current_ptr
IMPORT _tx_thread_execute_ptr
IMPORT _tx_timer_time_slice
IMPORT _tx_thread_system_stack_ptr
IMPORT _tx_thread_preempt_disable
IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
IMPORT _tx_execution_thread_enter
IMPORT _tx_execution_thread_exit
ENDIF
IF :DEF:TX_LOW_POWER
IMPORT tx_low_power_enter
IMPORT tx_low_power_exit
ENDIF
;
;
AREA ||.text||, CODE, READONLY
#endif
AREA ||.text||, CODE, READONLY
PRESERVE8
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_schedule Cortex-M4/AC5 */
;/* 6.1.5 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function waits for a thread control block pointer to appear in */
;/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
;/* in the variable, the corresponding thread is resumed. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* _tx_initialize_kernel_enter ThreadX entry function */
;/* _tx_thread_system_return Return to system from thread */
;/* _tx_thread_context_restore Restore thread's context */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* 03-02-2021 Scott Larson Modified comment(s), add */
;/* low power code, */
;/* resulting in version 6.1.5 */
;/* */
;/**************************************************************************/
;VOID _tx_thread_schedule(VOID)
;{
EXPORT _tx_thread_schedule
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_schedule Cortex-M4/AC5 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function waits for a thread control block pointer to appear in */
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
/* in the variable, the corresponding thread is resumed. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_initialize_kernel_enter ThreadX entry function */
/* _tx_thread_system_return Return to system from thread */
/* _tx_thread_context_restore Restore thread's context */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_schedule(VOID)
// {
EXPORT _tx_thread_schedule
_tx_thread_schedule
;
; /* This function should only ever be called on Cortex-M
; from the first schedule request. Subsequent scheduling occurs
; from the PendSV handling routines below. */
;
; /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
;
MOV r0, #0 ; Build value for TX_FALSE
LDR r2, =_tx_thread_preempt_disable ; Build address of preempt disable flag
STR r0, [r2, #0] ; Clear preempt disable flag
;
; /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
;
IF {TARGET_FPU_VFP} = {TRUE}
MRS r0, CONTROL ; Pickup current CONTROL register
BIC r0, r0, #4 ; Clear the FPCA bit
MSR CONTROL, r0 ; Setup new CONTROL register
ENDIF
;
; /* Enable the interrupts */
;
/* This function should only ever be called on Cortex-M
from the first schedule request. Subsequent scheduling occurs
from the PendSV handling routine below. */
/* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
MOV r0, #0 // Build value for TX_FALSE
LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
STR r0, [r2, #0] // Clear preempt disable flag
/* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
#ifdef __TARGET_FPU_VFP
MRS r0, CONTROL // Pickup current CONTROL register
BIC r0, r0, #4 // Clear the FPCA bit
MSR CONTROL, r0 // Setup new CONTROL register
#endif
/* Enable interrupts */
CPSIE i
;
; /* Enter the scheduler for the first time. */
;
MOV r0, #0x10000000 ; Load PENDSVSET bit
MOV r1, #0xE000E000 ; Load NVIC base
STR r0, [r1, #0xD04] ; Set PENDSVBIT in ICSR
DSB ; Complete all memory accesses
ISB ; Flush pipeline
;
; /* Wait here for the PendSV to take place. */
;
/* Enter the scheduler for the first time. */
MOV r0, #0x10000000 // Load PENDSVSET bit
MOV r1, #0xE000E000 // Load NVIC base
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
DSB // Complete all memory accesses
ISB // Flush pipeline
/* Wait here for the PendSV to take place. */
__tx_wait_here
B __tx_wait_here ; Wait for the PendSV to happen
;}
;
; /* Generic context switching PendSV handler. */
;
EXPORT __tx_PendSVHandler
EXPORT PendSV_Handler
B __tx_wait_here // Wait for the PendSV to happen
// }
/* Generic context switching PendSV handler. */
EXPORT __tx_PendSVHandler
EXPORT PendSV_Handler
__tx_PendSVHandler
PendSV_Handler
;
; /* Get current thread value and new thread pointer. */
;
/* Get current thread value and new thread pointer. */
__tx_ts_handler
IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
;
; /* Call the thread exit function to indicate the thread is no longer executing. */
;
CPSID i ; Disable interrupts
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
CPSIE i ; Enable interrupts
ENDIF
MOV32 r0, _tx_thread_current_ptr ; Build current thread pointer address
MOV32 r2, _tx_thread_execute_ptr ; Build execute thread pointer address
MOV r3, #0 ; Build NULL value
LDR r1, [r0] ; Pickup current thread pointer
;
; /* Determine if there is a current thread to finish preserving. */
;
CBZ r1, __tx_ts_new ; If NULL, skip preservation
;
; /* Recover PSP and preserve current thread context. */
;
STR r3, [r0] ; Set _tx_thread_current_ptr to NULL
MRS r12, PSP ; Pickup PSP pointer (thread's stack pointer)
STMDB r12!, {r4-r11} ; Save its remaining registers
IF {TARGET_FPU_VFP} = {TRUE}
TST LR, #0x10 ; Determine if the VFP extended frame is present
#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
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
CPSIE i // Enable interrupts
#endif
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
MOV r3, #0 // Build NULL value
LDR r1, [r0] // Pickup current thread pointer
/* Determine if there is a current thread to finish preserving. */
CBZ r1, __tx_ts_new // If NULL, skip preservation
/* Recover PSP and preserve current thread context. */
STR r3, [r0] // Set _tx_thread_current_ptr to NULL
MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
STMDB r12!, {r4-r11} // Save its remaining registers
#ifdef __TARGET_FPU_VFP
TST LR, #0x10 // Determine if the VFP extended frame is present
BNE _skip_vfp_save
VSTMDB r12!,{s16-s31} ; Yes, save additional VFP registers
VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
_skip_vfp_save
ENDIF
MOV32 r4, _tx_timer_time_slice ; Build address of time-slice variable
STMDB r12!, {LR} ; Save LR on the stack
;
; /* Determine if time-slice is active. If it isn't, skip time handling processing. */
;
LDR r5, [r4] ; Pickup current time-slice
STR r12, [r1, #8] ; Save the thread stack pointer
CBZ r5, __tx_ts_new ; If not active, skip processing
;
; /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
;
STR r5, [r1, #24] ; Save current time-slice
;
; /* Clear the global time-slice. */
;
STR r3, [r4] ; Clear time-slice
;
; /* Executing thread is now completely preserved!!! */
;
#endif
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
STMDB r12!, {LR} // Save LR on the stack
/* Determine if time-slice is active. If it isn't, skip time handling processing. */
LDR r5, [r4] // Pickup current time-slice
STR r12, [r1, #8] // Save the thread stack pointer
CBZ r5, __tx_ts_new // If not active, skip processing
/* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
STR r5, [r1, #24] // Save current time-slice
/* Clear the global time-slice. */
STR r3, [r4] // Clear time-slice
/* Executing thread is now completely preserved!!! */
__tx_ts_new
;
; /* Now we are looking for a new thread to execute! */
;
CPSID i ; Disable interrupts
LDR r1, [r2] ; Is there another thread ready to execute?
CBZ r1, __tx_ts_wait ; No, skip to the wait processing
;
; /* Yes, another thread is ready for else, make the current thread the new thread. */
;
STR r1, [r0] ; Setup the current thread pointer to the new thread
CPSIE i ; Enable interrupts
;
; /* Increment the thread run count. */
;
/* Now we are looking for a new thread to execute! */
CPSID i // Disable interrupts
LDR r1, [r2] // Is there another thread ready to execute?
CBZ r1, __tx_ts_wait // No, skip to the wait processing
/* Yes, another thread is ready for else, make the current thread the new thread. */
STR r1, [r0] // Setup the current thread pointer to the new thread
CPSIE i // Enable interrupts
/* Increment the thread run count. */
__tx_ts_restore
LDR r7, [r1, #4] ; Pickup the current thread run count
MOV32 r4, _tx_timer_time_slice ; Build address of time-slice variable
LDR r5, [r1, #24] ; Pickup thread's current time-slice
ADD r7, r7, #1 ; Increment the thread run count
STR r7, [r1, #4] ; Store the new run count
;
; /* Setup global time-slice with thread's current time-slice. */
;
STR r5, [r4] ; Setup global time-slice
LDR r7, [r1, #4] // Pickup the current thread run count
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
LDR r5, [r1, #24] // Pickup thread's current time-slice
ADD r7, r7, #1 // Increment the thread run count
STR r7, [r1, #4] // Store the new run count
IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
;
; /* Call the thread entry function to indicate the thread is executing. */
;
PUSH {r0, r1} ; Save r0/r1
BL _tx_execution_thread_enter ; Call the thread execution enter function
POP {r0, r1} ; Recover r3
ENDIF
;
; /* Restore the thread context and PSP. */
;
LDR r12, [r1, #8] ; Pickup thread's stack pointer
LDMIA r12!, {LR} ; Pickup LR
IF {TARGET_FPU_VFP} = {TRUE}
TST LR, #0x10 ; Determine if the VFP extended frame is present
BNE _skip_vfp_restore ; If not, skip VFP restore
VLDMIA r12!, {s16-s31} ; Yes, restore additional VFP registers
/* Setup global time-slice with thread's current time-slice. */
STR r5, [r4] // Setup global time-slice
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the thread entry function to indicate the thread is executing. */
PUSH {r0, r1} // Save r0 and r1
BL _tx_execution_thread_enter // Call the thread execution enter function
POP {r0, r1} // Recover r0 and r1
#endif
/* Restore the thread context and PSP. */
LDR r12, [r1, #8] // Pickup thread's stack pointer
LDMIA r12!, {LR} // Pickup LR
#ifdef __TARGET_FPU_VFP
TST LR, #0x10 // Determine if the VFP extended frame is present
BNE _skip_vfp_restore // If not, skip VFP restore
VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
_skip_vfp_restore
ENDIF
LDMIA r12!, {r4-r11} ; Recover thread's registers
MSR PSP, r12 ; Setup the thread's stack pointer
;
; /* Return to thread. */
;
BX lr ; Return to thread!
;
; /* The following is the idle wait processing... in this case, no threads are ready for execution and the
; system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
; are disabled to allow use of WFI for waiting for a thread to arrive. */
;
#endif
LDMIA r12!, {r4-r11} // Recover thread's registers
MSR PSP, r12 // Setup the thread's stack pointer
/* Return to thread. */
BX lr // Return to thread!
/* The following is the idle wait processing... in this case, no threads are ready for execution and the
system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
are disabled to allow use of WFI for waiting for a thread to arrive. */
__tx_ts_wait
CPSID i ; Disable interrupts
LDR r1, [r2] ; Pickup the next thread to execute pointer
STR r1, [r0] ; Store it in the current pointer
CBNZ r1, __tx_ts_ready ; If non-NULL, a new thread is ready!
CPSID i // Disable interrupts
LDR r1, [r2] // Pickup the next thread to execute pointer
STR r1, [r0] // Store it in the current pointer
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
IF :DEF:TX_LOW_POWER
PUSH {r0-r3}
BL tx_low_power_enter ; Possibly enter low power mode
POP {r0-r3}
ENDIF
#ifdef TX_LOW_POWER
BL tx_low_power_enter // Possibly enter low power mode
#endif
IF :DEF:TX_ENABLE_WFI
DSB ; Ensure no outstanding memory transactions
WFI ; Wait for interrupt
ISB ; Ensure pipeline is flushed
ENDIF
#ifdef TX_ENABLE_WFI
DSB // Ensure no outstanding memory transactions
WFI // Wait for interrupt
ISB // Ensure pipeline is flushed
#endif
IF :DEF:TX_LOW_POWER
PUSH {r0-r3}
BL tx_low_power_exit ; Exit low power mode
POP {r0-r3}
ENDIF
#ifdef TX_LOW_POWER
BL tx_low_power_exit // Exit low power mode
#endif
CPSIE i // Enable interrupts
B __tx_ts_wait // Loop to continue waiting
/* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
already in the handler! */
CPSIE i ; Enable interrupts
B __tx_ts_wait ; Loop to continue waiting
;
; /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
; already in the handler! */
;
__tx_ts_ready
MOV r7, #0x08000000 ; Build clear PendSV value
MOV r8, #0xE000E000 ; Build base NVIC address
STR r7, [r8, #0xD04] ; Clear any PendSV
;
; /* Re-enable interrupts and restore new thread. */
;
CPSIE i ; Enable interrupts
B __tx_ts_restore ; Restore the thread
MOV r7, #0x08000000 // Build clear PendSV value
MOV r8, #0xE000E000 // Build base NVIC address
STR r7, [r8, #0xD04] // Clear any PendSV
IF {TARGET_FPU_VFP} = {TRUE}
/* Re-enable interrupts and restore new thread. */
CPSIE i // Enable interrupts
B __tx_ts_restore // Restore the thread
// }
#ifdef __TARGET_FPU_VFP
EXPORT tx_thread_fpu_enable
tx_thread_fpu_enable
;
; /* Automatic VPF logic is supported, this function is present only for
; backward compatibility purposes and therefore simply returns. */
;
BX LR ; Return to caller
EXPORT tx_thread_fpu_disable
tx_thread_fpu_disable
;
; /* Automatic VPF logic is supported, this function is present only for
; backward compatibility purposes and therefore simply returns. */
;
BX LR ; Return to caller
/* Automatic VPF logic is supported, this function is present only for
backward compatibility purposes and therefore simply returns. */
BX LR // Return to caller
EXPORT _tx_vfp_access
_tx_vfp_access
VMOV.F32 s0, s0 ; Simply access the VFP
BX lr ; Return to caller
VMOV.F32 s0, s0 // Simply access the VFP
BX lr // Return to caller
ENDIF
#endif
ALIGN
LTORG

View File

@@ -1,133 +1,131 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
AREA ||.text||, CODE, READONLY
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_stack_build Cortex-M4/AC5 */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function builds a stack frame on the supplied thread's stack. */
;/* The stack frame results in a fake interrupt return to the supplied */
;/* function pointer. */
;/* */
;/* INPUT */
;/* */
;/* thread_ptr Pointer to thread control blk */
;/* function_ptr Pointer to return function */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* _tx_thread_create Create thread service */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_stack_build Cortex-M4/AC5 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function builds a stack frame on the supplied thread's stack. */
/* The stack frame results in a fake interrupt return to the supplied */
/* function pointer. */
/* */
/* INPUT */
/* */
/* thread_ptr Pointer to thread control blk */
/* function_ptr Pointer to return function */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_thread_create Create thread service */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
// {
EXPORT _tx_thread_stack_build
_tx_thread_stack_build
;
;
; /* Build a fake interrupt frame. The form of the fake interrupt stack
; on the Cortex-M4 should look like the following after it is built:
;
; Stack Top:
; LR Interrupted LR (LR at time of PENDSV)
; r4 Initial value for r4
; r5 Initial value for r5
; r6 Initial value for r6
; r7 Initial value for r7
; r8 Initial value for r8
; r9 Initial value for r9
; r10 Initial value for r10
; r11 Initial value for r11
; r0 Initial value for r0 (Hardware stack starts here!!)
; r1 Initial value for r1
; r2 Initial value for r2
; r3 Initial value for r3
; r12 Initial value for r12
; lr Initial value for lr
; pc Initial value for pc
; xPSR Initial value for xPSR
;
; Stack Bottom: (higher memory address) */
;
LDR r2, [r0, #16] ; Pickup end of stack area
BIC r2, r2, #0x7 ; Align frame for 8-byte alignment
SUB r2, r2, #68 ; Subtract frame size
LDR r3, =0xFFFFFFFD ; Build initial LR value
STR r3, [r2, #0] ; Save on the stack
;
; /* Actually build the stack frame. */
;
MOV r3, #0 ; Build initial register value
STR r3, [r2, #4] ; Store initial r4
STR r3, [r2, #8] ; Store initial r5
STR r3, [r2, #12] ; Store initial r6
STR r3, [r2, #16] ; Store initial r7
STR r3, [r2, #20] ; Store initial r8
STR r3, [r2, #24] ; Store initial r9
STR r3, [r2, #28] ; Store initial r10
STR r3, [r2, #32] ; Store initial r11
;
; /* Hardware stack follows. */
;
STR r3, [r2, #36] ; Store initial r0
STR r3, [r2, #40] ; Store initial r1
STR r3, [r2, #44] ; Store initial r2
STR r3, [r2, #48] ; Store initial r3
STR r3, [r2, #52] ; Store initial r12
MOV r3, #0xFFFFFFFF ; Poison EXC_RETURN value
STR r3, [r2, #56] ; Store initial lr
STR r1, [r2, #60] ; Store initial pc
MOV r3, #0x01000000 ; Only T-bit need be set
STR r3, [r2, #64] ; Store initial xPSR
;
; /* Setup stack pointer. */
; thread_ptr -> tx_thread_stack_ptr = r2;
;
STR r2, [r0, #8] ; Save stack pointer in thread's
; control block
BX lr ; Return to caller
;}
/* Build a fake interrupt frame. The form of the fake interrupt stack
on the Cortex-M should look like the following after it is built:
Stack Top:
LR Interrupted LR (LR at time of PENDSV)
r4 Initial value for r4
r5 Initial value for r5
r6 Initial value for r6
r7 Initial value for r7
r8 Initial value for r8
r9 Initial value for r9
r10 Initial value for r10
r11 Initial value for r11
r0 Initial value for r0 (Hardware stack starts here!!)
r1 Initial value for r1
r2 Initial value for r2
r3 Initial value for r3
r12 Initial value for r12
lr Initial value for lr
pc Initial value for pc
xPSR Initial value for xPSR
Stack Bottom: (higher memory address) */
LDR r2, [r0, #16] // Pickup end of stack area
BIC r2, r2, #0x7 // Align frame for 8-byte alignment
SUB r2, r2, #68 // Subtract frame size
LDR r3, =0xFFFFFFFD // Build initial LR value
STR r3, [r2, #0] // Save on the stack
/* Actually build the stack frame. */
MOV r3, #0 // Build initial register value
STR r3, [r2, #4] // Store initial r4
STR r3, [r2, #8] // Store initial r5
STR r3, [r2, #12] // Store initial r6
STR r3, [r2, #16] // Store initial r7
STR r3, [r2, #20] // Store initial r8
STR r3, [r2, #24] // Store initial r9
STR r3, [r2, #28] // Store initial r10
STR r3, [r2, #32] // Store initial r11
/* Hardware stack follows. */
STR r3, [r2, #36] // Store initial r0
STR r3, [r2, #40] // Store initial r1
STR r3, [r2, #44] // Store initial r2
STR r3, [r2, #48] // Store initial r3
STR r3, [r2, #52] // Store initial r12
MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
STR r3, [r2, #56] // Store initial lr
STR r1, [r2, #60] // Store initial pc
MOV r3, #0x01000000 // Only T-bit need be set
STR r3, [r2, #64] // Store initial xPSR
/* Setup stack pointer. */
// thread_ptr -> tx_thread_stack_ptr = r2;
STR r2, [r0, #8] // Save stack pointer in thread's
// control block
BX lr // Return to caller
// }
END

View File

@@ -1,85 +1,91 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
AREA ||.text||, CODE, READONLY
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_system_return Cortex-M4/AC5 */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function is target processor specific. It is used to transfer */
;/* control from a thread back to the ThreadX system. Only a */
;/* minimal context is saved since the compiler assumes temp registers */
;/* are going to get slicked by a function call anyway. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* _tx_thread_schedule Thread scheduling loop */
;/* */
;/* CALLED BY */
;/* */
;/* ThreadX components */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;VOID _tx_thread_system_return(VOID)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_system_return Cortex-M4/AC5 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is target processor specific. It is used to transfer */
/* control from a thread back to the ThreadX system. Only a */
/* minimal context is saved since the compiler assumes temp registers */
/* are going to get slicked by a function call anyway. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _tx_thread_schedule Thread scheduling loop */
/* */
/* CALLED BY */
/* */
/* ThreadX components */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_system_return(VOID)
// {
EXPORT _tx_thread_system_return
_tx_thread_system_return
;
; /* Return to real scheduler via PendSV. Note that this routine is often
; replaced with in-line assembly in tx_port.h to improved performance. */
;
MOV r0, #0x10000000 ; Load PENDSVSET bit
MOV r1, #0xE000E000 ; Load NVIC base
STR r0, [r1, #0xD04] ; Set PENDSVBIT in ICSR
MRS r0, IPSR ; Pickup IPSR
CMP r0, #0 ; Is it a thread returning?
BNE _isr_context ; If ISR, skip interrupt enable
MRS r1, PRIMASK ; Thread context returning, pickup PRIMASK
CPSIE i ; Enable interrupts
MSR PRIMASK, r1 ; Restore original interrupt posture
/* Return to real scheduler via PendSV. Note that this routine is often
replaced with in-line assembly in tx_port.h to improved performance. */
MOV r0, #0x10000000 // Load PENDSVSET bit
MOV r1, #0xE000E000 // Load NVIC base
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
MRS r0, IPSR // Pickup IPSR
CMP r0, #0 // Is it a thread returning?
BNE _isr_context // If ISR, skip interrupt enable
#ifdef TX_PORT_USE_BASEPRI
MRS r1, BASEPRI // Thread context returning, pickup BASEPRI
MOV r0, #0
MSR BASEPRI, r0 // Enable interrupts
MSR BASEPRI, r1 // Restore original interrupt posture
#else
MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
CPSIE i // Enable interrupts
MSR PRIMASK, r1 // Restore original interrupt posture
#endif
_isr_context
BX lr ; Return to caller
;}
BX lr // Return to caller
// }
END

View File

@@ -1,26 +1,25 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Timer */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Timer */
/** */
/**************************************************************************/
/**************************************************************************/
IMPORT _tx_timer_time_slice
IMPORT _tx_timer_system_clock
IMPORT _tx_timer_current_ptr
@@ -33,227 +32,223 @@
IMPORT _tx_thread_preempt_disable
IMPORT _tx_thread_current_ptr
IMPORT _tx_thread_execute_ptr
;
;
AREA ||.text||, CODE, READONLY
PRESERVE8
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_timer_interrupt Cortex-M4/AC5 */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function processes the hardware timer interrupt. This */
;/* processing includes incrementing the system clock and checking for */
;/* time slice and/or timer expiration. If either is found, the */
;/* interrupt context save/restore functions are called along with the */
;/* expiration functions. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* _tx_timer_expiration_process Timer expiration processing */
;/* _tx_thread_time_slice Time slice interrupted thread */
;/* */
;/* CALLED BY */
;/* */
;/* interrupt vector */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;VOID _tx_timer_interrupt(VOID)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_timer_interrupt Cortex-M4/AC5 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function processes the hardware timer interrupt. This */
/* processing includes incrementing the system clock and checking for */
/* time slice and/or timer expiration. If either is found, the */
/* expiration functions are called. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _tx_timer_expiration_process Timer expiration processing */
/* _tx_thread_time_slice Time slice interrupted thread */
/* */
/* CALLED BY */
/* */
/* interrupt vector */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_timer_interrupt(VOID)
// {
EXPORT _tx_timer_interrupt
_tx_timer_interrupt
;
; /* Upon entry to this routine, it is assumed that context save has already
; been called, and therefore the compiler scratch registers are available
; for use. */
;
; /* Increment the system clock. */
; _tx_timer_system_clock++;
;
MOV32 r1, _tx_timer_system_clock ; Pickup address of system clock
LDR r0, [r1, #0] ; Pickup system clock
ADD r0, r0, #1 ; Increment system clock
STR r0, [r1, #0] ; Store new system clock
;
; /* Test for time-slice expiration. */
; if (_tx_timer_time_slice)
; {
;
MOV32 r3, _tx_timer_time_slice ; Pickup address of time-slice
LDR r2, [r3, #0] ; Pickup time-slice
CBZ r2, __tx_timer_no_time_slice ; Is it non-active?
; Yes, skip time-slice processing
;
; /* Decrement the time_slice. */
; _tx_timer_time_slice--;
;
SUB r2, r2, #1 ; Decrement the time-slice
STR r2, [r3, #0] ; Store new time-slice value
;
; /* Check for expiration. */
; if (__tx_timer_time_slice == 0)
;
CBNZ r2, __tx_timer_no_time_slice ; Has it expired?
;
; /* Set the time-slice expired flag. */
; _tx_timer_expired_time_slice = TX_TRUE;
;
MOV32 r3, _tx_timer_expired_time_slice ; Pickup address of expired flag
MOV r0, #1 ; Build expired value
STR r0, [r3, #0] ; Set time-slice expiration flag
;
; }
;
__tx_timer_no_time_slice
;
; /* Test for timer expiration. */
; if (*_tx_timer_current_ptr)
; {
;
MOV32 r1, _tx_timer_current_ptr ; Pickup current timer pointer address
LDR r0, [r1, #0] ; Pickup current timer
LDR r2, [r0, #0] ; Pickup timer list entry
CBZ r2, __tx_timer_no_timer ; Is there anything in the list?
; No, just increment the timer
;
; /* Set expiration flag. */
; _tx_timer_expired = TX_TRUE;
;
MOV32 r3, _tx_timer_expired ; Pickup expiration flag address
MOV r2, #1 ; Build expired value
STR r2, [r3, #0] ; Set expired flag
B __tx_timer_done ; Finished timer processing
;
; }
; else
; {
__tx_timer_no_timer
;
; /* No timer expired, increment the timer pointer. */
; _tx_timer_current_ptr++;
;
ADD r0, r0, #4 ; Move to next timer
;
; /* Check for wrap-around. */
; if (_tx_timer_current_ptr == _tx_timer_list_end)
;
MOV32 r3, _tx_timer_list_end ; Pickup addr of timer list end
LDR r2, [r3, #0] ; Pickup list end
CMP r0, r2 ; Are we at list end?
BNE __tx_timer_skip_wrap ; No, skip wrap-around logic
;
; /* Wrap to beginning of list. */
; _tx_timer_current_ptr = _tx_timer_list_start;
;
MOV32 r3, _tx_timer_list_start ; Pickup addr of timer list start
LDR r0, [r3, #0] ; Set current pointer to list start
;
__tx_timer_skip_wrap
;
STR r0, [r1, #0] ; Store new current timer pointer
; }
;
__tx_timer_done
;
;
; /* See if anything has expired. */
; if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
; {
;
MOV32 r3, _tx_timer_expired_time_slice ; Pickup addr of expired flag
LDR r2, [r3, #0] ; Pickup time-slice expired flag
CBNZ r2, __tx_something_expired ; Did a time-slice expire?
; If non-zero, time-slice expired
MOV32 r1, _tx_timer_expired ; Pickup addr of other expired flag
LDR r0, [r1, #0] ; Pickup timer expired flag
CBZ r0, __tx_timer_nothing_expired ; Did a timer expire?
; No, nothing expired
;
__tx_something_expired
;
;
STMDB sp!, {r0, lr} ; Save the lr register on the stack
; and save r0 just to keep 8-byte alignment
;
; /* Did a timer expire? */
; if (_tx_timer_expired)
; {
;
MOV32 r1, _tx_timer_expired ; Pickup addr of expired flag
LDR r0, [r1, #0] ; Pickup timer expired flag
CBZ r0, __tx_timer_dont_activate ; Check for timer expiration
; If not set, skip timer activation
;
; /* Process timer expiration. */
; _tx_timer_expiration_process();
;
BL _tx_timer_expiration_process ; Call the timer expiration handling routine
;
; }
__tx_timer_dont_activate
;
; /* Did time slice expire? */
; if (_tx_timer_expired_time_slice)
; {
;
MOV32 r3, _tx_timer_expired_time_slice ; Pickup addr of time-slice expired
LDR r2, [r3, #0] ; Pickup the actual flag
CBZ r2, __tx_timer_not_ts_expiration ; See if the flag is set
; No, skip time-slice processing
;
; /* Time slice interrupted thread. */
; _tx_thread_time_slice();
BL _tx_thread_time_slice ; Call time-slice processing
MOV32 r0, _tx_thread_preempt_disable ; Build address of preempt disable flag
LDR r1, [r0] ; Is the preempt disable flag set?
CBNZ r1, __tx_timer_skip_time_slice ; Yes, skip the PendSV logic
MOV32 r0, _tx_thread_current_ptr ; Build current thread pointer address
LDR r1, [r0] ; Pickup the current thread pointer
MOV32 r2, _tx_thread_execute_ptr ; Build execute thread pointer address
LDR r3, [r2] ; Pickup the execute thread pointer
MOV32 r0, 0xE000ED04 ; Build address of control register
MOV32 r2, 0x10000000 ; Build value for PendSV bit
CMP r1, r3 ; Are they the same?
BEQ __tx_timer_skip_time_slice ; If the same, there was no time-slice performed
STR r2, [r0] ; Not the same, issue the PendSV for preemption
/* Upon entry to this routine, it is assumed that the compiler scratch registers are available
for use. */
/* Increment the system clock. */
// _tx_timer_system_clock++;
LDR r1, =_tx_timer_system_clock // Pickup address of system clock
LDR r0, [r1, #0] // Pickup system clock
ADD r0, r0, #1 // Increment system clock
STR r0, [r1, #0] // Store new system clock
/* Test for time-slice expiration. */
// if (_tx_timer_time_slice)
// {
LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
LDR r2, [r3, #0] // Pickup time-slice
CBZ r2, __tx_timer_no_time_slice // Is it non-active?
// Yes, skip time-slice processing
/* Decrement the time_slice. */
// _tx_timer_time_slice--;
SUB r2, r2, #1 // Decrement the time-slice
STR r2, [r3, #0] // Store new time-slice value
/* Check for expiration. */
// if (__tx_timer_time_slice == 0)
CBNZ r2, __tx_timer_no_time_slice // Has it expired?
// No, skip expiration processing
/* Set the time-slice expired flag. */
// _tx_timer_expired_time_slice = TX_TRUE;
LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
MOV r0, #1 // Build expired value
STR r0, [r3, #0] // Set time-slice expiration flag
// }
__tx_timer_no_time_slice
/* Test for timer expiration. */
// if (*_tx_timer_current_ptr)
// {
LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
LDR r0, [r1, #0] // Pickup current timer
LDR r2, [r0, #0] // Pickup timer list entry
CBZ r2, __tx_timer_no_timer // Is there anything in the list?
// No, just increment the timer
/* Set expiration flag. */
// _tx_timer_expired = TX_TRUE;
LDR r3, =_tx_timer_expired // Pickup expiration flag address
MOV r2, #1 // Build expired value
STR r2, [r3, #0] // Set expired flag
B __tx_timer_done // Finished timer processing
// }
// else
// {
__tx_timer_no_timer
/* No timer expired, increment the timer pointer. */
// _tx_timer_current_ptr++;
ADD r0, r0, #4 // Move to next timer
/* Check for wrap-around. */
// if (_tx_timer_current_ptr == _tx_timer_list_end)
LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
LDR r2, [r3, #0] // Pickup list end
CMP r0, r2 // Are we at list end?
BNE __tx_timer_skip_wrap // No, skip wrap-around logic
/* Wrap to beginning of list. */
// _tx_timer_current_ptr = _tx_timer_list_start;
LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
LDR r0, [r3, #0] // Set current pointer to list start
__tx_timer_skip_wrap
STR r0, [r1, #0] // Store new current timer pointer
// }
__tx_timer_done
/* See if anything has expired. */
// if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
// {
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
LDR r2, [r3, #0] // Pickup time-slice expired flag
CBNZ r2, __tx_something_expired // Did a time-slice expire?
// If non-zero, time-slice expired
LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
LDR r0, [r1, #0] // Pickup timer expired flag
CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
// No, nothing expired
__tx_something_expired
STMDB sp!, {r0, lr} // Save the lr register on the stack
// and save r0 just to keep 8-byte alignment
/* Did a timer expire? */
// if (_tx_timer_expired)
// {
LDR r1, =_tx_timer_expired // Pickup addr of expired flag
LDR r0, [r1, #0] // Pickup timer expired flag
CBZ r0, __tx_timer_dont_activate // Check for timer expiration
// If not set, skip timer activation
/* Process timer expiration. */
// _tx_timer_expiration_process();
BL _tx_timer_expiration_process // Call the timer expiration handling routine
// }
__tx_timer_dont_activate
/* Did time slice expire? */
// if (_tx_timer_expired_time_slice)
// {
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
LDR r2, [r3, #0] // Pickup the actual flag
CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
// No, skip time-slice processing
/* Time slice interrupted thread. */
// _tx_thread_time_slice();
BL _tx_thread_time_slice // Call time-slice processing
LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
LDR r1, [r0] // Is the preempt disable flag set?
CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
LDR r1, [r0] // Pickup the current thread pointer
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
LDR r3, [r2] // Pickup the execute thread pointer
LDR r0, =0xE000ED04 // Build address of control register
LDR r2, =0x10000000 // Build value for PendSV bit
CMP r1, r3 // Are they the same?
BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
STR r2, [r0] // Not the same, issue the PendSV for preemption
__tx_timer_skip_time_slice
;
; }
;
// }
__tx_timer_not_ts_expiration
;
LDMIA sp!, {r0, lr} ; Recover lr register (r0 is just there for
;
; }
;
LDMIA sp!, {r0, lr} // Recover lr register (r0 is just there for
// the 8-byte stack alignment
// }
__tx_timer_nothing_expired
DSB ; Complete all memory access
BX lr ; Return to caller
;
;}
DSB // Complete all memory access
BX lr // Return to caller
// }
ALIGN
LTORG
END

View File

@@ -26,11 +26,11 @@
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* tx_port.h Cortex-M4/AC6 */
/* 6.1.6 */
/* 6.1.7 */
/* */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
@@ -43,14 +43,14 @@
/* own special types that can be mapped to actual data types by this */
/* file to guarantee consistency in the interface and functionality. */
/* */
/* This file replaces the previous Cortex-M3/M4/M7 files. It unifies */
/* the ARMv7-M architecture and compilers into one common file. */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
/* 04-02-2021 Bhupendra Naphade Modified comment(s),updated */
/* macro definition, */
/* resulting in version 6.1.6 */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
@@ -62,7 +62,7 @@
#ifdef TX_INCLUDE_USER_DEFINE_FILE
/* Yes, include the user defines in tx_user.h. The defines in this file may
/* Yes, include the user defines in tx_user.h. The defines in this file may
alternately be defined on the command line. */
#include "tx_user.h"
@@ -74,6 +74,28 @@
#include <stdlib.h>
#include <string.h>
#ifdef __ICCARM__
#include <intrinsics.h> /* IAR Intrinsics */
#define __asm__ __asm /* Define to make all inline asm look similar */
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#include <yvals.h>
#endif
#endif /* __ICCARM__ */
#ifdef __ghs__
#include <arm_ghs.h>
#include "tx_ghs.h"
#endif /* __ghs__ */
#if !defined(__GNUC__) && !defined(__CC_ARM)
#define __get_control_value __get_CONTROL
#define __set_control_value __set_CONTROL
#endif
#ifndef __GNUC__
#define __get_ipsr_value __get_IPSR
#endif
/* Define ThreadX basic types for this port. */
@@ -84,9 +106,10 @@ typedef int INT;
typedef unsigned int UINT;
typedef long LONG;
typedef unsigned long ULONG;
typedef unsigned long long ULONG64;
typedef short SHORT;
typedef unsigned short USHORT;
#define ULONG64_DEFINED
/* Define the priority levels for ThreadX. Legal values range
from 32 to 1024 and MUST be evenly divisible by 32. */
@@ -111,19 +134,19 @@ typedef unsigned short USHORT;
#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
/* Define various constants for the ThreadX Cortex-M7 port. */
/* Define various constants for the ThreadX Cortex-M port. */
#define TX_INT_DISABLE 1 /* Disable interrupts */
#define TX_INT_ENABLE 0 /* Enable interrupts */
/* 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
/* 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
source constants would be:
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
@@ -131,46 +154,83 @@ typedef unsigned short USHORT;
*/
#ifndef TX_MISRA_ENABLE
#ifndef TX_TRACE_TIME_SOURCE
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
#endif
#else
ULONG _tx_misra_time_stamp_get(VOID);
#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
#endif
#ifndef TX_TRACE_TIME_MASK
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
#endif
#ifdef __ghs__
/* Define constants for Green Hills EventAnalyzer. */
/* Define the number of ticks per second. This informs the EventAnalyzer what the timestamps
represent. By default, this is set to 1,000,000 i.e., one tick every microsecond. */
#define TX_EL_TICKS_PER_SECOND 1000000
/* Define the method of how to get the upper and lower 32-bits of the time stamp. By default, simply
simulate the time-stamp source with a counter. */
#define read_tbu() _tx_el_time_base_upper
#define read_tbl() ++_tx_el_time_base_lower
#endif /* __ghs__ */
/* Define the port specific options for the _tx_build_options variable. This variable indicates
how the ThreadX library was built. */
#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
#define TX_PORT_SPECIFIC_BUILD_OPTIONS (0)
/* Define the in-line initialization constant so that modules with in-line
initialization capabilities can prevent their initialization from being
a function call. */
#ifdef TX_MISRA_ENABLE
#define TX_DISABLE_INLINE
#else
#define TX_INLINE_INITIALIZATION
#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
logic. */
#ifndef TX_MISRA_ENABLE
#ifdef TX_ENABLE_STACK_CHECKING
#undef TX_DISABLE_STACK_FILLING
#endif
#endif
/* 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
#define TX_THREAD_EXTENSION_1
#define TX_THREAD_EXTENSION_2
#define TX_THREAD_EXTENSION_3
#define TX_THREAD_EXTENSION_0
#define TX_THREAD_EXTENSION_1
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
#elif defined(__ghs__)
#define TX_THREAD_EXTENSION_2 VOID * tx_thread_eh_globals; \
int Errno; /* errno. */ \
char * strtok_saved_pos; /* strtok() position. */
#else
#define TX_THREAD_EXTENSION_2
#endif
#define TX_THREAD_EXTENSION_3
/* Define the port extensions of the remaining ThreadX objects. */
@@ -184,11 +244,11 @@ typedef unsigned short USHORT;
#define TX_TIMER_EXTENSION
/* 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
#define TX_THREAD_USER_EXTENSION
#define TX_THREAD_USER_EXTENSION
#endif
@@ -196,12 +256,28 @@ typedef unsigned short USHORT;
tx_thread_shell_entry, and tx_thread_terminate. */
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#if (__VER__ < 8000000)
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
#else
void *_tx_iar_create_per_thread_tls_area(void);
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
void __iar_Initlocks(void);
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
#endif
#else
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
#endif
#ifdef TX_ENABLE_FPU_SUPPORT
#if defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__TARGET_FPU_VFP) || defined(__VFP__)
#ifdef TX_MISRA_ENABLE
@@ -210,26 +286,49 @@ void _tx_misra_control_set(ULONG value);
ULONG _tx_misra_fpccr_get(void);
void _tx_misra_vfp_touch(void);
#else
#else /* TX_MISRA_ENABLE not defined */
__attribute__( ( always_inline ) ) static inline ULONG __get_control(void)
/* Define some helper functions (these are intrinsics in some compilers). */
#ifdef __GNUC__ /* GCC and ARM Compiler 6 */
__attribute__( ( always_inline ) ) static inline ULONG __get_control_value(void)
{
ULONG control_value;
__asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) );
return(control_value);
}
__attribute__( ( always_inline ) ) static inline void __set_control(ULONG control_value)
__attribute__( ( always_inline ) ) static inline void __set_control_value(ULONG control_value)
{
__asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" );
}
#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
#endif
#elif defined(__CC_ARM) /* ARM Compiler 5 */
__attribute__( ( always_inline ) ) ULONG __get_control_value(void)
{
ULONG control_value;
__asm volatile ("MRS control_value,CONTROL");
return(control_value);
}
__attribute__( ( always_inline ) ) void __set_control_value(ULONG control_value)
{
__asm__ volatile ("MSR CONTROL,control_value");
}
/* Can't access VFP registers with inline asm, so define this in tx_thread_schedule. */
void _tx_vfp_access(void);
#define TX_VFP_TOUCH() _tx_vfp_access();
#elif defined(__ICCARM__) /* IAR */
#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
#endif /* Helper functions for different compilers */
#endif /* TX_MISRA_ENABLE */
/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA
@@ -237,23 +336,22 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
#ifndef TX_MISRA_ENABLE
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control(_tx_vfp_state); \
}
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
}
#else
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
}
#endif
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
}
#endif
/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR.
If so, deactivate the FPU via CONTROL.FPCA. Otherwise we are in an interrupt or another thread is terminating
@@ -262,79 +360,76 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
#ifndef TX_MISRA_ENABLE
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = *((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 = _tx_vfp_state & ((ULONG) 0x4); \
__asm__ volatile ("vmov.f32 s0, s0"); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = __get_control(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control(_tx_vfp_state); \
} \
} \
} \
}
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = *((ULONG *) 0xE000EF34); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
TX_VFP_TOUCH(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
} \
} \
} \
}
#else
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = _tx_misra_fpccr_get(); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
_tx_misra_vfp_touch(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
} \
} \
}
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = _tx_misra_fpccr_get(); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
_tx_misra_vfp_touch(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
} \
} \
}
#endif
#else
#else /* No VFP in use */
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
#endif
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
#endif /* defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) */
/* Define the ThreadX object creation extensions for the remaining objects. */
@@ -359,126 +454,242 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
/* Define the get system state macro. */
/* Define the get system state macro. */
#ifndef TX_THREAD_GET_SYSTEM_STATE
#ifndef TX_MISRA_ENABLE
#ifdef __CC_ARM /* ARM Compiler 5 */
register unsigned int _ipsr __asm("ipsr");
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _ipsr)
#elif defined(__GNUC__) /* GCC and ARM Compiler 6 */
__attribute__( ( always_inline ) ) static inline unsigned int __get_ipsr_value(void)
{
unsigned int ipsr_value;
__asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) );
return(ipsr_value);
}
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_ipsr_value())
#else
#elif defined(__ICCARM__) /* IAR */
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_IPSR())
#endif /* TX_THREAD_GET_SYSTEM_STATE for different compilers */
#else /* TX_MISRA_ENABLE is defined, use MISRA function. */
ULONG _tx_misra_ipsr_get(VOID);
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
#endif
#endif
#endif /* TX_MISRA_ENABLE */
#endif /* TX_THREAD_GET_SYSTEM_STATE */
/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
indicates that _tx_thread_system_return should not be called. */
indicates that _tx_thread_system_return should not be called. This overrides the definition in tx_thread.h
for Cortex-M since so we don't waste time checking the _tx_thread_system_state variable that is always
zero after initialization for Cortex-M ports. */
#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
#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++;
/* This 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
/* Define the TX_LOWEST_SET_BIT_CALCULATE macro for each compiler. */
#ifdef __ICCARM__ /* IAR Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __CLZ(__RBIT((m)));
#elif defined(__CC_ARM) /* AC5 Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __clz(__rbit((m)));
#elif defined(__GNUC__) /* GCC and AC6 Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \
__asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) );
#endif
#ifndef TX_DISABLE_INLINE
/* Define AC6 specific macros, with in-line assembly for performance. */
/* Define the interrupt disable/restore macros for each compiler. */
#if defined(__GNUC__) || defined(__ICCARM__)
/*** GCC/AC6 and IAR ***/
__attribute__( ( always_inline ) ) static inline unsigned int __get_interrupt_posture(void)
{
unsigned int posture;
#ifdef TX_PORT_USE_BASEPRI
__asm__ volatile ("MRS %0, BASEPRI ": "=r" (posture));
#else
__asm__ volatile ("MRS %0, PRIMASK ": "=r" (posture));
#endif
return(posture);
}
#ifdef TX_PORT_USE_BASEPRI
__attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value)
{
__asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value));
}
#else
__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
{
__asm__ volatile ("CPSIE i": : : "memory");
}
#endif
__attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture)
{
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(int_posture);
//__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory");
#else
__asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory");
#endif
}
__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
{
unsigned int int_posture;
unsigned int primask_value;
int_posture = __get_interrupt_posture();
__asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
__asm__ volatile (" CPSID i" : : : "memory" );
return(primask_value);
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(TX_PORT_BASEPRI);
#else
__asm__ volatile ("CPSID i" : : : "memory");
#endif
return(int_posture);
}
__attribute__( ( always_inline ) ) static inline void __restore_interrupts(unsigned int primask_value)
{
__asm__ volatile (" MSR PRIMASK,%0": : "r" (primask_value): "memory" );
}
__attribute__( ( always_inline ) ) static inline unsigned int __get_primask_value(void)
{
unsigned int primask_value;
__asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
return(primask_value);
}
__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
{
__asm__ volatile (" CPSIE i": : : "memory" );
}
__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
{
unsigned int interrupt_save;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (__get_ipsr_value() == 0)
{
interrupt_save = __get_primask_value();
interrupt_save = __get_interrupt_posture();
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(0);
#else
__enable_interrupts();
__restore_interrupts(interrupt_save);
}
#endif
__restore_interrupt(interrupt_save);
}
}
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
#define TX_DISABLE interrupt_save = __disable_interrupts();
#define TX_RESTORE __restore_interrupt(interrupt_save);
/*** End GCC/AC6 and IAR ***/
#elif defined(__CC_ARM)
/*** AC5 ***/
static __inline unsigned int __get_interrupt_posture(void)
{
unsigned int posture;
#ifdef TX_PORT_USE_BASEPRI
__asm__ volatile ("MRS #posture, BASEPRI");
#else
__asm__ volatile ("MRS #posture, PRIMASK");
#endif
return(posture);
}
#ifdef TX_PORT_USE_BASEPRI
static __inline void __set_basepri_value(unsigned int basepri_value)
{
__asm__ volatile ("MSR BASEPRI, #basepri_value");
}
#endif
static __inline unsigned int __disable_interrupts(void)
{
unsigned int int_posture;
int_posture = __get_interrupt_posture();
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(TX_PORT_BASEPRI);
#else
__asm__ volatile ("CPSID i");
#endif
return(int_posture);
}
static __inline void __restore_interrupt(unsigned int int_posture)
{
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(int_posture);
#else
__asm__ volatile ("MSR PRIMASK, #int_posture");
#endif
}
static void _tx_thread_system_return_inline(void)
{
unsigned int interrupt_save;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (_ipsr == 0)
{
#ifdef TX_PORT_USE_BASEPRI
interrupt_save = __get_interrupt_posture();
__set_basepri_value(0);
__set_basepri_value(interrupt_save);
#else
interrupt_save = __disable_irq();
__enable_irq();
if (interrupt_save != 0)
__disable_irq();
#endif
}
}
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
#define TX_DISABLE interrupt_save = __disable_interrupts();
#define TX_RESTORE __restore_interrupt(interrupt_save);
#define TX_DISABLE interrupt_save = __disable_interrupts();
#define TX_RESTORE __restore_interrupts(interrupt_save);
/*** End AC5 ***/
#endif /* Interrupt disable/restore macros for each compiler. */
/* Redefine _tx_thread_system_return for improved performance. */
#define _tx_thread_system_return _tx_thread_system_return_inline
#else
#else /* TX_DISABLE_INLINE is defined */
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
UINT _tx_thread_interrupt_disable(VOID);
VOID _tx_thread_interrupt_restore(UINT previous_posture);
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
#endif
#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
#endif /* TX_DISABLE_INLINE */
/* Define FPU extension for the Cortex-M4. Each is assumed to be called in the context of the executing
thread. This is for legacy only, and not needed anylonger. */
/* Define FPU extension for the Cortex-M. 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);
@@ -487,16 +698,15 @@ void tx_thread_fpu_disable(void);
/* 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-M4/AC6 Version 6.1.6 *";
CHAR _tx_version_id[] =
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M4/AC6 Version 6.1.7 *";
#else
#ifdef TX_MISRA_ENABLE
extern CHAR _tx_version_id[100];
#else
extern CHAR _tx_version_id[];
#endif
#endif
#endif

View File

@@ -1,41 +1,39 @@
Microsoft's Azure RTOS ThreadX for Cortex-M4
Microsoft's Azure RTOS ThreadX for ARMv7-M
(Cortex-M3, Cortex-M4, Cortex-M7)
Using ARM Compiler 6 (AC6)
Using the AC6 Tools
1. Import the ThreadX Projects
1. Building the ThreadX run-time Library
In order to build the ThreadX library and the ThreadX demonstration, first import
the 'tx' and 'sample_threadx' projects (located in the "example_build" directory)
into your DS workspace.
2. Building the ThreadX run-time Library
Building the ThreadX library is easy; simply right-click the Eclipse project
"tx" and then select the "Build Project" button. You should now observe the compilation
and assembly of the ThreadX library. This project build produces the ThreadX
library file tx.a.
3. Demonstration System
2. Demonstration System
The ThreadX demonstration is designed to execute under the DS debugger on the
MPS2_Cortex_M4 Bare Metal simulator.
MPS2_Cortex_Mx Bare Metal simulator.
Building the demonstration is easy; simply right-click the Eclipse project
"sample_threadx" and then select the "Build Project" button. You should now observe
the compilation and assembly of the ThreadX demonstration. This project build produces
the ThreadX library file sample_threadx.axf. Next, expand the demo ThreadX project folder
in the Project Explorer window, right-click on the 'cortex-m4_tx.launch' file, click
'Debug As', and then click 'cortex-m4_tx' from the submenu. This will cause the
in the Project Explorer window, right-click on the 'cortex-mx_tx.launch' file, click
'Debug As', and then click 'cortex-mx_tx' from the submenu. This will cause the
debugger to load the sample_threadx.axf ELF file and run to main. You are now ready
to execute the ThreadX demonstration.
4. System Initialization
3. System Initialization
The entry point in ThreadX for the Cortex-M4 using AC6 tools uses the standard AC6
Cortex-M4 reset sequence. From the reset vector the C runtime will be initialized.
The entry point in ThreadX for the Cortex-M using AC6 tools uses the standard GNU
Cortex-M reset sequence. From the reset vector the C runtime will be initialized.
The ThreadX tx_initialize_low_level.S file is responsible for setting up
various system data structures, the vector area, and a periodic timer interrupt
@@ -46,11 +44,11 @@ address for use by the application, which is supplied as the sole input
parameter to your application definition function, tx_application_define.
5. Register Usage and Stack Frames
4. Register Usage and Stack Frames
The following defines the saved context stack frames for context switches
that occur as a result of interrupt handling or from thread-level API calls.
All suspended threads have the same stack frame in the Cortex-M4 version of
All suspended threads have the same stack frame in the Cortex-M version of
ThreadX. The top of the suspended thread's stack is pointed to by
tx_thread_stack_ptr in the associated thread control block TX_THREAD.
@@ -58,7 +56,7 @@ Non-FPU Stack Frame:
Stack Offset Stack Contents
0x00 LR Interrupted LR (LR at time of PENDSV)
0x00 lr Interrupted lr (lr at time of PENDSV)
0x04 r4 Software stacked GP registers
0x08 r5
0x0C r6
@@ -80,7 +78,7 @@ FPU Stack Frame (only interrupted thread with FPU enabled):
Stack Offset Stack Contents
0x00 LR Interrupted LR (LR at time of PENDSV)
0x00 lr Interrupted lr (lr at time of PENDSV)
0x04 s16 Software stacked FPU registers
0x08 s17
0x0C s18
@@ -132,57 +130,47 @@ FPU Stack Frame (only interrupted thread with FPU enabled):
0xC4 fpscr
6. Improving Performance
5. Improving Performance
The distribution version of ThreadX is built without any compiler optimizations.
This makes it easy to debug because you can trace or set breakpoints inside of
ThreadX itself. Of course, this costs some performance. To make it run faster,
you can change the build_threadx.bat file to remove the -g option and enable
all compiler optimizations.
The distribution version of ThreadX is built without any compiler
optimizations. This makes it easy to debug because you can trace or set
breakpoints inside of ThreadX itself. Of course, this costs some
performance. To make it run faster, you can change the ThreadX library
project to enable various compiler optimizations.
In addition, you can eliminate the ThreadX basic API error checking by
compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING
defined.
7. Interrupt Handling
6. Interrupt Handling
ThreadX provides complete and high-performance interrupt handling for Cortex-M4
ThreadX provides complete and high-performance interrupt handling for Cortex-M
targets. There are a certain set of requirements that are defined in the
following sub-sections:
7.1 Vector Area
6.1 Vector Area
The Cortex-M4 vectors start at the label __tx_vectors or similar. The application may modify
The Cortex-M vectors start at the label __tx_vectors or similar. The application may modify
the vector area according to its needs. There is code in tx_initialize_low_level() that will
configure the vector base register.
7.2 Managed Interrupts
6.2 Managed Interrupts
ISRs can be written completely in C (or assembly language) without any calls to
_tx_thread_context_save or _tx_thread_context_restore. These ISRs are allowed access to the
ThreadX API that is available to ISRs.
ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table):
void your_C_isr(void)
{
/* ISR processing goes here, including any needed function calls. */
}
ISRs written in assembly language will take the form:
A ThreadX managed interrupt is defined below. By following these conventions, the
application ISR is then allowed access to various ThreadX services from the ISR.
Here is the standard template for managed ISRs in ThreadX:
.global your_assembly_isr
.global __tx_IntHandler
.thumb_func
your_assembly_isr:
; VOID your_assembly_isr(VOID)
__tx_IntHandler:
; VOID InterruptHandler (VOID)
; {
PUSH {r0, lr}
;
; /* Do interrupt handler work here */
; /* BL <your interrupt routine in C> */
@@ -190,37 +178,31 @@ your_assembly_isr:
BX lr
; }
Note: the Cortex-M4 requires exception handlers to be thumb labels, this implies bit 0 set.
Note: the Cortex-M requires exception handlers to be thumb labels, this implies bit 0 set.
To accomplish this, the declaration of the label has to be preceded by the assembler directive
.thumb_func to instruct the linker to create thumb labels. The label __tx_IntHandler needs to
be inserted in the correct location in the interrupt vector table. This table is typically
located in either your runtime startup file or in the tx_initialize_low_level.S file.
8. FPU Support
7. FPU Support
ThreadX for Cortex-M4 supports automatic ("lazy") VFP support, which means that applications threads
ThreadX for Cortex-M supports automatic ("lazy") VFP support, which means that applications threads
can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread
context. If saving the context of the FPU registers is needed, the ThreadX library should be re-built
with TX_ENABLE_FPU_SUPPORT defined.
context - no additional setup by the application.
9. Revision History
8. Revision History
For generic code revision information, please refer to the readme_threadx_generic.txt
file, which is included in your distribution. The following details the revision
information associated with this specific port of ThreadX:
04-02-2021 Release 6.1.6 changes:
tx_port.h Updated macro definition
03-02-2021 The following files were changed/added for version 6.1.5:
tx_thread_schedule.s Added low power feature
09-30-2020 Initial ThreadX 6.1 version for Cortex-M4 using AC6 tools.
06-02-2021 Initial ThreadX version 6.1.7 for Cortex-M using AC6 tools.
Copyright(c) 1996-2020 Microsoft Corporation
Copyright(c) 1996-2021 Microsoft Corporation
https://azure.com/rtos

View File

@@ -1,86 +1,81 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
@
@
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Thread */
@/** */
@/**************************************************************************/
@/**************************************************************************/
@
@
.global _tx_thread_system_state
.global _tx_thread_current_ptr
.global _tx_thread_system_stack_ptr
.global _tx_thread_execute_ptr
.global _tx_timer_time_slice
.global _tx_thread_schedule
.global _tx_thread_preempt_disable
@
@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
.global _tx_execution_isr_exit
#endif
.text
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_thread_context_restore Cortex-M4/AC6 */
@/* 6.1 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function is only needed for legacy applications and it should */
@/* not be called in any new development on a Cortex-M. */
@/* This function restores the interrupt context if it is processing a */
@/* nested interrupt. If not, it returns to the interrupt thread if no */
@/* preemption is necessary. Otherwise, if preemption is necessary or */
@/* if no thread was running, the function returns to the scheduler. */
@/* */
@/* INPUT */
@/* */
@/* None */
@/* */
@/* OUTPUT */
@/* */
@/* None */
@/* */
@/* CALLS */
@/* */
@/* _tx_thread_schedule Thread scheduling routine */
@/* */
@/* CALLED BY */
@/* */
@/* ISRs Interrupt Service Routines */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 09-30-2020 William E. Lamie Initial Version 6.1 */
@/* */
@/**************************************************************************/
@VOID _tx_thread_context_restore(VOID)
@{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_context_restore Cortex-M4/AC6 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is only needed for legacy applications and it should */
/* not be called in any new development on a Cortex-M. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* [_tx_execution_isr_exit] Execution profiling ISR exit */
/* */
/* CALLED BY */
/* */
/* ISRs Interrupt Service Routines */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_context_restore(VOID)
// {
.global _tx_thread_context_restore
.thumb_func
_tx_thread_context_restore:
@
@ /* Not needed for this port - just return! */
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the ISR exit function to indicate an ISR is complete. */
PUSH {r0, lr} // Save return address
BL _tx_execution_isr_exit // Call the ISR exit function
POP {r0, lr} // Recover return address
#endif
BX lr
@}
// }

View File

@@ -1,80 +1,83 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
@
@
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Thread */
@/** */
@/**************************************************************************/
@/**************************************************************************/
@
@
.global _tx_thread_system_state
.global _tx_thread_current_ptr
@
@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.text
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_thread_context_save Cortex-M4/AC6 */
@/* 6.1 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function is only needed for legacy applications and it should */
@/* not be called in any new development on a Cortex-M. */
@/* This function saves the context of an executing thread in the */
@/* beginning of interrupt processing. The function also ensures that */
@/* the system stack is used upon return to the calling ISR. */
@/* */
@/* INPUT */
@/* */
@/* None */
@/* */
@/* OUTPUT */
@/* */
@/* None */
@/* */
@/* CALLS */
@/* */
@/* None */
@/* */
@/* CALLED BY */
@/* */
@/* ISRs */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 09-30-2020 William E. Lamie Initial Version 6.1 */
@/* */
@/**************************************************************************/
@VOID _tx_thread_context_save(VOID)
@{
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
.global _tx_execution_isr_enter
#endif
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_context_save Cortex-M4/AC6 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is only needed for legacy applications and it should */
/* not be called in any new development on a Cortex-M. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* ISRs */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_context_save(VOID)
// {
.global _tx_thread_context_save
.thumb_func
_tx_thread_context_save:
@
@ /* Not needed for this port - just return! */
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the ISR enter function to indicate an ISR is starting. */
PUSH {r0, lr} // Save return address
BL _tx_execution_isr_enter // Call the ISR enter function
POP {r0, lr} // Recover return address
#endif
/* Context is already saved - just return. */
BX lr
@}
// }

View File

@@ -1,81 +1,79 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Thread */
@/** */
@/**************************************************************************/
@/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.text 32
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_thread_interrupt_control Cortex-M4/AC6 */
@/* 6.1 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function is responsible for changing the interrupt lockout */
@/* posture of the system. */
@/* */
@/* INPUT */
@/* */
@/* new_posture New interrupt lockout posture */
@/* */
@/* OUTPUT */
@/* */
@/* old_posture Old interrupt lockout posture */
@/* */
@/* CALLS */
@/* */
@/* None */
@/* */
@/* CALLED BY */
@/* */
@/* Application Code */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 09-30-2020 William E. Lamie Initial Version 6.1 */
@/* */
@/**************************************************************************/
@/* UINT _tx_thread_interrupt_control(UINT new_posture)
{ */
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_control Cortex-M4/AC6 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for changing the interrupt lockout */
/* posture of the system. */
/* */
/* INPUT */
/* */
/* new_posture New interrupt lockout posture */
/* */
/* OUTPUT */
/* */
/* old_posture Old interrupt lockout posture */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// UINT _tx_thread_interrupt_control(UINT new_posture)
// {
.global _tx_thread_interrupt_control
.thumb_func
_tx_thread_interrupt_control:
@/* Pickup current interrupt lockout posture. */
MRS r1, PRIMASK @ Pickup current interrupt lockout
@/* Apply the new interrupt posture. */
MSR PRIMASK, r0 @ Apply the new interrupt lockout
MOV r0, r1 @ Transfer old to return register
BX lr @ Return to caller
@/* } */
#ifdef TX_PORT_USE_BASEPRI
MRS r1, BASEPRI // Pickup current interrupt posture
MSR BASEPRI, r0 // Apply the new interrupt posture
MOV r0, r1 // Transfer old to return register
#else
MRS r1, PRIMASK // Pickup current interrupt lockout
MSR PRIMASK, r0 // Apply the new interrupt lockout
MOV r0, r1 // Transfer old to return register
#endif
BX lr // Return to caller
// }

View File

@@ -0,0 +1,79 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.text 32
.align 4
.syntax unified
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_disable Cortex-M4/AC6 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for disabling interrupts and returning */
/* the previous interrupt lockout posture. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* old_posture Old interrupt lockout posture */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// UINT _tx_thread_interrupt_disable(VOID)
// {
.global _tx_thread_interrupt_disable
.thumb_func
_tx_thread_interrupt_disable:
/* Return current interrupt lockout posture. */
#ifdef TX_PORT_USE_BASEPRI
MRS r0, BASEPRI
LDR r1, =TX_PORT_BASEPRI
MSR BASEPRI, r1
#else
MRS r0, PRIMASK
CPSID i
#endif
BX lr
// }

View File

@@ -0,0 +1,76 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.text 32
.align 4
.syntax unified
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_restore Cortex-M4/AC6 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for restoring the previous */
/* interrupt lockout posture. */
/* */
/* INPUT */
/* */
/* previous_posture Previous interrupt posture */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_interrupt_restore(UINT previous_posture)
// {
.global _tx_thread_interrupt_restore
.thumb_func
_tx_thread_interrupt_restore:
/* Restore previous interrupt lockout posture. */
#ifdef TX_PORT_USE_BASEPRI
MSR BASEPRI, r0
#else
MSR PRIMASK, r0
#endif
BX lr
// }

View File

@@ -1,304 +1,286 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
@
@
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Thread */
@/** */
@/**************************************************************************/
@/**************************************************************************/
@
@
.global _tx_thread_current_ptr
.global _tx_thread_execute_ptr
.global _tx_timer_time_slice
.global _tx_thread_system_stack_ptr
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.global _tx_thread_current_ptr
.global _tx_thread_execute_ptr
.global _tx_timer_time_slice
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
.global _tx_execution_thread_enter
.global _tx_execution_thread_exit
#endif
#ifdef TX_LOW_POWER
.global tx_low_power_enter
.global tx_low_power_exit
#endif
@
@
.text
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_thread_schedule Cortex-M4/AC6 */
@/* 6.1.5 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function waits for a thread control block pointer to appear in */
@/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
@/* in the variable, the corresponding thread is resumed. */
@/* */
@/* INPUT */
@/* */
@/* None */
@/* */
@/* OUTPUT */
@/* */
@/* None */
@/* */
@/* CALLS */
@/* */
@/* None */
@/* */
@/* CALLED BY */
@/* */
@/* _tx_initialize_kernel_enter ThreadX entry function */
@/* _tx_thread_system_return Return to system from thread */
@/* _tx_thread_context_restore Restore thread's context */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 09-30-2020 William E. Lamie Initial Version 6.1 */
@/* 03-02-2021 Scott Larson Modified comment(s), add */
@/* low power code, */
@/* resulting in version 6.1.5 */
@/* */
@/**************************************************************************/
@VOID _tx_thread_schedule(VOID)
@{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_schedule Cortex-M4/AC6 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function waits for a thread control block pointer to appear in */
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
/* in the variable, the corresponding thread is resumed. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_initialize_kernel_enter ThreadX entry function */
/* _tx_thread_system_return Return to system from thread */
/* _tx_thread_context_restore Restore thread's context */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_schedule(VOID)
// {
.global _tx_thread_schedule
.thumb_func
_tx_thread_schedule:
@
@ /* This function should only ever be called on Cortex-M4
@ from the first schedule request. Subsequent scheduling occurs
@ from the PendSV handling routines below. */
@
@ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
@
MOV r0, #0 @ Build value for TX_FALSE
LDR r2, =_tx_thread_preempt_disable @ Build address of preempt disable flag
STR r0, [r2, #0] @ Clear preempt disable flag
@
@ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
@
#ifdef TX_ENABLE_FPU_SUPPORT
MRS r0, CONTROL @ Pickup current CONTROL register
BIC r0, r0, #4 @ Clear the FPCA bit
MSR CONTROL, r0 @ Setup new CONTROL register
/* This function should only ever be called on Cortex-M
from the first schedule request. Subsequent scheduling occurs
from the PendSV handling routine below. */
/* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
MOV r0, #0 // Build value for TX_FALSE
LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
STR r0, [r2, #0] // Clear preempt disable flag
/* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
#ifdef __ARM_PCS_VFP
MRS r0, CONTROL // Pickup current CONTROL register
BIC r0, r0, #4 // Clear the FPCA bit
MSR CONTROL, r0 // Setup new CONTROL register
#endif
@
@ /* Enable interrupts */
@
/* Enable interrupts */
CPSIE i
@
@ /* Enter the scheduler for the first time. */
@
MOV r0, #0x10000000 @ Load PENDSVSET bit
MOV r1, #0xE000E000 @ Load NVIC base
STR r0, [r1, #0xD04] @ Set PENDSVBIT in ICSR
DSB @ Complete all memory accesses
ISB @ Flush pipeline
@
@ /* Wait here for the PendSV to take place. */
@
/* Enter the scheduler for the first time. */
MOV r0, #0x10000000 // Load PENDSVSET bit
MOV r1, #0xE000E000 // Load NVIC base
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
DSB // Complete all memory accesses
ISB // Flush pipeline
/* Wait here for the PendSV to take place. */
__tx_wait_here:
B __tx_wait_here @ Wait for the PendSV to happen
@}
@
@ /* Generic context switch-out switch-in handler... Note that this handler is
@ common for both PendSV and SVCall. */
@
B __tx_wait_here // Wait for the PendSV to happen
// }
/* Generic context switching PendSV handler. */
.global PendSV_Handler
.global __tx_PendSVHandler
.syntax unified
.thumb_func
PendSV_Handler:
.thumb_func
__tx_PendSVHandler:
@
@ /* Get current thread value and new thread pointer. */
@
/* Get current thread value and new thread pointer. */
__tx_ts_handler:
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
@
@ /* Call the thread exit function to indicate the thread is no longer executing. */
@
CPSID i @ Disable interrupts
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
CPSIE i @ Enable interrupts
#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
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
CPSIE i // Enable interrupts
#endif
LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address
LDR r2, =_tx_thread_execute_ptr @ Build execute thread pointer address
MOV r3, #0 @ Build NULL value
LDR r1, [r0] @ Pickup current thread pointer
@
@ /* Determine if there is a current thread to finish preserving. */
@
CBZ r1, __tx_ts_new @ If NULL, skip preservation
@
@ /* Recover PSP and preserve current thread context. */
@
STR r3, [r0] @ Set _tx_thread_current_ptr to NULL
MRS r12, PSP @ Pickup PSP pointer (thread's stack pointer)
STMDB r12!, {r4-r11} @ Save its remaining registers
#ifdef TX_ENABLE_FPU_SUPPORT
TST LR, #0x10 @ Determine if the VFP extended frame is present
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
MOV r3, #0 // Build NULL value
LDR r1, [r0] // Pickup current thread pointer
/* Determine if there is a current thread to finish preserving. */
CBZ r1, __tx_ts_new // If NULL, skip preservation
/* Recover PSP and preserve current thread context. */
STR r3, [r0] // Set _tx_thread_current_ptr to NULL
MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
STMDB r12!, {r4-r11} // Save its remaining registers
#ifdef __ARM_PCS_VFP
TST LR, #0x10 // Determine if the VFP extended frame is present
BNE _skip_vfp_save
VSTMDB r12!,{s16-s31} @ Yes, save additional VFP registers
VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
_skip_vfp_save:
#endif
LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
STMDB r12!, {LR} @ Save LR on the stack
@
@ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
@
LDR r5, [r4] @ Pickup current time-slice
STR r12, [r1, #8] @ Save the thread stack pointer
CBZ r5, __tx_ts_new @ If not active, skip processing
@
@ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
@
STR r5, [r1, #24] @ Save current time-slice
@
@ /* Clear the global time-slice. */
@
STR r3, [r4] @ Clear time-slice
@
@
@ /* Executing thread is now completely preserved!!! */
@
__tx_ts_new:
@
@ /* Now we are looking for a new thread to execute! */
@
CPSID i @ Disable interrupts
LDR r1, [r2] @ Is there another thread ready to execute?
CBZ r1, __tx_ts_wait @ No, skip to the wait processing
@
@ /* Yes, another thread is ready for else, make the current thread the new thread. */
@
STR r1, [r0] @ Setup the current thread pointer to the new thread
CPSIE i @ Enable interrupts
@
@ /* Increment the thread run count. */
@
__tx_ts_restore:
LDR r7, [r1, #4] @ Pickup the current thread run count
LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
LDR r5, [r1, #24] @ Pickup thread's current time-slice
ADD r7, r7, #1 @ Increment the thread run count
STR r7, [r1, #4] @ Store the new run count
@
@ /* Setup global time-slice with thread's current time-slice. */
@
STR r5, [r4] @ Setup global time-slice
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
STMDB r12!, {LR} // Save LR on the stack
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
@
@ /* Call the thread entry function to indicate the thread is executing. */
@
PUSH {r0, r1} @ Save r0/r1
BL _tx_execution_thread_enter @ Call the thread execution enter function
POP {r0, r1} @ Recover r3
/* Determine if time-slice is active. If it isn't, skip time handling processing. */
LDR r5, [r4] // Pickup current time-slice
STR r12, [r1, #8] // Save the thread stack pointer
CBZ r5, __tx_ts_new // If not active, skip processing
/* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
STR r5, [r1, #24] // Save current time-slice
/* Clear the global time-slice. */
STR r3, [r4] // Clear time-slice
/* Executing thread is now completely preserved!!! */
__tx_ts_new:
/* Now we are looking for a new thread to execute! */
CPSID i // Disable interrupts
LDR r1, [r2] // Is there another thread ready to execute?
CBZ r1, __tx_ts_wait // No, skip to the wait processing
/* Yes, another thread is ready for else, make the current thread the new thread. */
STR r1, [r0] // Setup the current thread pointer to the new thread
CPSIE i // Enable interrupts
/* Increment the thread run count. */
__tx_ts_restore:
LDR r7, [r1, #4] // Pickup the current thread run count
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
LDR r5, [r1, #24] // Pickup thread's current time-slice
ADD r7, r7, #1 // Increment the thread run count
STR r7, [r1, #4] // Store the new run count
/* Setup global time-slice with thread's current time-slice. */
STR r5, [r4] // Setup global time-slice
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the thread entry function to indicate the thread is executing. */
PUSH {r0, r1} // Save r0 and r1
BL _tx_execution_thread_enter // Call the thread execution enter function
POP {r0, r1} // Recover r0 and r1
#endif
@
@ /* Restore the thread context and PSP. */
@
LDR r12, [r1, #8] @ Pickup thread's stack pointer
LDMIA r12!, {LR} @ Pickup LR
#ifdef TX_ENABLE_FPU_SUPPORT
TST LR, #0x10 @ Determine if the VFP extended frame is present
BNE _skip_vfp_restore @ If not, skip VFP restore
VLDMIA r12!, {s16-s31} @ Yes, restore additional VFP registers
/* Restore the thread context and PSP. */
LDR r12, [r1, #8] // Pickup thread's stack pointer
LDMIA r12!, {LR} // Pickup LR
#ifdef __ARM_PCS_VFP
TST LR, #0x10 // Determine if the VFP extended frame is present
BNE _skip_vfp_restore // If not, skip VFP restore
VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
_skip_vfp_restore:
#endif
LDMIA r12!, {r4-r11} @ Recover thread's registers
MSR PSP, r12 @ Setup the thread's stack pointer
@
@ /* Return to thread. */
@
BX lr @ Return to thread!
@
@ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
@ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
@ are disabled to allow use of WFI for waiting for a thread to arrive. */
@
LDMIA r12!, {r4-r11} // Recover thread's registers
MSR PSP, r12 // Setup the thread's stack pointer
/* Return to thread. */
BX lr // Return to thread!
/* The following is the idle wait processing... in this case, no threads are ready for execution and the
system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
are disabled to allow use of WFI for waiting for a thread to arrive. */
__tx_ts_wait:
CPSID i @ Disable interrupts
LDR r1, [r2] @ Pickup the next thread to execute pointer
STR r1, [r0] @ Store it in the current pointer
CBNZ r1, __tx_ts_ready @ If non-NULL, a new thread is ready!
CPSID i // Disable interrupts
LDR r1, [r2] // Pickup the next thread to execute pointer
STR r1, [r0] // Store it in the current pointer
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
#ifdef TX_LOW_POWER
PUSH {r0-r3}
BL tx_low_power_enter @ Possibly enter low power mode
POP {r0-r3}
BL tx_low_power_enter // Possibly enter low power mode
#endif
#ifdef TX_ENABLE_WFI
DSB @ Ensure no outstanding memory transactions
WFI @ Wait for interrupt
ISB @ Ensure pipeline is flushed
DSB // Ensure no outstanding memory transactions
WFI // Wait for interrupt
ISB // Ensure pipeline is flushed
#endif
#ifdef TX_LOW_POWER
PUSH {r0-r3}
BL tx_low_power_exit @ Exit low power mode
POP {r0-r3}
BL tx_low_power_exit // Exit low power mode
#endif
CPSIE i @ Enable interrupts
B __tx_ts_wait @ Loop to continue waiting
@
@ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
@ already in the handler! */
@
CPSIE i // Enable interrupts
B __tx_ts_wait // Loop to continue waiting
/* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
already in the handler! */
__tx_ts_ready:
MOV r7, #0x08000000 @ Build clear PendSV value
MOV r8, #0xE000E000 @ Build base NVIC address
STR r7, [r8, #0xD04] @ Clear any PendSV
@
@ /* Re-enable interrupts and restore new thread. */
@
CPSIE i @ Enable interrupts
B __tx_ts_restore @ Restore the thread
MOV r7, #0x08000000 // Build clear PendSV value
MOV r8, #0xE000E000 // Build base NVIC address
STR r7, [r8, #0xD04] // Clear any PendSV
#ifdef TX_ENABLE_FPU_SUPPORT
/* Re-enable interrupts and restore new thread. */
.global tx_thread_fpu_enable
.thumb_func
CPSIE i // Enable interrupts
B __tx_ts_restore // Restore the thread
// }
#ifdef __ARM_PCS_VFP
.global tx_thread_fpu_enable
.thumb_func
tx_thread_fpu_enable:
@
@ /* Automatic VPF logic is supported, this function is present only for
@ backward compatibility purposes and therefore simply returns. */
@
BX LR @ Return to caller
.global tx_thread_fpu_disable
.thumb_func
.global tx_thread_fpu_disable
.thumb_func
tx_thread_fpu_disable:
@
@ /* Automatic VPF logic is supported, this function is present only for
@ backward compatibility purposes and therefore simply returns. */
@
BX LR @ Return to caller
/* Automatic VPF logic is supported, this function is present only for
backward compatibility purposes and therefore simply returns. */
BX LR // Return to caller
#endif

View File

@@ -1,135 +1,133 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
@
@
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Thread */
@/** */
@/**************************************************************************/
@/**************************************************************************/
@
@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.text
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_thread_stack_build Cortex-M4/AC6 */
@/* 6.1 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function builds a stack frame on the supplied thread's stack. */
@/* The stack frame results in a fake interrupt return to the supplied */
@/* function pointer. */
@/* */
@/* INPUT */
@/* */
@/* thread_ptr Pointer to thread control blk */
@/* function_ptr Pointer to return function */
@/* */
@/* OUTPUT */
@/* */
@/* None */
@/* */
@/* CALLS */
@/* */
@/* None */
@/* */
@/* CALLED BY */
@/* */
@/* _tx_thread_create Create thread service */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 09-30-2020 William E. Lamie Initial Version 6.1 */
@/* */
@/**************************************************************************/
@VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
@{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_stack_build Cortex-M4/AC6 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function builds a stack frame on the supplied thread's stack. */
/* The stack frame results in a fake interrupt return to the supplied */
/* function pointer. */
/* */
/* INPUT */
/* */
/* thread_ptr Pointer to thread control blk */
/* function_ptr Pointer to return function */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_thread_create Create thread service */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
// {
.global _tx_thread_stack_build
.thumb_func
_tx_thread_stack_build:
@
@
@ /* Build a fake interrupt frame. The form of the fake interrupt stack
@ on the Cortex-M4 should look like the following after it is built:
@
@ Stack Top:
@ LR Interrupted LR (LR at time of PENDSV)
@ r4 Initial value for r4
@ r5 Initial value for r5
@ r6 Initial value for r6
@ r7 Initial value for r7
@ r8 Initial value for r8
@ r9 Initial value for r9
@ r10 Initial value for r10
@ r11 Initial value for r11
@ r0 Initial value for r0 (Hardware stack starts here!!)
@ r1 Initial value for r1
@ r2 Initial value for r2
@ r3 Initial value for r3
@ r12 Initial value for r12
@ lr Initial value for lr
@ pc Initial value for pc
@ xPSR Initial value for xPSR
@
@ Stack Bottom: (higher memory address) */
@
LDR r2, [r0, #16] @ Pickup end of stack area
BIC r2, r2, #0x7 @ Align frame
SUB r2, r2, #68 @ Subtract frame size
LDR r3, =0xFFFFFFFD @ Build initial LR value
STR r3, [r2, #0] @ Save on the stack
@
@ /* Actually build the stack frame. */
@
MOV r3, #0 @ Build initial register value
STR r3, [r2, #4] @ Store initial r4
STR r3, [r2, #8] @ Store initial r5
STR r3, [r2, #12] @ Store initial r6
STR r3, [r2, #16] @ Store initial r7
STR r3, [r2, #20] @ Store initial r8
STR r3, [r2, #24] @ Store initial r9
STR r3, [r2, #28] @ Store initial r10
STR r3, [r2, #32] @ Store initial r11
@
@ /* Hardware stack follows. */
@
STR r3, [r2, #36] @ Store initial r0
STR r3, [r2, #40] @ Store initial r1
STR r3, [r2, #44] @ Store initial r2
STR r3, [r2, #48] @ Store initial r3
STR r3, [r2, #52] @ Store initial r12
MOV r3, #0xFFFFFFFF @ Poison EXC_RETURN value
STR r3, [r2, #56] @ Store initial lr
STR r1, [r2, #60] @ Store initial pc
MOV r3, #0x01000000 @ Only T-bit need be set
STR r3, [r2, #64] @ Store initial xPSR
@
@ /* Setup stack pointer. */
@ thread_ptr -> tx_thread_stack_ptr = r2;
@
STR r2, [r0, #8] @ Save stack pointer in thread's
@ control block
BX lr @ Return to caller
@}
/* Build a fake interrupt frame. The form of the fake interrupt stack
on the Cortex-M should look like the following after it is built:
Stack Top:
LR Interrupted LR (LR at time of PENDSV)
r4 Initial value for r4
r5 Initial value for r5
r6 Initial value for r6
r7 Initial value for r7
r8 Initial value for r8
r9 Initial value for r9
r10 Initial value for r10
r11 Initial value for r11
r0 Initial value for r0 (Hardware stack starts here!!)
r1 Initial value for r1
r2 Initial value for r2
r3 Initial value for r3
r12 Initial value for r12
lr Initial value for lr
pc Initial value for pc
xPSR Initial value for xPSR
Stack Bottom: (higher memory address) */
LDR r2, [r0, #16] // Pickup end of stack area
BIC r2, r2, #0x7 // Align frame for 8-byte alignment
SUB r2, r2, #68 // Subtract frame size
LDR r3, =0xFFFFFFFD // Build initial LR value
STR r3, [r2, #0] // Save on the stack
/* Actually build the stack frame. */
MOV r3, #0 // Build initial register value
STR r3, [r2, #4] // Store initial r4
STR r3, [r2, #8] // Store initial r5
STR r3, [r2, #12] // Store initial r6
STR r3, [r2, #16] // Store initial r7
STR r3, [r2, #20] // Store initial r8
STR r3, [r2, #24] // Store initial r9
STR r3, [r2, #28] // Store initial r10
STR r3, [r2, #32] // Store initial r11
/* Hardware stack follows. */
STR r3, [r2, #36] // Store initial r0
STR r3, [r2, #40] // Store initial r1
STR r3, [r2, #44] // Store initial r2
STR r3, [r2, #48] // Store initial r3
STR r3, [r2, #52] // Store initial r12
MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
STR r3, [r2, #56] // Store initial lr
STR r1, [r2, #60] // Store initial pc
MOV r3, #0x01000000 // Only T-bit need be set
STR r3, [r2, #64] // Store initial xPSR
/* Setup stack pointer. */
// thread_ptr -> tx_thread_stack_ptr = r2;
STR r2, [r0, #8] // Save stack pointer in thread's
// control block
BX lr // Return to caller
// }

View File

@@ -1,88 +1,93 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
@
@
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Thread */
@/** */
@/**************************************************************************/
@/**************************************************************************/
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.text 32
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_thread_system_return Cortex-M4/AC6 */
@/* 6.1 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function is target processor specific. It is used to transfer */
@/* control from a thread back to the ThreadX system. Only a */
@/* minimal context is saved since the compiler assumes temp registers */
@/* are going to get slicked by a function call anyway. */
@/* */
@/* INPUT */
@/* */
@/* None */
@/* */
@/* OUTPUT */
@/* */
@/* None */
@/* */
@/* CALLS */
@/* */
@/* _tx_thread_schedule Thread scheduling loop */
@/* */
@/* CALLED BY */
@/* */
@/* ThreadX components */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 09-30-2020 William E. Lamie Initial Version 6.1 */
@/* */
@/**************************************************************************/
@/* VOID _tx_thread_system_return(VOID)
@{ */
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_system_return Cortex-M4/AC6 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is target processor specific. It is used to transfer */
/* control from a thread back to the ThreadX system. Only a */
/* minimal context is saved since the compiler assumes temp registers */
/* are going to get slicked by a function call anyway. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _tx_thread_schedule Thread scheduling loop */
/* */
/* CALLED BY */
/* */
/* ThreadX components */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_system_return(VOID)
// {
.thumb_func
.global _tx_thread_system_return
_tx_thread_system_return:
@
@ /* Return to real scheduler via PendSV. Note that this routine is often
@ replaced with in-line assembly in tx_port.h to improved performance. */
@
MOV r0, #0x10000000 @ Load PENDSVSET bit
MOV r1, #0xE000E000 @ Load NVIC base
STR r0, [r1, #0xD04] @ Set PENDSVBIT in ICSR
MRS r0, IPSR @ Pickup IPSR
CMP r0, #0 @ Is it a thread returning?
BNE _isr_context @ If ISR, skip interrupt enable
MRS r1, PRIMASK @ Thread context returning, pickup PRIMASK
CPSIE i @ Enable interrupts
MSR PRIMASK, r1 @ Restore original interrupt posture
_isr_context:
BX lr @ Return to caller
@/* } */
/* Return to real scheduler via PendSV. Note that this routine is often
replaced with in-line assembly in tx_port.h to improved performance. */
MOV r0, #0x10000000 // Load PENDSVSET bit
MOV r1, #0xE000E000 // Load NVIC base
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
MRS r0, IPSR // Pickup IPSR
CMP r0, #0 // Is it a thread returning?
BNE _isr_context // If ISR, skip interrupt enable
#ifdef TX_PORT_USE_BASEPRI
MRS r1, BASEPRI // Thread context returning, pickup BASEPRI
MOV r0, #0
MSR BASEPRI, r0 // Enable interrupts
MSR BASEPRI, r1 // Restore original interrupt posture
#else
MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
CPSIE i // Enable interrupts
MSR PRIMASK, r1 // Restore original interrupt posture
#endif
_isr_context:
BX lr // Return to caller
// }

View File

@@ -1,257 +1,250 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
@
@
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Timer */
@/** */
@/**************************************************************************/
@/**************************************************************************/
@
@
.global _tx_timer_time_slice
.global _tx_timer_system_clock
.global _tx_timer_current_ptr
.global _tx_timer_list_start
.global _tx_timer_list_end
.global _tx_timer_expired_time_slice
.global _tx_timer_expired
.global _tx_thread_time_slice
.global _tx_timer_expiration_process
@
@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Timer */
/** */
/**************************************************************************/
/**************************************************************************/
.global _tx_timer_time_slice
.global _tx_timer_system_clock
.global _tx_timer_current_ptr
.global _tx_timer_list_start
.global _tx_timer_list_end
.global _tx_timer_expired_time_slice
.global _tx_timer_expired
.global _tx_thread_time_slice
.global _tx_timer_expiration_process
.text
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_timer_interrupt Cortex-M4/AC6 */
@/* 6.1 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function processes the hardware timer interrupt. This */
@/* processing includes incrementing the system clock and checking for */
@/* time slice and/or timer expiration. If either is found, the */
@/* interrupt context save/restore functions are called along with the */
@/* expiration functions. */
@/* */
@/* INPUT */
@/* */
@/* None */
@/* */
@/* OUTPUT */
@/* */
@/* None */
@/* */
@/* CALLS */
@/* */
@/* _tx_timer_expiration_process Timer expiration processing */
@/* _tx_thread_time_slice Time slice interrupted thread */
@/* */
@/* CALLED BY */
@/* */
@/* interrupt vector */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 09-30-2020 William E. Lamie Initial Version 6.1 */
@/* */
@/**************************************************************************/
@VOID _tx_timer_interrupt(VOID)
@{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_timer_interrupt Cortex-M4/AC6 */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function processes the hardware timer interrupt. This */
/* processing includes incrementing the system clock and checking for */
/* time slice and/or timer expiration. If either is found, the */
/* expiration functions are called. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _tx_timer_expiration_process Timer expiration processing */
/* _tx_thread_time_slice Time slice interrupted thread */
/* */
/* CALLED BY */
/* */
/* interrupt vector */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_timer_interrupt(VOID)
// {
.global _tx_timer_interrupt
.thumb_func
_tx_timer_interrupt:
@
@ /* Upon entry to this routine, it is assumed that context save has already
@ been called, and therefore the compiler scratch registers are available
@ for use. */
@
@ /* Increment the system clock. */
@ _tx_timer_system_clock++;
@
LDR r1, =_tx_timer_system_clock @ Pickup address of system clock
LDR r0, [r1, #0] @ Pickup system clock
ADD r0, r0, #1 @ Increment system clock
STR r0, [r1, #0] @ Store new system clock
@
@ /* Test for time-slice expiration. */
@ if (_tx_timer_time_slice)
@ {
@
LDR r3, =_tx_timer_time_slice @ Pickup address of time-slice
LDR r2, [r3, #0] @ Pickup time-slice
CMP r2, #0 @ Is it non-active?
BEQ __tx_timer_no_time_slice @ Yes, skip time-slice processing
@
@ /* Decrement the time_slice. */
@ _tx_timer_time_slice--;
@
SUB r2, r2, #1 @ Decrement the time-slice
STR r2, [r3, #0] @ Store new time-slice value
@
@ /* Check for expiration. */
@ if (__tx_timer_time_slice == 0)
@
CMP r2, #0 @ Has it expired?
BNE __tx_timer_no_time_slice @ No, skip expiration processing
@
@ /* Set the time-slice expired flag. */
@ _tx_timer_expired_time_slice = TX_TRUE;
@
LDR r3, =_tx_timer_expired_time_slice @ Pickup address of expired flag
MOV r0, #1 @ Build expired value
STR r0, [r3, #0] @ Set time-slice expiration flag
@
@ }
@
/* Upon entry to this routine, it is assumed that the compiler scratch registers are available
for use. */
/* Increment the system clock. */
// _tx_timer_system_clock++;
LDR r1, =_tx_timer_system_clock // Pickup address of system clock
LDR r0, [r1, #0] // Pickup system clock
ADD r0, r0, #1 // Increment system clock
STR r0, [r1, #0] // Store new system clock
/* Test for time-slice expiration. */
// if (_tx_timer_time_slice)
// {
LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
LDR r2, [r3, #0] // Pickup time-slice
CBZ r2, __tx_timer_no_time_slice // Is it non-active?
// Yes, skip time-slice processing
/* Decrement the time_slice. */
// _tx_timer_time_slice--;
SUB r2, r2, #1 // Decrement the time-slice
STR r2, [r3, #0] // Store new time-slice value
/* Check for expiration. */
// if (__tx_timer_time_slice == 0)
CBNZ r2, __tx_timer_no_time_slice // Has it expired?
// No, skip expiration processing
/* Set the time-slice expired flag. */
// _tx_timer_expired_time_slice = TX_TRUE;
LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
MOV r0, #1 // Build expired value
STR r0, [r3, #0] // Set time-slice expiration flag
// }
__tx_timer_no_time_slice:
@
@ /* Test for timer expiration. */
@ if (*_tx_timer_current_ptr)
@ {
@
LDR r1, =_tx_timer_current_ptr @ Pickup current timer pointer address
LDR r0, [r1, #0] @ Pickup current timer
LDR r2, [r0, #0] @ Pickup timer list entry
CMP r2, #0 @ Is there anything in the list?
BEQ __tx_timer_no_timer @ No, just increment the timer
@
@ /* Set expiration flag. */
@ _tx_timer_expired = TX_TRUE;
@
LDR r3, =_tx_timer_expired @ Pickup expiration flag address
MOV r2, #1 @ Build expired value
STR r2, [r3, #0] @ Set expired flag
B __tx_timer_done @ Finished timer processing
@
@ }
@ else
@ {
/* Test for timer expiration. */
// if (*_tx_timer_current_ptr)
// {
LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
LDR r0, [r1, #0] // Pickup current timer
LDR r2, [r0, #0] // Pickup timer list entry
CBZ r2, __tx_timer_no_timer // Is there anything in the list?
// No, just increment the timer
/* Set expiration flag. */
// _tx_timer_expired = TX_TRUE;
LDR r3, =_tx_timer_expired // Pickup expiration flag address
MOV r2, #1 // Build expired value
STR r2, [r3, #0] // Set expired flag
B __tx_timer_done // Finished timer processing
// }
// else
// {
__tx_timer_no_timer:
@
@ /* No timer expired, increment the timer pointer. */
@ _tx_timer_current_ptr++;
@
ADD r0, r0, #4 @ Move to next timer
@
@ /* Check for wrap-around. */
@ if (_tx_timer_current_ptr == _tx_timer_list_end)
@
LDR r3, =_tx_timer_list_end @ Pickup addr of timer list end
LDR r2, [r3, #0] @ Pickup list end
CMP r0, r2 @ Are we at list end?
BNE __tx_timer_skip_wrap @ No, skip wrap-around logic
@
@ /* Wrap to beginning of list. */
@ _tx_timer_current_ptr = _tx_timer_list_start;
@
LDR r3, =_tx_timer_list_start @ Pickup addr of timer list start
LDR r0, [r3, #0] @ Set current pointer to list start
@
/* No timer expired, increment the timer pointer. */
// _tx_timer_current_ptr++;
ADD r0, r0, #4 // Move to next timer
/* Check for wrap-around. */
// if (_tx_timer_current_ptr == _tx_timer_list_end)
LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
LDR r2, [r3, #0] // Pickup list end
CMP r0, r2 // Are we at list end?
BNE __tx_timer_skip_wrap // No, skip wrap-around logic
/* Wrap to beginning of list. */
// _tx_timer_current_ptr = _tx_timer_list_start;
LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
LDR r0, [r3, #0] // Set current pointer to list start
__tx_timer_skip_wrap:
@
STR r0, [r1, #0] @ Store new current timer pointer
@ }
@
STR r0, [r1, #0] // Store new current timer pointer
// }
__tx_timer_done:
@
@
@ /* See if anything has expired. */
@ if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
@ {
@
LDR r3, =_tx_timer_expired_time_slice @ Pickup addr of expired flag
LDR r2, [r3, #0] @ Pickup time-slice expired flag
CMP r2, #0 @ Did a time-slice expire?
BNE __tx_something_expired @ If non-zero, time-slice expired
LDR r1, =_tx_timer_expired @ Pickup addr of other expired flag
LDR r0, [r1, #0] @ Pickup timer expired flag
CMP r0, #0 @ Did a timer expire?
BEQ __tx_timer_nothing_expired @ No, nothing expired
@
/* See if anything has expired. */
// if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
// {
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
LDR r2, [r3, #0] // Pickup time-slice expired flag
CBNZ r2, __tx_something_expired // Did a time-slice expire?
// If non-zero, time-slice expired
LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
LDR r0, [r1, #0] // Pickup timer expired flag
CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
// No, nothing expired
__tx_something_expired:
@
@
STMDB sp!, {r0, lr} @ Save the lr register on the stack
@ and save r0 just to keep 8-byte alignment
@
@ /* Did a timer expire? */
@ if (_tx_timer_expired)
@ {
@
LDR r1, =_tx_timer_expired @ Pickup addr of expired flag
LDR r0, [r1, #0] @ Pickup timer expired flag
CMP r0, #0 @ Check for timer expiration
BEQ __tx_timer_dont_activate @ If not set, skip timer activation
@
@ /* Process timer expiration. */
@ _tx_timer_expiration_process();
@
BL _tx_timer_expiration_process @ Call the timer expiration handling routine
@
@ }
STMDB sp!, {r0, lr} // Save the lr register on the stack
// and save r0 just to keep 8-byte alignment
/* Did a timer expire? */
// if (_tx_timer_expired)
// {
LDR r1, =_tx_timer_expired // Pickup addr of expired flag
LDR r0, [r1, #0] // Pickup timer expired flag
CBZ r0, __tx_timer_dont_activate // Check for timer expiration
// If not set, skip timer activation
/* Process timer expiration. */
// _tx_timer_expiration_process();
BL _tx_timer_expiration_process // Call the timer expiration handling routine
// }
__tx_timer_dont_activate:
@
@ /* Did time slice expire? */
@ if (_tx_timer_expired_time_slice)
@ {
@
LDR r3, =_tx_timer_expired_time_slice @ Pickup addr of time-slice expired
LDR r2, [r3, #0] @ Pickup the actual flag
CMP r2, #0 @ See if the flag is set
BEQ __tx_timer_not_ts_expiration @ No, skip time-slice processing
@
@ /* Time slice interrupted thread. */
@ _tx_thread_time_slice();
@
BL _tx_thread_time_slice @ Call time-slice processing
LDR r0, =_tx_thread_preempt_disable @ Build address of preempt disable flag
LDR r1, [r0] @ Is the preempt disable flag set?
CBNZ r1, __tx_timer_skip_time_slice @ Yes, skip the PendSV logic
LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address
LDR r1, [r0] @ Pickup the current thread pointer
LDR r2, =_tx_thread_execute_ptr @ Build execute thread pointer address
LDR r3, [r2] @ Pickup the execute thread pointer
LDR r0, =0xE000ED04 @ Build address of control register
LDR r2, =0x10000000 @ Build value for PendSV bit
CMP r1, r3 @ Are they the same?
BEQ __tx_timer_skip_time_slice @ If the same, there was no time-slice performed
STR r2, [r0] @ Not the same, issue the PendSV for preemption
/* Did time slice expire? */
// if (_tx_timer_expired_time_slice)
// {
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
LDR r2, [r3, #0] // Pickup the actual flag
CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
// No, skip time-slice processing
/* Time slice interrupted thread. */
// _tx_thread_time_slice();
BL _tx_thread_time_slice // Call time-slice processing
LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
LDR r1, [r0] // Is the preempt disable flag set?
CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
LDR r1, [r0] // Pickup the current thread pointer
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
LDR r3, [r2] // Pickup the execute thread pointer
LDR r0, =0xE000ED04 // Build address of control register
LDR r2, =0x10000000 // Build value for PendSV bit
CMP r1, r3 // Are they the same?
BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
STR r2, [r0] // Not the same, issue the PendSV for preemption
__tx_timer_skip_time_slice:
@
@ }
@
// }
__tx_timer_not_ts_expiration:
@
LDMIA sp!, {r0, lr} @ Recover lr register (r0 is just there for
@ the 8-byte stack alignment
@
@ }
@
LDMIA sp!, {r0, lr} // Recover lr register (r0 is just there for
// the 8-byte stack alignment
// }
__tx_timer_nothing_expired:
DSB @ Complete all memory access
BX lr @ Return to caller
@
@}
DSB // Complete all memory access
BX lr // Return to caller
// }

View File

@@ -26,11 +26,11 @@
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* tx_port.h Cortex-M4/GNU */
/* 6.1.6 */
/* 6.1.7 */
/* */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
@@ -43,16 +43,14 @@
/* own special types that can be mapped to actual data types by this */
/* file to guarantee consistency in the interface and functionality. */
/* */
/* This file replaces the previous Cortex-M3/M4/M7 files. It unifies */
/* the ARMv7-M architecture and compilers into one common file. */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
/* 09-30-2020 William E. Lamie Modified comment(s), */
/* resulting in version 6.1 */
/* 04-02-2021 Bhupendra Naphade Modified comment(s),updated */
/* macro definition, */
/* resulting in version 6.1.6 */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
@@ -64,7 +62,7 @@
#ifdef TX_INCLUDE_USER_DEFINE_FILE
/* Yes, include the user defines in tx_user.h. The defines in this file may
/* Yes, include the user defines in tx_user.h. The defines in this file may
alternately be defined on the command line. */
#include "tx_user.h"
@@ -76,6 +74,28 @@
#include <stdlib.h>
#include <string.h>
#ifdef __ICCARM__
#include <intrinsics.h> /* IAR Intrinsics */
#define __asm__ __asm /* Define to make all inline asm look similar */
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#include <yvals.h>
#endif
#endif /* __ICCARM__ */
#ifdef __ghs__
#include <arm_ghs.h>
#include "tx_ghs.h"
#endif /* __ghs__ */
#if !defined(__GNUC__) && !defined(__CC_ARM)
#define __get_control_value __get_CONTROL
#define __set_control_value __set_CONTROL
#endif
#ifndef __GNUC__
#define __get_ipsr_value __get_IPSR
#endif
/* Define ThreadX basic types for this port. */
@@ -86,9 +106,10 @@ typedef int INT;
typedef unsigned int UINT;
typedef long LONG;
typedef unsigned long ULONG;
typedef unsigned long long ULONG64;
typedef short SHORT;
typedef unsigned short USHORT;
#define ULONG64_DEFINED
/* Define the priority levels for ThreadX. Legal values range
from 32 to 1024 and MUST be evenly divisible by 32. */
@@ -113,19 +134,19 @@ typedef unsigned short USHORT;
#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
/* Define various constants for the ThreadX Cortex-M7 port. */
/* Define various constants for the ThreadX Cortex-M port. */
#define TX_INT_DISABLE 1 /* Disable interrupts */
#define TX_INT_ENABLE 0 /* Enable interrupts */
/* 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
/* 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
source constants would be:
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
@@ -133,46 +154,83 @@ typedef unsigned short USHORT;
*/
#ifndef TX_MISRA_ENABLE
#ifndef TX_TRACE_TIME_SOURCE
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
#endif
#else
ULONG _tx_misra_time_stamp_get(VOID);
#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
#endif
#ifndef TX_TRACE_TIME_MASK
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
#endif
#ifdef __ghs__
/* Define constants for Green Hills EventAnalyzer. */
/* Define the number of ticks per second. This informs the EventAnalyzer what the timestamps
represent. By default, this is set to 1,000,000 i.e., one tick every microsecond. */
#define TX_EL_TICKS_PER_SECOND 1000000
/* Define the method of how to get the upper and lower 32-bits of the time stamp. By default, simply
simulate the time-stamp source with a counter. */
#define read_tbu() _tx_el_time_base_upper
#define read_tbl() ++_tx_el_time_base_lower
#endif /* __ghs__ */
/* Define the port specific options for the _tx_build_options variable. This variable indicates
how the ThreadX library was built. */
#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
#define TX_PORT_SPECIFIC_BUILD_OPTIONS (0)
/* Define the in-line initialization constant so that modules with in-line
initialization capabilities can prevent their initialization from being
a function call. */
#ifdef TX_MISRA_ENABLE
#define TX_DISABLE_INLINE
#else
#define TX_INLINE_INITIALIZATION
#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
logic. */
#ifndef TX_MISRA_ENABLE
#ifdef TX_ENABLE_STACK_CHECKING
#undef TX_DISABLE_STACK_FILLING
#endif
#endif
/* 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
#define TX_THREAD_EXTENSION_1
#define TX_THREAD_EXTENSION_2
#define TX_THREAD_EXTENSION_3
#define TX_THREAD_EXTENSION_0
#define TX_THREAD_EXTENSION_1
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
#elif defined(__ghs__)
#define TX_THREAD_EXTENSION_2 VOID * tx_thread_eh_globals; \
int Errno; /* errno. */ \
char * strtok_saved_pos; /* strtok() position. */
#else
#define TX_THREAD_EXTENSION_2
#endif
#define TX_THREAD_EXTENSION_3
/* Define the port extensions of the remaining ThreadX objects. */
@@ -186,11 +244,11 @@ typedef unsigned short USHORT;
#define TX_TIMER_EXTENSION
/* 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
#define TX_THREAD_USER_EXTENSION
#define TX_THREAD_USER_EXTENSION
#endif
@@ -198,12 +256,28 @@ typedef unsigned short USHORT;
tx_thread_shell_entry, and tx_thread_terminate. */
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#if (__VER__ < 8000000)
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
#else
void *_tx_iar_create_per_thread_tls_area(void);
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
void __iar_Initlocks(void);
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
#endif
#else
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
#endif
#ifdef TX_ENABLE_FPU_SUPPORT
#if defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__TARGET_FPU_VFP) || defined(__VFP__)
#ifdef TX_MISRA_ENABLE
@@ -212,26 +286,49 @@ void _tx_misra_control_set(ULONG value);
ULONG _tx_misra_fpccr_get(void);
void _tx_misra_vfp_touch(void);
#else
#else /* TX_MISRA_ENABLE not defined */
__attribute__( ( always_inline ) ) static inline ULONG __get_control(void)
/* Define some helper functions (these are intrinsics in some compilers). */
#ifdef __GNUC__ /* GCC and ARM Compiler 6 */
__attribute__( ( always_inline ) ) static inline ULONG __get_control_value(void)
{
ULONG control_value;
__asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) );
return(control_value);
}
__attribute__( ( always_inline ) ) static inline void __set_control(ULONG control_value)
__attribute__( ( always_inline ) ) static inline void __set_control_value(ULONG control_value)
{
__asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" );
}
#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
#endif
#elif defined(__CC_ARM) /* ARM Compiler 5 */
__attribute__( ( always_inline ) ) ULONG __get_control_value(void)
{
ULONG control_value;
__asm volatile ("MRS control_value,CONTROL");
return(control_value);
}
__attribute__( ( always_inline ) ) void __set_control_value(ULONG control_value)
{
__asm__ volatile ("MSR CONTROL,control_value");
}
/* Can't access VFP registers with inline asm, so define this in tx_thread_schedule. */
void _tx_vfp_access(void);
#define TX_VFP_TOUCH() _tx_vfp_access();
#elif defined(__ICCARM__) /* IAR */
#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
#endif /* Helper functions for different compilers */
#endif /* TX_MISRA_ENABLE */
/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA
@@ -239,23 +336,22 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
#ifndef TX_MISRA_ENABLE
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control(_tx_vfp_state); \
}
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
}
#else
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
}
#endif
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
}
#endif
/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR.
If so, deactivate the FPU via CONTROL.FPCA. Otherwise we are in an interrupt or another thread is terminating
@@ -264,79 +360,76 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
#ifndef TX_MISRA_ENABLE
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = *((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 = _tx_vfp_state & ((ULONG) 0x4); \
__asm__ volatile ("vmov.f32 s0, s0"); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = __get_control(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control(_tx_vfp_state); \
} \
} \
} \
}
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = *((ULONG *) 0xE000EF34); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
TX_VFP_TOUCH(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
} \
} \
} \
}
#else
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = _tx_misra_fpccr_get(); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
_tx_misra_vfp_touch(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
} \
} \
}
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = _tx_misra_fpccr_get(); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
_tx_misra_vfp_touch(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
} \
} \
}
#endif
#else
#else /* No VFP in use */
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
#endif
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
#endif /* defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) */
/* Define the ThreadX object creation extensions for the remaining objects. */
@@ -361,126 +454,242 @@ __attribute__( ( always_inline ) ) static inline void __set_control(ULONG contro
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
/* Define the get system state macro. */
/* Define the get system state macro. */
#ifndef TX_THREAD_GET_SYSTEM_STATE
#ifndef TX_MISRA_ENABLE
#ifdef __CC_ARM /* ARM Compiler 5 */
register unsigned int _ipsr __asm("ipsr");
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _ipsr)
#elif defined(__GNUC__) /* GCC and ARM Compiler 6 */
__attribute__( ( always_inline ) ) static inline unsigned int __get_ipsr_value(void)
{
unsigned int ipsr_value;
__asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) );
return(ipsr_value);
}
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_ipsr_value())
#else
#elif defined(__ICCARM__) /* IAR */
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_IPSR())
#endif /* TX_THREAD_GET_SYSTEM_STATE for different compilers */
#else /* TX_MISRA_ENABLE is defined, use MISRA function. */
ULONG _tx_misra_ipsr_get(VOID);
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
#endif
#endif
#endif /* TX_MISRA_ENABLE */
#endif /* TX_THREAD_GET_SYSTEM_STATE */
/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
indicates that _tx_thread_system_return should not be called. */
indicates that _tx_thread_system_return should not be called. This overrides the definition in tx_thread.h
for Cortex-M since so we don't waste time checking the _tx_thread_system_state variable that is always
zero after initialization for Cortex-M ports. */
#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
#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++;
/* This 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
/* Define the TX_LOWEST_SET_BIT_CALCULATE macro for each compiler. */
#ifdef __ICCARM__ /* IAR Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __CLZ(__RBIT((m)));
#elif defined(__CC_ARM) /* AC5 Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __clz(__rbit((m)));
#elif defined(__GNUC__) /* GCC and AC6 Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \
__asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) );
#endif
#ifndef TX_DISABLE_INLINE
/* Define GNU specific macros, with in-line assembly for performance. */
/* Define the interrupt disable/restore macros for each compiler. */
#if defined(__GNUC__) || defined(__ICCARM__)
/*** GCC/AC6 and IAR ***/
__attribute__( ( always_inline ) ) static inline unsigned int __get_interrupt_posture(void)
{
unsigned int posture;
#ifdef TX_PORT_USE_BASEPRI
__asm__ volatile ("MRS %0, BASEPRI ": "=r" (posture));
#else
__asm__ volatile ("MRS %0, PRIMASK ": "=r" (posture));
#endif
return(posture);
}
#ifdef TX_PORT_USE_BASEPRI
__attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value)
{
__asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value));
}
#else
__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
{
__asm__ volatile ("CPSIE i": : : "memory");
}
#endif
__attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture)
{
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(int_posture);
//__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory");
#else
__asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory");
#endif
}
__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
{
unsigned int int_posture;
unsigned int primask_value;
int_posture = __get_interrupt_posture();
__asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
__asm__ volatile (" CPSID i" : : : "memory" );
return(primask_value);
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(TX_PORT_BASEPRI);
#else
__asm__ volatile ("CPSID i" : : : "memory");
#endif
return(int_posture);
}
__attribute__( ( always_inline ) ) static inline void __restore_interrupts(unsigned int primask_value)
{
__asm__ volatile (" MSR PRIMASK,%0": : "r" (primask_value): "memory" );
}
__attribute__( ( always_inline ) ) static inline unsigned int __get_primask_value(void)
{
unsigned int primask_value;
__asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
return(primask_value);
}
__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
{
__asm__ volatile (" CPSIE i": : : "memory" );
}
__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
{
unsigned int interrupt_save;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (__get_ipsr_value() == 0)
{
interrupt_save = __get_primask_value();
interrupt_save = __get_interrupt_posture();
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(0);
#else
__enable_interrupts();
__restore_interrupts(interrupt_save);
}
#endif
__restore_interrupt(interrupt_save);
}
}
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
#define TX_DISABLE interrupt_save = __disable_interrupts();
#define TX_RESTORE __restore_interrupt(interrupt_save);
/*** End GCC/AC6 and IAR ***/
#elif defined(__CC_ARM)
/*** AC5 ***/
static __inline unsigned int __get_interrupt_posture(void)
{
unsigned int posture;
#ifdef TX_PORT_USE_BASEPRI
__asm__ volatile ("MRS #posture, BASEPRI");
#else
__asm__ volatile ("MRS #posture, PRIMASK");
#endif
return(posture);
}
#ifdef TX_PORT_USE_BASEPRI
static __inline void __set_basepri_value(unsigned int basepri_value)
{
__asm__ volatile ("MSR BASEPRI, #basepri_value");
}
#endif
static __inline unsigned int __disable_interrupts(void)
{
unsigned int int_posture;
int_posture = __get_interrupt_posture();
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(TX_PORT_BASEPRI);
#else
__asm__ volatile ("CPSID i");
#endif
return(int_posture);
}
static __inline void __restore_interrupt(unsigned int int_posture)
{
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(int_posture);
#else
__asm__ volatile ("MSR PRIMASK, #int_posture");
#endif
}
static void _tx_thread_system_return_inline(void)
{
unsigned int interrupt_save;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (_ipsr == 0)
{
#ifdef TX_PORT_USE_BASEPRI
interrupt_save = __get_interrupt_posture();
__set_basepri_value(0);
__set_basepri_value(interrupt_save);
#else
interrupt_save = __disable_irq();
__enable_irq();
if (interrupt_save != 0)
__disable_irq();
#endif
}
}
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
#define TX_DISABLE interrupt_save = __disable_interrupts();
#define TX_RESTORE __restore_interrupt(interrupt_save);
#define TX_DISABLE interrupt_save = __disable_interrupts();
#define TX_RESTORE __restore_interrupts(interrupt_save);
/*** End AC5 ***/
#endif /* Interrupt disable/restore macros for each compiler. */
/* Redefine _tx_thread_system_return for improved performance. */
#define _tx_thread_system_return _tx_thread_system_return_inline
#else
#else /* TX_DISABLE_INLINE is defined */
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
UINT _tx_thread_interrupt_disable(VOID);
VOID _tx_thread_interrupt_restore(UINT previous_posture);
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
#endif
#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
#endif /* TX_DISABLE_INLINE */
/* Define FPU extension for the Cortex-M4. Each is assumed to be called in the context of the executing
thread. This is for legacy only, and not needed anylonger. */
/* Define FPU extension for the Cortex-M. 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);
@@ -489,16 +698,15 @@ void tx_thread_fpu_disable(void);
/* 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-M4/GNU Version 6.1.6 *";
CHAR _tx_version_id[] =
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M4/GNU Version 6.1.7 *";
#else
#ifdef TX_MISRA_ENABLE
extern CHAR _tx_version_id[100];
#else
extern CHAR _tx_version_id[];
#endif
#endif
#endif

View File

@@ -1,12 +1,13 @@
Microsoft's Azure RTOS ThreadX for Cortex-M4
Microsoft's Azure RTOS ThreadX for ARMv7-M
(Cortex-M3, Cortex-M4, Cortex-M7)
Using the GNU Tools
1. Building the ThreadX run-time Library
First make sure you are in the "example_build" directory. Also, make sure that
Navigate to the "example_build" directory. Ensure that
you have setup your path and other environment variables necessary for the ARM
gnu (GNU) compiler. At this point you may run the build_threadx.bat batch file.
GNU compiler. At this point you may run the build_threadx.bat batch file.
This will build the ThreadX run-time environment in the "example_build"
directory.
@@ -16,13 +17,13 @@ run-time library file: tx.a. This file must be linked with your
application in order to use ThreadX.
2. Demonstration System for Cortex-M4
2. Demonstration System
The ThreadX demonstration is designed to execute on Cortex-M4 evaluation boards
The ThreadX demonstration is designed to execute on Cortex-M evaluation boards
or on a dedicated simulator.
Building the demonstration is easy, simply execute the build_threadx_sample.bat
batch file while inside the "example_build" directory.
batch file while inside the "example_build" directory.
You should observe the compilation of sample_threadx.c (which is the demonstration
application) and linking with tx.a. The resulting file sample_threadx.out is a binary
@@ -31,8 +32,8 @@ file that can be downloaded and executed on the a simulator, or downloaded to a
3. System Initialization
The entry point in ThreadX for the Cortex-M4 using gnu tools uses the standard GNU
Cortex-M4 reset sequence. From the reset vector the C runtime will be initialized.
The entry point in ThreadX for the Cortex-M using gnu tools uses the standard GNU
Cortex-M reset sequence. From the reset vector the C runtime will be initialized.
The ThreadX tx_initialize_low_level.S file is responsible for setting up
various system data structures, the vector area, and a periodic timer interrupt
@@ -47,7 +48,7 @@ parameter to your application definition function, tx_application_define.
The following defines the saved context stack frames for context switches
that occur as a result of interrupt handling or from thread-level API calls.
All suspended threads have the same stack frame in the Cortex-M4 version of
All suspended threads have the same stack frame in the Cortex-M version of
ThreadX. The top of the suspended thread's stack is pointed to by
tx_thread_stack_ptr in the associated thread control block TX_THREAD.
@@ -55,7 +56,7 @@ Non-FPU Stack Frame:
Stack Offset Stack Contents
0x00 LR Interrupted LR (LR at time of PENDSV)
0x00 lr Interrupted lr (lr at time of PENDSV)
0x04 r4 Software stacked GP registers
0x08 r5
0x0C r6
@@ -77,7 +78,7 @@ FPU Stack Frame (only interrupted thread with FPU enabled):
Stack Offset Stack Contents
0x00 LR Interrupted LR (LR at time of PENDSV)
0x00 lr Interrupted lr (lr at time of PENDSV)
0x04 s16 Software stacked FPU registers
0x08 s17
0x0C s18
@@ -144,42 +145,32 @@ defined.
6. Interrupt Handling
ThreadX provides complete and high-performance interrupt handling for Cortex-M4
ThreadX provides complete and high-performance interrupt handling for Cortex-M
targets. There are a certain set of requirements that are defined in the
following sub-sections:
6.1 Vector Area
The Cortex-M4 vectors start at the label __tx_vectors or similar. The application may modify
The Cortex-M vectors start at the label __tx_vectors or similar. The application may modify
the vector area according to its needs. There is code in tx_initialize_low_level() that will
configure the vector base register.
6.2 Managed Interrupts
ISRs can be written completely in C (or assembly language) without any calls to
_tx_thread_context_save or _tx_thread_context_restore. These ISRs are allowed access to the
ThreadX API that is available to ISRs.
ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table):
void your_C_isr(void)
{
/* ISR processing goes here, including any needed function calls. */
}
ISRs written in assembly language will take the form:
A ThreadX managed interrupt is defined below. By following these conventions, the
application ISR is then allowed access to various ThreadX services from the ISR.
Here is the standard template for managed ISRs in ThreadX:
.global your_assembly_isr
.global __tx_IntHandler
.thumb_func
your_assembly_isr:
; VOID your_assembly_isr(VOID)
__tx_IntHandler:
; VOID InterruptHandler (VOID)
; {
PUSH {r0, lr}
;
; /* Do interrupt handler work here */
; /* BL <your interrupt routine in C> */
@@ -187,7 +178,8 @@ your_assembly_isr:
BX lr
; }
Note: the Cortex-M4 requires exception handlers to be thumb labels, this implies bit 0 set.
Note: the Cortex-M requires exception handlers to be thumb labels, this implies bit 0 set.
To accomplish this, the declaration of the label has to be preceded by the assembler directive
.thumb_func to instruct the linker to create thumb labels. The label __tx_IntHandler needs to
be inserted in the correct location in the interrupt vector table. This table is typically
@@ -196,10 +188,9 @@ located in either your runtime startup file or in the tx_initialize_low_level.S
7. FPU Support
ThreadX for Cortex-M4 supports automatic ("lazy") VFP support, which means that applications threads
ThreadX for Cortex-M supports automatic ("lazy") VFP support, which means that applications threads
can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread
context. If saving the context of the FPU registers is needed, the ThreadX library should be re-built
with TX_ENABLE_FPU_SUPPORT defined.
context - no additional setup by the application.
8. Revision History
@@ -208,21 +199,10 @@ For generic code revision information, please refer to the readme_threadx_generi
file, which is included in your distribution. The following details the revision
information associated with this specific port of ThreadX:
04-02-2021 Release 6.1.6 changes:
tx_port.h Updated macro definition
03-02-2021 The following files were changed/added for version 6.1.5:
tx_thread_schedule.s Added low power feature
09-30-2020 ThreadX update of Cortex-M4/GNU port. The following files were
changed/added for port specific version 6.1:
*.S Modified comments and whitespace.
05/19/2020 Initial ThreadX 6.0 version for Cortex-M4 using GNU tools.
06-02-2021 Initial ThreadX version 6.1.7 for Cortex-M using GNU tools.
Copyright(c) 1996-2020 Microsoft Corporation
Copyright(c) 1996-2021 Microsoft Corporation
https://azure.com/rtos

View File

@@ -1,89 +1,81 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
@
@
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Thread */
@/** */
@/**************************************************************************/
@/**************************************************************************/
@
@
.global _tx_thread_system_state
.global _tx_thread_current_ptr
.global _tx_thread_system_stack_ptr
.global _tx_thread_execute_ptr
.global _tx_timer_time_slice
.global _tx_thread_schedule
.global _tx_thread_preempt_disable
.global _tx_execution_isr_exit
@
@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
.global _tx_execution_isr_exit
#endif
.text
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_thread_context_restore Cortex-M4/GNU */
@/* 6.1 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function is only needed for legacy applications and it should */
@/* not be called in any new development on a Cortex-M. */
@/* This function restores the interrupt context if it is processing a */
@/* nested interrupt. If not, it returns to the interrupt thread if no */
@/* preemption is necessary. Otherwise, if preemption is necessary or */
@/* if no thread was running, the function returns to the scheduler. */
@/* */
@/* INPUT */
@/* */
@/* None */
@/* */
@/* OUTPUT */
@/* */
@/* None */
@/* */
@/* CALLS */
@/* */
@/* _tx_thread_schedule Thread scheduling routine */
@/* */
@/* CALLED BY */
@/* */
@/* ISRs Interrupt Service Routines */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
@/* 09-30-2020 William E. Lamie Modified comment(s), */
@/* resulting in version 6.1 */
@/* */
@/**************************************************************************/
@VOID _tx_thread_context_restore(VOID)
@{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_context_restore Cortex-M4/GNU */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is only needed for legacy applications and it should */
/* not be called in any new development on a Cortex-M. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* [_tx_execution_isr_exit] Execution profiling ISR exit */
/* */
/* CALLED BY */
/* */
/* ISRs Interrupt Service Routines */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_context_restore(VOID)
// {
.global _tx_thread_context_restore
.thumb_func
_tx_thread_context_restore:
@
@ /* Not needed for this port - just return! */
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the ISR exit function to indicate an ISR is complete. */
PUSH {r0, lr} // Save return address
BL _tx_execution_isr_exit // Call the ISR exit function
POP {r0, lr} // Recover return address
#endif
BX lr
@}
// }

View File

@@ -1,84 +1,80 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
@
@
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Thread */
@/** */
@/**************************************************************************/
@/**************************************************************************/
@
@
.global _tx_thread_system_state
.global _tx_thread_current_ptr
.global _tx_execution_isr_enter
@
@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.text
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_thread_context_save Cortex-M4/GNU */
@/* 6.1 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function is only needed for legacy applications and it should */
@/* not be called in any new development on a Cortex-M. */
@/* This function saves the context of an executing thread in the */
@/* beginning of interrupt processing. The function also ensures that */
@/* the system stack is used upon return to the calling ISR. */
@/* */
@/* INPUT */
@/* */
@/* None */
@/* */
@/* OUTPUT */
@/* */
@/* None */
@/* */
@/* CALLS */
@/* */
@/* None */
@/* */
@/* CALLED BY */
@/* */
@/* ISRs */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
@/* 09-30-2020 Scott Larson Modified comment(s), and */
@/* cleaned up whitespace, */
@/* resulting in version 6.1 */
@/* */
@/**************************************************************************/
@VOID _tx_thread_context_save(VOID)
@{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_context_save Cortex-M4/GNU */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is only needed for legacy applications and it should */
/* not be called in any new development on a Cortex-M. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* [_tx_execution_isr_enter] Execution profiling ISR enter */
/* */
/* CALLED BY */
/* */
/* ISRs */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_context_save(VOID)
// {
.global _tx_thread_context_save
.thumb_func
_tx_thread_context_save:
@
@ /* Not needed for this port - just return! */
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the ISR enter function to indicate an ISR is starting. */
PUSH {r0, lr} // Save return address
BL _tx_execution_isr_enter // Call the ISR enter function
POP {r0, lr} // Recover return address
#endif
/* Context is already saved - just return. */
BX lr
@}
// }

View File

@@ -1,83 +1,79 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Thread */
@/** */
@/**************************************************************************/
@/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.text 32
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_thread_interrupt_control Cortex-M4/GNU */
@/* 6.1 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function is responsible for changing the interrupt lockout */
@/* posture of the system. */
@/* */
@/* INPUT */
@/* */
@/* new_posture New interrupt lockout posture */
@/* */
@/* OUTPUT */
@/* */
@/* old_posture Old interrupt lockout posture */
@/* */
@/* CALLS */
@/* */
@/* None */
@/* */
@/* CALLED BY */
@/* */
@/* Application Code */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
@/* 09-30-2020 William E. Lamie Modified comment(s), */
@/* resulting in version 6.1 */
@/* */
@/**************************************************************************/
@/* UINT _tx_thread_interrupt_control(UINT new_posture)
{ */
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_control Cortex-M4/GNU */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for changing the interrupt lockout */
/* posture of the system. */
/* */
/* INPUT */
/* */
/* new_posture New interrupt lockout posture */
/* */
/* OUTPUT */
/* */
/* old_posture Old interrupt lockout posture */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// UINT _tx_thread_interrupt_control(UINT new_posture)
// {
.global _tx_thread_interrupt_control
.thumb_func
_tx_thread_interrupt_control:
@/* Pickup current interrupt lockout posture. */
MRS r1, PRIMASK @ Pickup current interrupt lockout
@/* Apply the new interrupt posture. */
MSR PRIMASK, r0 @ Apply the new interrupt lockout
MOV r0, r1 @ Transfer old to return register
BX lr @ Return to caller
@/* } */
#ifdef TX_PORT_USE_BASEPRI
MRS r1, BASEPRI // Pickup current interrupt posture
MSR BASEPRI, r0 // Apply the new interrupt posture
MOV r0, r1 // Transfer old to return register
#else
MRS r1, PRIMASK // Pickup current interrupt lockout
MSR PRIMASK, r0 // Apply the new interrupt lockout
MOV r0, r1 // Transfer old to return register
#endif
BX lr // Return to caller
// }

View File

@@ -0,0 +1,79 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.text 32
.align 4
.syntax unified
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_disable Cortex-M4/GNU */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for disabling interrupts and returning */
/* the previous interrupt lockout posture. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* old_posture Old interrupt lockout posture */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// UINT _tx_thread_interrupt_disable(VOID)
// {
.global _tx_thread_interrupt_disable
.thumb_func
_tx_thread_interrupt_disable:
/* Return current interrupt lockout posture. */
#ifdef TX_PORT_USE_BASEPRI
MRS r0, BASEPRI
LDR r1, =TX_PORT_BASEPRI
MSR BASEPRI, r1
#else
MRS r0, PRIMASK
CPSID i
#endif
BX lr
// }

View File

@@ -0,0 +1,76 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.text 32
.align 4
.syntax unified
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_restore Cortex-M4/GNU */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for restoring the previous */
/* interrupt lockout posture. */
/* */
/* INPUT */
/* */
/* previous_posture Previous interrupt posture */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_interrupt_restore(UINT previous_posture)
// {
.global _tx_thread_interrupt_restore
.thumb_func
_tx_thread_interrupt_restore:
/* Restore previous interrupt lockout posture. */
#ifdef TX_PORT_USE_BASEPRI
MSR BASEPRI, r0
#else
MSR PRIMASK, r0
#endif
BX lr
// }

View File

@@ -1,307 +1,284 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
@
@
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Thread */
@/** */
@/**************************************************************************/
@/**************************************************************************/
@
@
.global _tx_thread_current_ptr
.global _tx_thread_execute_ptr
.global _tx_timer_time_slice
.global _tx_thread_system_stack_ptr
.global _tx_execution_thread_enter
.global _tx_execution_thread_exit
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.global _tx_thread_current_ptr
.global _tx_thread_execute_ptr
.global _tx_timer_time_slice
.global _tx_execution_thread_enter
.global _tx_execution_thread_exit
#ifdef TX_LOW_POWER
.global tx_low_power_enter
.global tx_low_power_exit
#endif
@
@
.text
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_thread_schedule Cortex-M4/GNU */
@/* 6.1.5 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function waits for a thread control block pointer to appear in */
@/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
@/* in the variable, the corresponding thread is resumed. */
@/* */
@/* INPUT */
@/* */
@/* None */
@/* */
@/* OUTPUT */
@/* */
@/* None */
@/* */
@/* CALLS */
@/* */
@/* None */
@/* */
@/* CALLED BY */
@/* */
@/* _tx_initialize_kernel_enter ThreadX entry function */
@/* _tx_thread_system_return Return to system from thread */
@/* _tx_thread_context_restore Restore thread's context */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
@/* 09-30-2020 William E. Lamie Modified comment(s), */
@/* resulting in version 6.1 */
@/* 03-02-2021 Scott Larson Modified comment(s), add */
@/* low power code, */
@/* resulting in version 6.1.5 */
@/* */
@/**************************************************************************/
@VOID _tx_thread_schedule(VOID)
@{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_schedule Cortex-M4/GNU */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function waits for a thread control block pointer to appear in */
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
/* in the variable, the corresponding thread is resumed. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_initialize_kernel_enter ThreadX entry function */
/* _tx_thread_system_return Return to system from thread */
/* _tx_thread_context_restore Restore thread's context */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_schedule(VOID)
// {
.global _tx_thread_schedule
.thumb_func
_tx_thread_schedule:
@
@ /* This function should only ever be called on Cortex-M4
@ from the first schedule request. Subsequent scheduling occurs
@ from the PendSV handling routines below. */
@
@ /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
@
MOV r0, #0 @ Build value for TX_FALSE
LDR r2, =_tx_thread_preempt_disable @ Build address of preempt disable flag
STR r0, [r2, #0] @ Clear preempt disable flag
@
@ /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
@
#ifdef TX_ENABLE_FPU_SUPPORT
MRS r0, CONTROL @ Pickup current CONTROL register
BIC r0, r0, #4 @ Clear the FPCA bit
MSR CONTROL, r0 @ Setup new CONTROL register
/* This function should only ever be called on Cortex-M
from the first schedule request. Subsequent scheduling occurs
from the PendSV handling routine below. */
/* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
MOV r0, #0 // Build value for TX_FALSE
LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
STR r0, [r2, #0] // Clear preempt disable flag
/* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
#ifdef __ARM_PCS_VFP
MRS r0, CONTROL // Pickup current CONTROL register
BIC r0, r0, #4 // Clear the FPCA bit
MSR CONTROL, r0 // Setup new CONTROL register
#endif
@
@ /* Enable interrupts */
@
/* Enable interrupts */
CPSIE i
@
@ /* Enter the scheduler for the first time. */
@
MOV r0, #0x10000000 @ Load PENDSVSET bit
MOV r1, #0xE000E000 @ Load NVIC base
STR r0, [r1, #0xD04] @ Set PENDSVBIT in ICSR
DSB @ Complete all memory accesses
ISB @ Flush pipeline
@
@ /* Wait here for the PendSV to take place. */
@
/* Enter the scheduler for the first time. */
MOV r0, #0x10000000 // Load PENDSVSET bit
MOV r1, #0xE000E000 // Load NVIC base
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
DSB // Complete all memory accesses
ISB // Flush pipeline
/* Wait here for the PendSV to take place. */
__tx_wait_here:
B __tx_wait_here @ Wait for the PendSV to happen
@}
@
@ /* Generic context switch-out switch-in handler... Note that this handler is
@ common for both PendSV and SVCall. */
@
B __tx_wait_here // Wait for the PendSV to happen
// }
/* Generic context switching PendSV handler. */
.global PendSV_Handler
.global __tx_PendSVHandler
.syntax unified
.thumb_func
PendSV_Handler:
.thumb_func
__tx_PendSVHandler:
@
@ /* Get current thread value and new thread pointer. */
@
/* Get current thread value and new thread pointer. */
__tx_ts_handler:
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
@
@ /* Call the thread exit function to indicate the thread is no longer executing. */
@
CPSID i @ Disable interrupts
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
CPSIE i @ Enable interrupts
#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
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
CPSIE i // Enable interrupts
#endif
LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address
LDR r2, =_tx_thread_execute_ptr @ Build execute thread pointer address
MOV r3, #0 @ Build NULL value
LDR r1, [r0] @ Pickup current thread pointer
@
@ /* Determine if there is a current thread to finish preserving. */
@
CBZ r1, __tx_ts_new @ If NULL, skip preservation
@
@ /* Recover PSP and preserve current thread context. */
@
STR r3, [r0] @ Set _tx_thread_current_ptr to NULL
MRS r12, PSP @ Pickup PSP pointer (thread's stack pointer)
STMDB r12!, {r4-r11} @ Save its remaining registers
#ifdef TX_ENABLE_FPU_SUPPORT
TST LR, #0x10 @ Determine if the VFP extended frame is present
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
MOV r3, #0 // Build NULL value
LDR r1, [r0] // Pickup current thread pointer
/* Determine if there is a current thread to finish preserving. */
CBZ r1, __tx_ts_new // If NULL, skip preservation
/* Recover PSP and preserve current thread context. */
STR r3, [r0] // Set _tx_thread_current_ptr to NULL
MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
STMDB r12!, {r4-r11} // Save its remaining registers
#ifdef __ARM_PCS_VFP
TST LR, #0x10 // Determine if the VFP extended frame is present
BNE _skip_vfp_save
VSTMDB r12!,{s16-s31} @ Yes, save additional VFP registers
VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
_skip_vfp_save:
#endif
LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
STMDB r12!, {LR} @ Save LR on the stack
@
@ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
@
LDR r5, [r4] @ Pickup current time-slice
STR r12, [r1, #8] @ Save the thread stack pointer
CBZ r5, __tx_ts_new @ If not active, skip processing
@
@ /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
@
STR r5, [r1, #24] @ Save current time-slice
@
@ /* Clear the global time-slice. */
@
STR r3, [r4] @ Clear time-slice
@
@
@ /* Executing thread is now completely preserved!!! */
@
__tx_ts_new:
@
@ /* Now we are looking for a new thread to execute! */
@
CPSID i @ Disable interrupts
LDR r1, [r2] @ Is there another thread ready to execute?
CBZ r1, __tx_ts_wait @ No, skip to the wait processing
@
@ /* Yes, another thread is ready for else, make the current thread the new thread. */
@
STR r1, [r0] @ Setup the current thread pointer to the new thread
CPSIE i @ Enable interrupts
@
@ /* Increment the thread run count. */
@
__tx_ts_restore:
LDR r7, [r1, #4] @ Pickup the current thread run count
LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
LDR r5, [r1, #24] @ Pickup thread's current time-slice
ADD r7, r7, #1 @ Increment the thread run count
STR r7, [r1, #4] @ Store the new run count
@
@ /* Setup global time-slice with thread's current time-slice. */
@
STR r5, [r4] @ Setup global time-slice
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
STMDB r12!, {LR} // Save LR on the stack
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
@
@ /* Call the thread entry function to indicate the thread is executing. */
@
PUSH {r0, r1} @ Save r0/r1
BL _tx_execution_thread_enter @ Call the thread execution enter function
POP {r0, r1} @ Recover r3
/* Determine if time-slice is active. If it isn't, skip time handling processing. */
LDR r5, [r4] // Pickup current time-slice
STR r12, [r1, #8] // Save the thread stack pointer
CBZ r5, __tx_ts_new // If not active, skip processing
/* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
STR r5, [r1, #24] // Save current time-slice
/* Clear the global time-slice. */
STR r3, [r4] // Clear time-slice
/* Executing thread is now completely preserved!!! */
__tx_ts_new:
/* Now we are looking for a new thread to execute! */
CPSID i // Disable interrupts
LDR r1, [r2] // Is there another thread ready to execute?
CBZ r1, __tx_ts_wait // No, skip to the wait processing
/* Yes, another thread is ready for else, make the current thread the new thread. */
STR r1, [r0] // Setup the current thread pointer to the new thread
CPSIE i // Enable interrupts
/* Increment the thread run count. */
__tx_ts_restore:
LDR r7, [r1, #4] // Pickup the current thread run count
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
LDR r5, [r1, #24] // Pickup thread's current time-slice
ADD r7, r7, #1 // Increment the thread run count
STR r7, [r1, #4] // Store the new run count
/* Setup global time-slice with thread's current time-slice. */
STR r5, [r4] // Setup global time-slice
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the thread entry function to indicate the thread is executing. */
PUSH {r0, r1} // Save r0 and r1
BL _tx_execution_thread_enter // Call the thread execution enter function
POP {r0, r1} // Recover r0 and r1
#endif
@
@ /* Restore the thread context and PSP. */
@
LDR r12, [r1, #8] @ Pickup thread's stack pointer
LDMIA r12!, {LR} @ Pickup LR
#ifdef TX_ENABLE_FPU_SUPPORT
TST LR, #0x10 @ Determine if the VFP extended frame is present
BNE _skip_vfp_restore @ If not, skip VFP restore
VLDMIA r12!, {s16-s31} @ Yes, restore additional VFP registers
/* Restore the thread context and PSP. */
LDR r12, [r1, #8] // Pickup thread's stack pointer
LDMIA r12!, {LR} // Pickup LR
#ifdef __ARM_PCS_VFP
TST LR, #0x10 // Determine if the VFP extended frame is present
BNE _skip_vfp_restore // If not, skip VFP restore
VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
_skip_vfp_restore:
#endif
LDMIA r12!, {r4-r11} @ Recover thread's registers
MSR PSP, r12 @ Setup the thread's stack pointer
@
@ /* Return to thread. */
@
BX lr @ Return to thread!
@
@ /* The following is the idle wait processing... in this case, no threads are ready for execution and the
@ system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
@ are disabled to allow use of WFI for waiting for a thread to arrive. */
@
LDMIA r12!, {r4-r11} // Recover thread's registers
MSR PSP, r12 // Setup the thread's stack pointer
/* Return to thread. */
BX lr // Return to thread!
/* The following is the idle wait processing... in this case, no threads are ready for execution and the
system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
are disabled to allow use of WFI for waiting for a thread to arrive. */
__tx_ts_wait:
CPSID i @ Disable interrupts
LDR r1, [r2] @ Pickup the next thread to execute pointer
STR r1, [r0] @ Store it in the current pointer
CBNZ r1, __tx_ts_ready @ If non-NULL, a new thread is ready!
CPSID i // Disable interrupts
LDR r1, [r2] // Pickup the next thread to execute pointer
STR r1, [r0] // Store it in the current pointer
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
#ifdef TX_LOW_POWER
PUSH {r0-r3}
BL tx_low_power_enter @ Possibly enter low power mode
POP {r0-r3}
BL tx_low_power_enter // Possibly enter low power mode
#endif
#ifdef TX_ENABLE_WFI
DSB @ Ensure no outstanding memory transactions
WFI @ Wait for interrupt
ISB @ Ensure pipeline is flushed
DSB // Ensure no outstanding memory transactions
WFI // Wait for interrupt
ISB // Ensure pipeline is flushed
#endif
#ifdef TX_LOW_POWER
PUSH {r0-r3}
BL tx_low_power_exit @ Exit low power mode
POP {r0-r3}
BL tx_low_power_exit // Exit low power mode
#endif
CPSIE i @ Enable interrupts
B __tx_ts_wait @ Loop to continue waiting
@
@ /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
@ already in the handler! */
@
CPSIE i // Enable interrupts
B __tx_ts_wait // Loop to continue waiting
/* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
already in the handler! */
__tx_ts_ready:
MOV r7, #0x08000000 @ Build clear PendSV value
MOV r8, #0xE000E000 @ Build base NVIC address
STR r7, [r8, #0xD04] @ Clear any PendSV
@
@ /* Re-enable interrupts and restore new thread. */
@
CPSIE i @ Enable interrupts
B __tx_ts_restore @ Restore the thread
MOV r7, #0x08000000 // Build clear PendSV value
MOV r8, #0xE000E000 // Build base NVIC address
STR r7, [r8, #0xD04] // Clear any PendSV
#ifdef TX_ENABLE_FPU_SUPPORT
/* Re-enable interrupts and restore new thread. */
.global tx_thread_fpu_enable
.thumb_func
CPSIE i // Enable interrupts
B __tx_ts_restore // Restore the thread
// }
#ifdef __ARM_PCS_VFP
.global tx_thread_fpu_enable
.thumb_func
tx_thread_fpu_enable:
@
@ /* Automatic VPF logic is supported, this function is present only for
@ backward compatibility purposes and therefore simply returns. */
@
BX LR @ Return to caller
.global tx_thread_fpu_disable
.thumb_func
.global tx_thread_fpu_disable
.thumb_func
tx_thread_fpu_disable:
@
@ /* Automatic VPF logic is supported, this function is present only for
@ backward compatibility purposes and therefore simply returns. */
@
BX LR @ Return to caller
/* Automatic VPF logic is supported, this function is present only for
backward compatibility purposes and therefore simply returns. */
BX LR // Return to caller
#endif

View File

@@ -1,141 +1,133 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
@
@
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Thread */
@/** */
@/**************************************************************************/
@/**************************************************************************/
@
@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.text
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_thread_stack_build Cortex-M4/GNU */
@/* 6.1 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function builds a stack frame on the supplied thread's stack. */
@/* The stack frame results in a fake interrupt return to the supplied */
@/* function pointer. */
@/* */
@/* INPUT */
@/* */
@/* thread_ptr Pointer to thread control blk */
@/* function_ptr Pointer to return function */
@/* */
@/* OUTPUT */
@/* */
@/* None */
@/* */
@/* CALLS */
@/* */
@/* None */
@/* */
@/* CALLED BY */
@/* */
@/* _tx_thread_create Create thread service */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
@/* 09-30-2020 William E. Lamie Modified Comment(s), setting */
@/* R10 to top of stack is not */
@/* needed. Removed references */
@/* to stack frame, clean up */
@/* whitespace, resulting */
@/* in version 6.1 */
@/* */
@/**************************************************************************/
@VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
@{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_stack_build Cortex-M4/GNU */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function builds a stack frame on the supplied thread's stack. */
/* The stack frame results in a fake interrupt return to the supplied */
/* function pointer. */
/* */
/* INPUT */
/* */
/* thread_ptr Pointer to thread control blk */
/* function_ptr Pointer to return function */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_thread_create Create thread service */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
// {
.global _tx_thread_stack_build
.thumb_func
_tx_thread_stack_build:
@
@
@ /* Build a fake interrupt frame. The form of the fake interrupt stack
@ on the Cortex-M4 should look like the following after it is built:
@
@ Stack Top:
@ LR Interrupted LR (LR at time of PENDSV)
@ r4 Initial value for r4
@ r5 Initial value for r5
@ r6 Initial value for r6
@ r7 Initial value for r7
@ r8 Initial value for r8
@ r9 Initial value for r9
@ r10 Initial value for r10
@ r11 Initial value for r11
@ r0 Initial value for r0 (Hardware stack starts here!!)
@ r1 Initial value for r1
@ r2 Initial value for r2
@ r3 Initial value for r3
@ r12 Initial value for r12
@ lr Initial value for lr
@ pc Initial value for pc
@ xPSR Initial value for xPSR
@
@ Stack Bottom: (higher memory address) */
@
LDR r2, [r0, #16] @ Pickup end of stack area
BIC r2, r2, #0x7 @ Align frame
SUB r2, r2, #68 @ Subtract frame size
LDR r3, =0xFFFFFFFD @ Build initial LR value
STR r3, [r2, #0] @ Save on the stack
@
@ /* Actually build the stack frame. */
@
MOV r3, #0 @ Build initial register value
STR r3, [r2, #4] @ Store initial r4
STR r3, [r2, #8] @ Store initial r5
STR r3, [r2, #12] @ Store initial r6
STR r3, [r2, #16] @ Store initial r7
STR r3, [r2, #20] @ Store initial r8
STR r3, [r2, #24] @ Store initial r9
STR r3, [r2, #28] @ Store initial r10
STR r3, [r2, #32] @ Store initial r11
@
@ /* Hardware stack follows. */
@
STR r3, [r2, #36] @ Store initial r0
STR r3, [r2, #40] @ Store initial r1
STR r3, [r2, #44] @ Store initial r2
STR r3, [r2, #48] @ Store initial r3
STR r3, [r2, #52] @ Store initial r12
MOV r3, #0xFFFFFFFF @ Poison EXC_RETURN value
STR r3, [r2, #56] @ Store initial lr
STR r1, [r2, #60] @ Store initial pc
MOV r3, #0x01000000 @ Only T-bit need be set
STR r3, [r2, #64] @ Store initial xPSR
@
@ /* Setup stack pointer. */
@ thread_ptr -> tx_thread_stack_ptr = r2;
@
STR r2, [r0, #8] @ Save stack pointer in thread's
@ control block
BX lr @ Return to caller
@}
/* Build a fake interrupt frame. The form of the fake interrupt stack
on the Cortex-M should look like the following after it is built:
Stack Top:
LR Interrupted LR (LR at time of PENDSV)
r4 Initial value for r4
r5 Initial value for r5
r6 Initial value for r6
r7 Initial value for r7
r8 Initial value for r8
r9 Initial value for r9
r10 Initial value for r10
r11 Initial value for r11
r0 Initial value for r0 (Hardware stack starts here!!)
r1 Initial value for r1
r2 Initial value for r2
r3 Initial value for r3
r12 Initial value for r12
lr Initial value for lr
pc Initial value for pc
xPSR Initial value for xPSR
Stack Bottom: (higher memory address) */
LDR r2, [r0, #16] // Pickup end of stack area
BIC r2, r2, #0x7 // Align frame for 8-byte alignment
SUB r2, r2, #68 // Subtract frame size
LDR r3, =0xFFFFFFFD // Build initial LR value
STR r3, [r2, #0] // Save on the stack
/* Actually build the stack frame. */
MOV r3, #0 // Build initial register value
STR r3, [r2, #4] // Store initial r4
STR r3, [r2, #8] // Store initial r5
STR r3, [r2, #12] // Store initial r6
STR r3, [r2, #16] // Store initial r7
STR r3, [r2, #20] // Store initial r8
STR r3, [r2, #24] // Store initial r9
STR r3, [r2, #28] // Store initial r10
STR r3, [r2, #32] // Store initial r11
/* Hardware stack follows. */
STR r3, [r2, #36] // Store initial r0
STR r3, [r2, #40] // Store initial r1
STR r3, [r2, #44] // Store initial r2
STR r3, [r2, #48] // Store initial r3
STR r3, [r2, #52] // Store initial r12
MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
STR r3, [r2, #56] // Store initial lr
STR r1, [r2, #60] // Store initial pc
MOV r3, #0x01000000 // Only T-bit need be set
STR r3, [r2, #64] // Store initial xPSR
/* Setup stack pointer. */
// thread_ptr -> tx_thread_stack_ptr = r2;
STR r2, [r0, #8] // Save stack pointer in thread's
// control block
BX lr // Return to caller
// }

View File

@@ -1,90 +1,93 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
@
@
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Thread */
@/** */
@/**************************************************************************/
@/**************************************************************************/
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
.text 32
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_thread_system_return Cortex-M4/GNU */
@/* 6.1 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function is target processor specific. It is used to transfer */
@/* control from a thread back to the ThreadX system. Only a */
@/* minimal context is saved since the compiler assumes temp registers */
@/* are going to get slicked by a function call anyway. */
@/* */
@/* INPUT */
@/* */
@/* None */
@/* */
@/* OUTPUT */
@/* */
@/* None */
@/* */
@/* CALLS */
@/* */
@/* _tx_thread_schedule Thread scheduling loop */
@/* */
@/* CALLED BY */
@/* */
@/* ThreadX components */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
@/* 09-30-2020 William E. Lamie Modified comment(s), */
@/* resulting in version 6.1 */
@/* */
@/**************************************************************************/
@/* VOID _tx_thread_system_return(VOID)
@{ */
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_system_return Cortex-M4/GNU */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is target processor specific. It is used to transfer */
/* control from a thread back to the ThreadX system. Only a */
/* minimal context is saved since the compiler assumes temp registers */
/* are going to get slicked by a function call anyway. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _tx_thread_schedule Thread scheduling loop */
/* */
/* CALLED BY */
/* */
/* ThreadX components */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_system_return(VOID)
// {
.thumb_func
.global _tx_thread_system_return
_tx_thread_system_return:
@
@ /* Return to real scheduler via PendSV. Note that this routine is often
@ replaced with in-line assembly in tx_port.h to improved performance. */
@
MOV r0, #0x10000000 @ Load PENDSVSET bit
MOV r1, #0xE000E000 @ Load NVIC base
STR r0, [r1, #0xD04] @ Set PENDSVBIT in ICSR
MRS r0, IPSR @ Pickup IPSR
CMP r0, #0 @ Is it a thread returning?
BNE _isr_context @ If ISR, skip interrupt enable
MRS r1, PRIMASK @ Thread context returning, pickup PRIMASK
CPSIE i @ Enable interrupts
MSR PRIMASK, r1 @ Restore original interrupt posture
_isr_context:
BX lr @ Return to caller
@/* } */
/* Return to real scheduler via PendSV. Note that this routine is often
replaced with in-line assembly in tx_port.h to improved performance. */
MOV r0, #0x10000000 // Load PENDSVSET bit
MOV r1, #0xE000E000 // Load NVIC base
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
MRS r0, IPSR // Pickup IPSR
CMP r0, #0 // Is it a thread returning?
BNE _isr_context // If ISR, skip interrupt enable
#ifdef TX_PORT_USE_BASEPRI
MRS r1, BASEPRI // Thread context returning, pickup BASEPRI
MOV r0, #0
MSR BASEPRI, r0 // Enable interrupts
MSR BASEPRI, r1 // Restore original interrupt posture
#else
MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
CPSIE i // Enable interrupts
MSR PRIMASK, r1 // Restore original interrupt posture
#endif
_isr_context:
BX lr // Return to caller
// }

View File

@@ -1,259 +1,250 @@
@/**************************************************************************/
@/* */
@/* Copyright (c) Microsoft Corporation. All rights reserved. */
@/* */
@/* This software is licensed under the Microsoft Software License */
@/* Terms for Microsoft Azure RTOS. Full text of the license can be */
@/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
@/* and in the root directory of this software. */
@/* */
@/**************************************************************************/
@
@
@/**************************************************************************/
@/**************************************************************************/
@/** */
@/** ThreadX Component */
@/** */
@/** Timer */
@/** */
@/**************************************************************************/
@/**************************************************************************/
@
@
.global _tx_timer_time_slice
.global _tx_timer_system_clock
.global _tx_timer_current_ptr
.global _tx_timer_list_start
.global _tx_timer_list_end
.global _tx_timer_expired_time_slice
.global _tx_timer_expired
.global _tx_thread_time_slice
.global _tx_timer_expiration_process
@
@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Timer */
/** */
/**************************************************************************/
/**************************************************************************/
.global _tx_timer_time_slice
.global _tx_timer_system_clock
.global _tx_timer_current_ptr
.global _tx_timer_list_start
.global _tx_timer_list_end
.global _tx_timer_expired_time_slice
.global _tx_timer_expired
.global _tx_thread_time_slice
.global _tx_timer_expiration_process
.text
.align 4
.syntax unified
@/**************************************************************************/
@/* */
@/* FUNCTION RELEASE */
@/* */
@/* _tx_timer_interrupt Cortex-M4/GNU */
@/* 6.1 */
@/* AUTHOR */
@/* */
@/* William E. Lamie, Microsoft Corporation */
@/* */
@/* DESCRIPTION */
@/* */
@/* This function processes the hardware timer interrupt. This */
@/* processing includes incrementing the system clock and checking for */
@/* time slice and/or timer expiration. If either is found, the */
@/* interrupt context save/restore functions are called along with the */
@/* expiration functions. */
@/* */
@/* INPUT */
@/* */
@/* None */
@/* */
@/* OUTPUT */
@/* */
@/* None */
@/* */
@/* CALLS */
@/* */
@/* _tx_timer_expiration_process Timer expiration processing */
@/* _tx_thread_time_slice Time slice interrupted thread */
@/* */
@/* CALLED BY */
@/* */
@/* interrupt vector */
@/* */
@/* RELEASE HISTORY */
@/* */
@/* DATE NAME DESCRIPTION */
@/* */
@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
@/* 09-30-2020 William E. Lamie Modified comment(s), */
@/* resulting in version 6.1 */
@/* */
@/**************************************************************************/
@VOID _tx_timer_interrupt(VOID)
@{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_timer_interrupt Cortex-M4/GNU */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function processes the hardware timer interrupt. This */
/* processing includes incrementing the system clock and checking for */
/* time slice and/or timer expiration. If either is found, the */
/* expiration functions are called. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _tx_timer_expiration_process Timer expiration processing */
/* _tx_thread_time_slice Time slice interrupted thread */
/* */
/* CALLED BY */
/* */
/* interrupt vector */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_timer_interrupt(VOID)
// {
.global _tx_timer_interrupt
.thumb_func
_tx_timer_interrupt:
@
@ /* Upon entry to this routine, it is assumed that context save has already
@ been called, and therefore the compiler scratch registers are available
@ for use. */
@
@ /* Increment the system clock. */
@ _tx_timer_system_clock++;
@
LDR r1, =_tx_timer_system_clock @ Pickup address of system clock
LDR r0, [r1, #0] @ Pickup system clock
ADD r0, r0, #1 @ Increment system clock
STR r0, [r1, #0] @ Store new system clock
@
@ /* Test for time-slice expiration. */
@ if (_tx_timer_time_slice)
@ {
@
LDR r3, =_tx_timer_time_slice @ Pickup address of time-slice
LDR r2, [r3, #0] @ Pickup time-slice
CMP r2, #0 @ Is it non-active?
BEQ __tx_timer_no_time_slice @ Yes, skip time-slice processing
@
@ /* Decrement the time_slice. */
@ _tx_timer_time_slice--;
@
SUB r2, r2, #1 @ Decrement the time-slice
STR r2, [r3, #0] @ Store new time-slice value
@
@ /* Check for expiration. */
@ if (__tx_timer_time_slice == 0)
@
CMP r2, #0 @ Has it expired?
BNE __tx_timer_no_time_slice @ No, skip expiration processing
@
@ /* Set the time-slice expired flag. */
@ _tx_timer_expired_time_slice = TX_TRUE;
@
LDR r3, =_tx_timer_expired_time_slice @ Pickup address of expired flag
MOV r0, #1 @ Build expired value
STR r0, [r3, #0] @ Set time-slice expiration flag
@
@ }
@
/* Upon entry to this routine, it is assumed that the compiler scratch registers are available
for use. */
/* Increment the system clock. */
// _tx_timer_system_clock++;
LDR r1, =_tx_timer_system_clock // Pickup address of system clock
LDR r0, [r1, #0] // Pickup system clock
ADD r0, r0, #1 // Increment system clock
STR r0, [r1, #0] // Store new system clock
/* Test for time-slice expiration. */
// if (_tx_timer_time_slice)
// {
LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
LDR r2, [r3, #0] // Pickup time-slice
CBZ r2, __tx_timer_no_time_slice // Is it non-active?
// Yes, skip time-slice processing
/* Decrement the time_slice. */
// _tx_timer_time_slice--;
SUB r2, r2, #1 // Decrement the time-slice
STR r2, [r3, #0] // Store new time-slice value
/* Check for expiration. */
// if (__tx_timer_time_slice == 0)
CBNZ r2, __tx_timer_no_time_slice // Has it expired?
// No, skip expiration processing
/* Set the time-slice expired flag. */
// _tx_timer_expired_time_slice = TX_TRUE;
LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
MOV r0, #1 // Build expired value
STR r0, [r3, #0] // Set time-slice expiration flag
// }
__tx_timer_no_time_slice:
@
@ /* Test for timer expiration. */
@ if (*_tx_timer_current_ptr)
@ {
@
LDR r1, =_tx_timer_current_ptr @ Pickup current timer pointer address
LDR r0, [r1, #0] @ Pickup current timer
LDR r2, [r0, #0] @ Pickup timer list entry
CMP r2, #0 @ Is there anything in the list?
BEQ __tx_timer_no_timer @ No, just increment the timer
@
@ /* Set expiration flag. */
@ _tx_timer_expired = TX_TRUE;
@
LDR r3, =_tx_timer_expired @ Pickup expiration flag address
MOV r2, #1 @ Build expired value
STR r2, [r3, #0] @ Set expired flag
B __tx_timer_done @ Finished timer processing
@
@ }
@ else
@ {
/* Test for timer expiration. */
// if (*_tx_timer_current_ptr)
// {
LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
LDR r0, [r1, #0] // Pickup current timer
LDR r2, [r0, #0] // Pickup timer list entry
CBZ r2, __tx_timer_no_timer // Is there anything in the list?
// No, just increment the timer
/* Set expiration flag. */
// _tx_timer_expired = TX_TRUE;
LDR r3, =_tx_timer_expired // Pickup expiration flag address
MOV r2, #1 // Build expired value
STR r2, [r3, #0] // Set expired flag
B __tx_timer_done // Finished timer processing
// }
// else
// {
__tx_timer_no_timer:
@
@ /* No timer expired, increment the timer pointer. */
@ _tx_timer_current_ptr++;
@
ADD r0, r0, #4 @ Move to next timer
@
@ /* Check for wrap-around. */
@ if (_tx_timer_current_ptr == _tx_timer_list_end)
@
LDR r3, =_tx_timer_list_end @ Pickup addr of timer list end
LDR r2, [r3, #0] @ Pickup list end
CMP r0, r2 @ Are we at list end?
BNE __tx_timer_skip_wrap @ No, skip wrap-around logic
@
@ /* Wrap to beginning of list. */
@ _tx_timer_current_ptr = _tx_timer_list_start;
@
LDR r3, =_tx_timer_list_start @ Pickup addr of timer list start
LDR r0, [r3, #0] @ Set current pointer to list start
@
/* No timer expired, increment the timer pointer. */
// _tx_timer_current_ptr++;
ADD r0, r0, #4 // Move to next timer
/* Check for wrap-around. */
// if (_tx_timer_current_ptr == _tx_timer_list_end)
LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
LDR r2, [r3, #0] // Pickup list end
CMP r0, r2 // Are we at list end?
BNE __tx_timer_skip_wrap // No, skip wrap-around logic
/* Wrap to beginning of list. */
// _tx_timer_current_ptr = _tx_timer_list_start;
LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
LDR r0, [r3, #0] // Set current pointer to list start
__tx_timer_skip_wrap:
@
STR r0, [r1, #0] @ Store new current timer pointer
@ }
@
STR r0, [r1, #0] // Store new current timer pointer
// }
__tx_timer_done:
@
@
@ /* See if anything has expired. */
@ if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
@ {
@
LDR r3, =_tx_timer_expired_time_slice @ Pickup addr of expired flag
LDR r2, [r3, #0] @ Pickup time-slice expired flag
CMP r2, #0 @ Did a time-slice expire?
BNE __tx_something_expired @ If non-zero, time-slice expired
LDR r1, =_tx_timer_expired @ Pickup addr of other expired flag
LDR r0, [r1, #0] @ Pickup timer expired flag
CMP r0, #0 @ Did a timer expire?
BEQ __tx_timer_nothing_expired @ No, nothing expired
@
/* See if anything has expired. */
// if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
// {
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
LDR r2, [r3, #0] // Pickup time-slice expired flag
CBNZ r2, __tx_something_expired // Did a time-slice expire?
// If non-zero, time-slice expired
LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
LDR r0, [r1, #0] // Pickup timer expired flag
CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
// No, nothing expired
__tx_something_expired:
@
@
STMDB sp!, {r0, lr} @ Save the lr register on the stack
@ and save r0 just to keep 8-byte alignment
@
@ /* Did a timer expire? */
@ if (_tx_timer_expired)
@ {
@
LDR r1, =_tx_timer_expired @ Pickup addr of expired flag
LDR r0, [r1, #0] @ Pickup timer expired flag
CMP r0, #0 @ Check for timer expiration
BEQ __tx_timer_dont_activate @ If not set, skip timer activation
@
@ /* Process timer expiration. */
@ _tx_timer_expiration_process();
@
BL _tx_timer_expiration_process @ Call the timer expiration handling routine
@
@ }
STMDB sp!, {r0, lr} // Save the lr register on the stack
// and save r0 just to keep 8-byte alignment
/* Did a timer expire? */
// if (_tx_timer_expired)
// {
LDR r1, =_tx_timer_expired // Pickup addr of expired flag
LDR r0, [r1, #0] // Pickup timer expired flag
CBZ r0, __tx_timer_dont_activate // Check for timer expiration
// If not set, skip timer activation
/* Process timer expiration. */
// _tx_timer_expiration_process();
BL _tx_timer_expiration_process // Call the timer expiration handling routine
// }
__tx_timer_dont_activate:
@
@ /* Did time slice expire? */
@ if (_tx_timer_expired_time_slice)
@ {
@
LDR r3, =_tx_timer_expired_time_slice @ Pickup addr of time-slice expired
LDR r2, [r3, #0] @ Pickup the actual flag
CMP r2, #0 @ See if the flag is set
BEQ __tx_timer_not_ts_expiration @ No, skip time-slice processing
@
@ /* Time slice interrupted thread. */
@ _tx_thread_time_slice();
@
BL _tx_thread_time_slice @ Call time-slice processing
LDR r0, =_tx_thread_preempt_disable @ Build address of preempt disable flag
LDR r1, [r0] @ Is the preempt disable flag set?
CBNZ r1, __tx_timer_skip_time_slice @ Yes, skip the PendSV logic
LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address
LDR r1, [r0] @ Pickup the current thread pointer
LDR r2, =_tx_thread_execute_ptr @ Build execute thread pointer address
LDR r3, [r2] @ Pickup the execute thread pointer
LDR r0, =0xE000ED04 @ Build address of control register
LDR r2, =0x10000000 @ Build value for PendSV bit
CMP r1, r3 @ Are they the same?
BEQ __tx_timer_skip_time_slice @ If the same, there was no time-slice performed
STR r2, [r0] @ Not the same, issue the PendSV for preemption
/* Did time slice expire? */
// if (_tx_timer_expired_time_slice)
// {
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
LDR r2, [r3, #0] // Pickup the actual flag
CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
// No, skip time-slice processing
/* Time slice interrupted thread. */
// _tx_thread_time_slice();
BL _tx_thread_time_slice // Call time-slice processing
LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
LDR r1, [r0] // Is the preempt disable flag set?
CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
LDR r1, [r0] // Pickup the current thread pointer
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
LDR r3, [r2] // Pickup the execute thread pointer
LDR r0, =0xE000ED04 // Build address of control register
LDR r2, =0x10000000 // Build value for PendSV bit
CMP r1, r3 // Are they the same?
BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
STR r2, [r0] // Not the same, issue the PendSV for preemption
__tx_timer_skip_time_slice:
@
@ }
@
// }
__tx_timer_not_ts_expiration:
@
LDMIA sp!, {r0, lr} @ Recover lr register (r0 is just there for
@ the 8-byte stack alignment
@
@ }
@
LDMIA sp!, {r0, lr} // Recover lr register (r0 is just there for
// the 8-byte stack alignment
// }
__tx_timer_nothing_expired:
DSB @ Complete all memory access
BX lr @ Return to caller
@
@}
DSB // Complete all memory access
BX lr // Return to caller
// }

View File

@@ -26,11 +26,11 @@
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* tx_port.h Cortex-M4/IAR */
/* 6.1.6 */
/* 6.1.7 */
/* */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
@@ -43,14 +43,14 @@
/* own special types that can be mapped to actual data types by this */
/* file to guarantee consistency in the interface and functionality. */
/* */
/* This file replaces the previous Cortex-M3/M4/M7 files. It unifies */
/* the ARMv7-M architecture and compilers into one common file. */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
/* 04-02-2021 Bhupendra Naphade Modified comment(s),updated */
/* macro definition, */
/* resulting in version 6.1.6 */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
@@ -62,7 +62,7 @@
#ifdef TX_INCLUDE_USER_DEFINE_FILE
/* Yes, include the user defines in tx_user.h. The defines in this file may
/* Yes, include the user defines in tx_user.h. The defines in this file may
alternately be defined on the command line. */
#include "tx_user.h"
@@ -73,11 +73,29 @@
#include <stdlib.h>
#include <string.h>
#include <intrinsics.h>
#ifdef __ICCARM__
#include <intrinsics.h> /* IAR Intrinsics */
#define __asm__ __asm /* Define to make all inline asm look similar */
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#include <yvals.h>
#endif
#endif /* __ICCARM__ */
#ifdef __ghs__
#include <arm_ghs.h>
#include "tx_ghs.h"
#endif /* __ghs__ */
#if !defined(__GNUC__) && !defined(__CC_ARM)
#define __get_control_value __get_CONTROL
#define __set_control_value __set_CONTROL
#endif
#ifndef __GNUC__
#define __get_ipsr_value __get_IPSR
#endif
/* Define ThreadX basic types for this port. */
@@ -88,9 +106,10 @@ typedef int INT;
typedef unsigned int UINT;
typedef long LONG;
typedef unsigned long ULONG;
typedef unsigned long long ULONG64;
typedef short SHORT;
typedef unsigned short USHORT;
#define ULONG64_DEFINED
/* Define the priority levels for ThreadX. Legal values range
from 32 to 1024 and MUST be evenly divisible by 32. */
@@ -115,19 +134,19 @@ typedef unsigned short USHORT;
#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
/* Define various constants for the ThreadX ARM Cortex-M port. */
/* Define various constants for the ThreadX Cortex-M port. */
#define TX_INT_DISABLE 1 /* Disable interrupts */
#define TX_INT_ENABLE 0 /* Enable interrupts */
/* 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
/* 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
source constants would be:
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
@@ -137,7 +156,7 @@ typedef unsigned short USHORT;
#ifndef TX_MISRA_ENABLE
#ifndef TX_TRACE_TIME_SOURCE
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
#endif
#else
ULONG _tx_misra_time_stamp_get(VOID);
@@ -148,6 +167,20 @@ ULONG _tx_misra_time_stamp_get(VOID);
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
#endif
#ifdef __ghs__
/* Define constants for Green Hills EventAnalyzer. */
/* Define the number of ticks per second. This informs the EventAnalyzer what the timestamps
represent. By default, this is set to 1,000,000 i.e., one tick every microsecond. */
#define TX_EL_TICKS_PER_SECOND 1000000
/* Define the method of how to get the upper and lower 32-bits of the time stamp. By default, simply
simulate the time-stamp source with a counter. */
#define read_tbu() _tx_el_time_base_upper
#define read_tbl() ++_tx_el_time_base_lower
#endif /* __ghs__ */
/* Define the port specific options for the _tx_build_options variable. This variable indicates
how the ThreadX library was built. */
@@ -166,7 +199,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
@@ -180,24 +213,26 @@ 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
#define TX_THREAD_EXTENSION_1
#define TX_THREAD_EXTENSION_0
#define TX_THREAD_EXTENSION_1
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
#elif defined(__ghs__)
#define TX_THREAD_EXTENSION_2 VOID * tx_thread_eh_globals; \
int Errno; /* errno. */ \
char * strtok_saved_pos; /* strtok() position. */
#else
#define TX_THREAD_EXTENSION_2
#endif
#ifndef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
#define TX_THREAD_EXTENSION_3
#else
#define TX_THREAD_EXTENSION_3 unsigned long long tx_thread_execution_time_total; \
unsigned long long tx_thread_execution_time_last_start;
#define TX_THREAD_EXTENSION_2
#endif
#define TX_THREAD_EXTENSION_3
/* Define the port extensions of the remaining ThreadX objects. */
#define TX_BLOCK_POOL_EXTENSION
@@ -209,11 +244,11 @@ ULONG _tx_misra_time_stamp_get(VOID);
#define TX_TIMER_EXTENSION
/* 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
#define TX_THREAD_USER_EXTENSION
#define TX_THREAD_USER_EXTENSION
#endif
@@ -223,27 +258,26 @@ ULONG _tx_misra_time_stamp_get(VOID);
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#if (__VER__ < 8000000)
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
#else
void *_tx_iar_create_per_thread_tls_area(void);
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
void __iar_Initlocks(void);
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area();
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
#endif
#else
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
#endif
#ifdef __ARMVFP__
#if defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__TARGET_FPU_VFP) || defined(__VFP__)
#ifdef TX_MISRA_ENABLE
@@ -252,28 +286,71 @@ void _tx_misra_control_set(ULONG value);
ULONG _tx_misra_fpccr_get(void);
void _tx_misra_vfp_touch(void);
#endif
#else /* TX_MISRA_ENABLE not defined */
/* Define some helper functions (these are intrinsics in some compilers). */
#ifdef __GNUC__ /* GCC and ARM Compiler 6 */
__attribute__( ( always_inline ) ) static inline ULONG __get_control_value(void)
{
ULONG control_value;
__asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) );
return(control_value);
}
__attribute__( ( always_inline ) ) static inline void __set_control_value(ULONG control_value)
{
__asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" );
}
#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
#elif defined(__CC_ARM) /* ARM Compiler 5 */
__attribute__( ( always_inline ) ) ULONG __get_control_value(void)
{
ULONG control_value;
__asm volatile ("MRS control_value,CONTROL");
return(control_value);
}
__attribute__( ( always_inline ) ) void __set_control_value(ULONG control_value)
{
__asm__ volatile ("MSR CONTROL,control_value");
}
/* Can't access VFP registers with inline asm, so define this in tx_thread_schedule. */
void _tx_vfp_access(void);
#define TX_VFP_TOUCH() _tx_vfp_access();
#elif defined(__ICCARM__) /* IAR */
#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
#endif /* Helper functions for different compilers */
#endif /* TX_MISRA_ENABLE */
/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA
in order to ensure no lazy stacking will occur. */
#ifndef TX_MISRA_ENABLE
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_CONTROL(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_CONTROL(_tx_vfp_state); \
}
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
}
#else
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
}
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
}
#endif
/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR.
@@ -283,76 +360,76 @@ void _tx_misra_vfp_touch(void);
#ifndef TX_MISRA_ENABLE
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_CONTROL(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_CONTROL(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = *((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 = _tx_vfp_state & ((ULONG) 0x4); \
__asm volatile ("vmov.f32 s0, s0"); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = __get_CONTROL(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_CONTROL(_tx_vfp_state); \
} \
} \
} \
}
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = *((ULONG *) 0xE000EF34); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
TX_VFP_TOUCH(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
} \
} \
} \
}
#else
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = _tx_misra_fpccr_get(); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
_tx_misra_vfp_touch(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
} \
} \
}
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = _tx_misra_fpccr_get(); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
_tx_misra_vfp_touch(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
} \
} \
}
#endif
#else
#else /* No VFP in use */
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
#endif
#endif /* defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) */
/* Define the ThreadX object creation extensions for the remaining objects. */
@@ -377,16 +454,38 @@ void _tx_misra_vfp_touch(void);
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
/* Define the get system state macro. */
/* Define the get system state macro. */
#ifndef TX_THREAD_GET_SYSTEM_STATE
#ifndef TX_MISRA_ENABLE
#ifdef __CC_ARM /* ARM Compiler 5 */
register unsigned int _ipsr __asm("ipsr");
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _ipsr)
#elif defined(__GNUC__) /* GCC and ARM Compiler 6 */
__attribute__( ( always_inline ) ) static inline unsigned int __get_ipsr_value(void)
{
unsigned int ipsr_value;
__asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) );
return(ipsr_value);
}
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_ipsr_value())
#elif defined(__ICCARM__) /* IAR */
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_IPSR())
#else
#endif /* TX_THREAD_GET_SYSTEM_STATE for different compilers */
#else /* TX_MISRA_ENABLE is defined, use MISRA function. */
ULONG _tx_misra_ipsr_get(VOID);
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
#endif
#endif
#endif /* TX_MISRA_ENABLE */
#endif /* TX_THREAD_GET_SYSTEM_STATE */
/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
@@ -395,35 +494,189 @@ ULONG _tx_misra_ipsr_get(VOID);
zero after initialization for Cortex-M ports. */
#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
#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
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT)__CLZ(__RBIT((m)));
/* Define the TX_LOWEST_SET_BIT_CALCULATE macro for each compiler. */
#ifdef __ICCARM__ /* IAR Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __CLZ(__RBIT((m)));
#elif defined(__CC_ARM) /* AC5 Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __clz(__rbit((m)));
#elif defined(__GNUC__) /* GCC and AC6 Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \
__asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) );
#endif
/* Define ThreadX interrupt lockout and restore macros for protection on
access of critical kernel information. The restore interrupt macro must
restore the interrupt posture of the running thread prior to the value
present prior to the disable macro. In most cases, the save area macro
is used to define a local function save area for the disable and restore
macros. */
#ifdef TX_DISABLE_INLINE
/* Define the interrupt disable/restore macros for each compiler. */
#if defined(__GNUC__) || defined(__ICCARM__)
/*** GCC/AC6 and IAR ***/
__attribute__( ( always_inline ) ) static inline unsigned int __get_interrupt_posture(void)
{
unsigned int posture;
#ifdef TX_PORT_USE_BASEPRI
__asm__ volatile ("MRS %0, BASEPRI ": "=r" (posture));
#else
__asm__ volatile ("MRS %0, PRIMASK ": "=r" (posture));
#endif
return(posture);
}
#ifdef TX_PORT_USE_BASEPRI
__attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value)
{
__asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value));
}
#else
__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
{
__asm__ volatile ("CPSIE i": : : "memory");
}
#endif
__attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture)
{
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(int_posture);
//__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory");
#else
__asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory");
#endif
}
__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
{
unsigned int int_posture;
int_posture = __get_interrupt_posture();
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(TX_PORT_BASEPRI);
#else
__asm__ volatile ("CPSID i" : : : "memory");
#endif
return(int_posture);
}
__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
{
unsigned int interrupt_save;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (__get_ipsr_value() == 0)
{
interrupt_save = __get_interrupt_posture();
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(0);
#else
__enable_interrupts();
#endif
__restore_interrupt(interrupt_save);
}
}
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
#define TX_DISABLE interrupt_save = __disable_interrupts();
#define TX_RESTORE __restore_interrupt(interrupt_save);
/*** End GCC/AC6 and IAR ***/
#elif defined(__CC_ARM)
/*** AC5 ***/
static __inline unsigned int __get_interrupt_posture(void)
{
unsigned int posture;
#ifdef TX_PORT_USE_BASEPRI
__asm__ volatile ("MRS #posture, BASEPRI");
#else
__asm__ volatile ("MRS #posture, PRIMASK");
#endif
return(posture);
}
#ifdef TX_PORT_USE_BASEPRI
static __inline void __set_basepri_value(unsigned int basepri_value)
{
__asm__ volatile ("MSR BASEPRI, #basepri_value");
}
#endif
static __inline unsigned int __disable_interrupts(void)
{
unsigned int int_posture;
int_posture = __get_interrupt_posture();
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(TX_PORT_BASEPRI);
#else
__asm__ volatile ("CPSID i");
#endif
return(int_posture);
}
static __inline void __restore_interrupt(unsigned int int_posture)
{
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(int_posture);
#else
__asm__ volatile ("MSR PRIMASK, #int_posture");
#endif
}
static void _tx_thread_system_return_inline(void)
{
unsigned int interrupt_save;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (_ipsr == 0)
{
#ifdef TX_PORT_USE_BASEPRI
interrupt_save = __get_interrupt_posture();
__set_basepri_value(0);
__set_basepri_value(interrupt_save);
#else
interrupt_save = __disable_irq();
__enable_irq();
if (interrupt_save != 0)
__disable_irq();
#endif
}
}
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
#define TX_DISABLE interrupt_save = __disable_interrupts();
#define TX_RESTORE __restore_interrupt(interrupt_save);
/*** End AC5 ***/
#endif /* Interrupt disable/restore macros for each compiler. */
/* Redefine _tx_thread_system_return for improved performance. */
#define _tx_thread_system_return _tx_thread_system_return_inline
#else /* TX_DISABLE_INLINE is defined */
UINT _tx_thread_interrupt_disable(VOID);
VOID _tx_thread_interrupt_restore(UINT previous_posture);
@@ -431,56 +684,22 @@ VOID _tx_thread_interrupt_restore(UIN
#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
#else
#define TX_INTERRUPT_SAVE_AREA __istate_t interrupt_save;
#define TX_DISABLE {interrupt_save = __get_interrupt_state();__disable_interrupt();};
#define TX_RESTORE {__set_interrupt_state(interrupt_save);};
#define _tx_thread_system_return _tx_thread_system_return_inline
static void _tx_thread_system_return_inline(void)
{
__istate_t interrupt_save;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (__get_IPSR() == 0)
{
interrupt_save = __get_interrupt_state();
__enable_interrupt();
__set_interrupt_state(interrupt_save);
}
}
#endif
#endif /* TX_DISABLE_INLINE */
/* Define FPU extension for the Cortex-M4. Each is assumed to be called in the context of the executing
/* Define FPU extension for the Cortex-M. 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);
/* Define the interrupt lockout macros for each ThreadX object. */
#define TX_BLOCK_POOL_DISABLE TX_DISABLE
#define TX_BYTE_POOL_DISABLE TX_DISABLE
#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
#define TX_MUTEX_DISABLE TX_DISABLE
#define TX_QUEUE_DISABLE TX_DISABLE
#define TX_SEMAPHORE_DISABLE TX_DISABLE
/* 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-M4/IAR Version 6.1.6 *";
CHAR _tx_version_id[] =
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M4/IAR Version 6.1.7 *";
#else
#ifdef TX_MISRA_ENABLE
extern CHAR _tx_version_id[100];
@@ -491,6 +710,3 @@ extern CHAR _tx_version_id[];
#endif

View File

@@ -1,6 +1,6 @@
Microsoft's Azure RTOS ThreadX for Cortex-M4
Using the IAR Tools
Microsoft's Azure RTOS ThreadX for ARMv7-M
(Cortex-M3, Cortex-M4, Cortex-M7)
Using IAR EWARM Tools
1. Building the ThreadX run-time Library
@@ -25,12 +25,12 @@ Workbench, and select the "Make" button.
You should observe the compilation of sample_threadx.c (which is the demonstration
application) and linking with tx.a. The resulting file sample_threadx.out is a
binary ELF file that can be downloaded and executed on the IAR Windows-based
Cortex-M4 simulator.
Cortex-M simulator.
3. System Initialization
The entry point in ThreadX for the Cortex-M4 using IAR tools is at label
The entry point in ThreadX for the Cortex-M using IAR tools is at label
__iar_program_start. This is defined within the IAR compiler's startup code.
In addition, this is where all static and global preset C variable
initialization processing takes place.
@@ -52,7 +52,7 @@ other RAM sections in memory.
The following defines the saved context stack frames for context switches
that occur as a result of interrupt handling or from thread-level API calls.
All suspended threads have the same stack frame in the Cortex-M4 version of
All suspended threads have the same stack frame in the Cortex-M version of
ThreadX. The top of the suspended thread's stack is pointed to by
tx_thread_stack_ptr in the associated thread control block TX_THREAD.
@@ -60,7 +60,7 @@ Non-FPU Stack Frame:
Stack Offset Stack Contents
0x00 LR Interrupted LR (LR at time of PENDSV)
0x00 lr Interrupted lr (lr at time of PENDSV)
0x04 r4 Software stacked GP registers
0x08 r5
0x0C r6
@@ -82,7 +82,7 @@ FPU Stack Frame (only interrupted thread with FPU enabled):
Stack Offset Stack Contents
0x00 LR Interrupted LR (LR at time of PENDSV)
0x00 lr Interrupted lr (lr at time of PENDSV)
0x04 s16 Software stacked FPU registers
0x08 s17
0x0C s18
@@ -140,7 +140,7 @@ The distribution version of ThreadX is built without any compiler
optimizations. This makes it easy to debug because you can trace or set
breakpoints inside of ThreadX itself. Of course, this costs some
performance. To make it run faster, you can change the ThreadX library
project to enable various compiler optimizations.
project to enable various compiler optimizations.
In addition, you can eliminate the ThreadX basic API error checking by
compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING
@@ -149,7 +149,7 @@ defined.
6. Interrupt Handling
The Cortex-M4 vectors start at the label __vector_table and is defined in cstartup_M.s.
The Cortex-M vectors start at the label __vector_table and is defined in cstartup_M.s.
The application may modify the vector area according to its needs.
@@ -172,23 +172,14 @@ ISRs written in assembly language will take the form:
PUBLIC your_assembly_isr
your_assembly_isr:
PUSH {lr}
PUSH {r0, lr}
; ISR processing goes here, including any needed function calls.
POP {lr}
POP {r0, lr}
BX lr
7. IAR Thread-safe Library Support
Thread-safe support for the IAR tools is easily enabled by building the ThreadX library
and the application with TX_ENABLE_IAR_LIBRARY_SUPPORT. Also, the linker control file
should have the following line added (if not already in place):
initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application
7. IAR Thread-safe Library Support
Thread-safe support for the IAR tools is easily enabled by building the ThreadX library
@@ -203,7 +194,7 @@ The project options "General Options -> Library Configuration" should also have
8. VFP Support
ThreadX for Cortex-M4 supports automatic ("lazy") VFP support, which means that applications threads
ThreadX for Cortex-M supports automatic ("lazy") VFP support, which means that applications threads
can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread
context - no additional setup by the application.
@@ -214,16 +205,10 @@ For generic code revision information, please refer to the readme_threadx_generi
file, which is included in your distribution. The following details the revision
information associated with this specific port of ThreadX:
04-02-2021 Release 6.1.6 changes:
tx_port.h Updated macro definition
03-02-2021 The following files were changed/added for version 6.1.5:
tx_thread_schedule.s Added low power feature
09-30-2020 Initial ThreadX 6.1 version for Cortex-M4 using IAR's ARM tools.
06-02-2021 Initial ThreadX version 6.1.7 for Cortex-M using IAR's ARM tools.
Copyright(c) 1996-2020 Microsoft Corporation
Copyright(c) 1996-2021 Microsoft Corporation
https://azure.com/rtos

View File

@@ -1,89 +1,78 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
EXTERN _tx_execution_isr_exit
;
;
SECTION `.text`:CODE:NOROOT(2)
THUMB
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_context_restore Cortex-M4/IAR */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function is only needed for legacy applications and it should */
;/* not be called in any new development on a Cortex-M. */
;/* This function restores the interrupt context if it is processing a */
;/* nested interrupt. If not, it returns to the interrupt thread if no */
;/* preemption is necessary. Otherwise, if preemption is necessary or */
;/* if no thread was running, the function returns to the scheduler. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* [_tx_execution_isr_exit] Execution profiling ISR exit */
;/* */
;/* CALLED BY */
;/* */
;/* ISRs Interrupt Service Routines */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;VOID _tx_thread_context_restore(VOID)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_context_restore Cortex-M4/IAR */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is only needed for legacy applications and it should */
/* not be called in any new development on a Cortex-M. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* [_tx_execution_isr_exit] Execution profiling ISR exit */
/* */
/* CALLED BY */
/* */
/* ISRs Interrupt Service Routines */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_context_restore(VOID)
// {
PUBLIC _tx_thread_context_restore
_tx_thread_context_restore:
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
;
; /* Call the ISR exit function to indicate an ISR is complete. */
;
PUSH {r0, lr} ; Save return address
BL _tx_execution_isr_exit ; Call the ISR exit function
POP {r0, lr} ; Save return address
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the ISR exit function to indicate an ISR is complete. */
PUSH {r0, lr} // Save return address
BL _tx_execution_isr_exit // Call the ISR exit function
POP {r0, lr} // Recover return address
#endif
;
POP {lr}
BX lr
;
;}
// }
END

View File

@@ -1,87 +1,80 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
EXTERN _tx_execution_isr_enter
;
;
SECTION `.text`:CODE:NOROOT(2)
THUMB
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_context_save Cortex-M4/IAR */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function is only needed for legacy applications and it should */
;/* not be called in any new development on a Cortex-M. */
;/* This function saves the context of an executing thread in the */
;/* beginning of interrupt processing. The function also ensures that */
;/* the system stack is used upon return to the calling ISR. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* ISRs */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;VOID _tx_thread_context_save(VOID)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_context_save Cortex-M4/IAR */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is only needed for legacy applications and it should */
/* not be called in any new development on a Cortex-M. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* [_tx_execution_isr_enter] Execution profiling ISR enter */
/* */
/* CALLED BY */
/* */
/* ISRs */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_context_save(VOID)
// {
PUBLIC _tx_thread_context_save
_tx_thread_context_save:
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
;
; /* Call the ISR enter function to indicate an ISR is starting. */
;
PUSH {r0, lr} ; Save return address
BL _tx_execution_isr_enter ; Call the ISR enter function
POP {r0, lr} ; Recover return address
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the ISR enter function to indicate an ISR is starting. */
PUSH {r0, lr} // Save return address
BL _tx_execution_isr_enter // Call the ISR enter function
POP {r0, lr} // Recover return address
#endif
;
; /* Context is already saved - just return! */
;
/* Context is already saved - just return. */
BX lr
;}
// }
END

View File

@@ -1,74 +1,78 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
SECTION `.text`:CODE:NOROOT(2)
THUMB
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_interrupt_control Cortex-M4/IAR */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function is responsible for changing the interrupt lockout */
;/* posture of the system. */
;/* */
;/* INPUT */
;/* */
;/* new_posture New interrupt lockout posture */
;/* */
;/* OUTPUT */
;/* */
;/* old_posture Old interrupt lockout posture */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* Application Code */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;UINT _tx_thread_interrupt_control(UINT new_posture)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_control Cortex-M4/IAR */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for changing the interrupt lockout */
/* posture of the system. */
/* */
/* INPUT */
/* */
/* new_posture New interrupt lockout posture */
/* */
/* OUTPUT */
/* */
/* old_posture Old interrupt lockout posture */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// UINT _tx_thread_interrupt_control(UINT new_posture)
// {
PUBLIC _tx_thread_interrupt_control
_tx_thread_interrupt_control:
MRS r1, PRIMASK ; Pickup current interrupt lockout
MSR PRIMASK, r0 ; Apply the new interrupt lockout
MOV r0, r1 ; Transfer old to return register
BX lr ; Return to caller
;
;}
#ifdef TX_PORT_USE_BASEPRI
MRS r1, BASEPRI // Pickup current interrupt posture
MSR BASEPRI, r0 // Apply the new interrupt posture
MOV r0, r1 // Transfer old to return register
#else
MRS r1, PRIMASK // Pickup current interrupt lockout
MSR PRIMASK, r0 // Apply the new interrupt lockout
MOV r0, r1 // Transfer old to return register
#endif
BX lr // Return to caller
// }
END

View File

@@ -1,76 +1,78 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
SECTION `.text`:CODE:NOROOT(2)
THUMB
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_interrupt_restore Cortex-M4/IAR */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function is responsible for disabling interrupts and returning */
;/* the previous interrupt lockout posture. */
;/* */
;/* INPUT */
;/* */
;/* old_posture Old interrupt lockout posture */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* Application Code */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;UINT _tx_thread_interrupt_disable(UINT new_posture)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_disable Cortex-M4/IAR */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for disabling interrupts and returning */
/* the previous interrupt lockout posture. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* old_posture Old interrupt lockout posture */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// UINT _tx_thread_interrupt_disable(VOID)
// {
PUBLIC _tx_thread_interrupt_disable
_tx_thread_interrupt_disable:
;
; /* Return current interrupt lockout posture. */
;
/* Return current interrupt lockout posture. */
#ifdef TX_PORT_USE_BASEPRI
MRS r0, BASEPRI
LDR r1, =TX_PORT_USE_BASEPRI
MSR BASEPRI, r1
#else
MRS r0, PRIMASK
CPSID i
#endif
BX lr
;
;}
// }
END

View File

@@ -1,75 +1,75 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
SECTION `.text`:CODE:NOROOT(2)
THUMB
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_interrupt_restore Cortex-M4/IAR */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function is responsible for restoring the previous */
;/* interrupt lockout posture. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* previous_posture Previous interrupt posture */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* Application Code */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;VOID _tx_thread_interrupt_restore(UINT new_posture)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_interrupt_restore Cortex-M4/IAR */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is responsible for restoring the previous */
/* interrupt lockout posture. */
/* */
/* INPUT */
/* */
/* previous_posture Previous interrupt posture */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* Application Code */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_interrupt_restore(UINT previous_posture)
// {
PUBLIC _tx_thread_interrupt_restore
_tx_thread_interrupt_restore:
;
; /* Restore previous interrupt lockout posture. */
;
/* Restore previous interrupt lockout posture. */
#ifdef TX_PORT_USE_BASEPRI
MSR BASEPRI, r0
#else
MSR PRIMASK, r0
#endif
BX lr
;
;}
// }
END

View File

@@ -1,302 +1,279 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
EXTERN _tx_thread_current_ptr
EXTERN _tx_thread_execute_ptr
EXTERN _tx_timer_time_slice
EXTERN _tx_thread_system_stack_ptr
EXTERN _tx_thread_preempt_disable
EXTERN _tx_execution_thread_enter
EXTERN _tx_execution_thread_exit
EXTERN _tx_thread_preempt_disable
#ifdef TX_LOW_POWER
EXTERN tx_low_power_enter
EXTERN tx_low_power_exit
#endif
;
;
SECTION `.text`:CODE:NOROOT(2)
THUMB
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_schedule Cortex-M4/IAR */
;/* 6.1.5 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function waits for a thread control block pointer to appear in */
;/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
;/* in the variable, the corresponding thread is resumed. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* _tx_initialize_kernel_enter ThreadX entry function */
;/* _tx_thread_system_return Return to system from thread */
;/* _tx_thread_context_restore Restore thread's context */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* 03-02-2021 Scott Larson Modified comment(s), add */
;/* low power code, */
;/* resulting in version 6.1.5 */
;/* */
;/**************************************************************************/
;VOID _tx_thread_schedule(VOID)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_schedule Cortex-M4/IAR */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function waits for a thread control block pointer to appear in */
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
/* in the variable, the corresponding thread is resumed. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_initialize_kernel_enter ThreadX entry function */
/* _tx_thread_system_return Return to system from thread */
/* _tx_thread_context_restore Restore thread's context */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_schedule(VOID)
// {
PUBLIC _tx_thread_schedule
_tx_thread_schedule:
;
; /* This function should only ever be called on Cortex-M
; from the first schedule request. Subsequent scheduling occurs
; from the PendSV handling routines below. */
;
; /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
;
MOV r0, #0 ; Build value for TX_FALSE
LDR r2, =_tx_thread_preempt_disable ; Build address of preempt disable flag
STR r0, [r2, #0] ; Clear preempt disable flag
;
; /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
;
/* This function should only ever be called on Cortex-M
from the first schedule request. Subsequent scheduling occurs
from the PendSV handling routine below. */
/* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */
MOV r0, #0 // Build value for TX_FALSE
LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag
STR r0, [r2, #0] // Clear preempt disable flag
/* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */
#ifdef __ARMVFP__
MRS r0, CONTROL ; Pickup current CONTROL register
BIC r0, r0, #4 ; Clear the FPCA bit
MSR CONTROL, r0 ; Setup new CONTROL register
MRS r0, CONTROL // Pickup current CONTROL register
BIC r0, r0, #4 // Clear the FPCA bit
MSR CONTROL, r0 // Setup new CONTROL register
#endif
;
; /* Enable interrupts */
;
/* Enable interrupts */
CPSIE i
;
; /* Enter the scheduler for the first time. */
;
MOV r0, #0x10000000 ; Load PENDSVSET bit
MOV r1, #0xE000E000 ; Load NVIC base
STR r0, [r1, #0xD04] ; Set PENDSVBIT in ICSR
DSB ; Complete all memory accesses
ISB ; Flush pipeline
;
; /* Wait here for the PendSV to take place. */
;
/* Enter the scheduler for the first time. */
MOV r0, #0x10000000 // Load PENDSVSET bit
MOV r1, #0xE000E000 // Load NVIC base
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
DSB // Complete all memory accesses
ISB // Flush pipeline
/* Wait here for the PendSV to take place. */
__tx_wait_here:
B __tx_wait_here ; Wait for the PendSV to happen
;}
;
; /* Generic context PendSV handler. */
;
B __tx_wait_here // Wait for the PendSV to happen
// }
/* Generic context switching PendSV handler. */
PUBLIC PendSV_Handler
PUBLIC __tx_PendSVHandler
PendSV_Handler:
__tx_PendSVHandler:
;
; /* Get current thread value and new thread pointer. */
;
/* Get current thread value and new thread pointer. */
__tx_ts_handler:
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
;
; /* Call the thread exit function to indicate the thread is no longer executing. */
;
CPSID i ; Disable interrupts
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
CPSIE i ; Enable interrupts
#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
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
CPSIE i // Enable interrupts
#endif
MOV32 r0, _tx_thread_current_ptr ; Build current thread pointer address
MOV32 r2, _tx_thread_execute_ptr ; Build execute thread pointer address
MOV r3, #0 ; Build NULL value
LDR r1, [r0] ; Pickup current thread pointer
;
; /* Determine if there is a current thread to finish preserving. */
;
CBZ r1, __tx_ts_new ; If NULL, skip preservation
;
; /* Recover PSP and preserve current thread context. */
;
STR r3, [r0] ; Set _tx_thread_current_ptr to NULL
MRS r12, PSP ; Pickup PSP pointer (thread's stack pointer)
STMDB r12!, {r4-r11} ; Save its remaining registers
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
MOV r3, #0 // Build NULL value
LDR r1, [r0] // Pickup current thread pointer
/* Determine if there is a current thread to finish preserving. */
CBZ r1, __tx_ts_new // If NULL, skip preservation
/* Recover PSP and preserve current thread context. */
STR r3, [r0] // Set _tx_thread_current_ptr to NULL
MRS r12, PSP // Pickup PSP pointer (thread's stack pointer)
STMDB r12!, {r4-r11} // Save its remaining registers
#ifdef __ARMVFP__
TST LR, #0x10 ; Determine if the VFP extended frame is present
TST LR, #0x10 // Determine if the VFP extended frame is present
BNE _skip_vfp_save
VSTMDB r12!,{s16-s31} ; Yes, save additional VFP registers
VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers
_skip_vfp_save:
#endif
MOV32 r4, _tx_timer_time_slice ; Build address of time-slice variable
STMDB r12!, {LR} ; Save LR on the stack
;
; /* Determine if time-slice is active. If it isn't, skip time handling processing. */
;
LDR r5, [r4] ; Pickup current time-slice
STR r12, [r1, #8] ; Save the thread stack pointer
CBZ r5, __tx_ts_new ; If not active, skip processing
;
; /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
;
STR r5, [r1, #24] ; Save current time-slice
;
; /* Clear the global time-slice. */
;
STR r3, [r4] ; Clear time-slice
;
;
; /* Executing thread is now completely preserved!!! */
;
__tx_ts_new:
;
; /* Now we are looking for a new thread to execute! */
;
CPSID i ; Disable interrupts
LDR r1, [r2] ; Is there another thread ready to execute?
CBZ r1, __tx_ts_wait ; No, skip to the wait processing
;
; /* Yes, another thread is ready for else, make the current thread the new thread. */
;
STR r1, [r0] ; Setup the current thread pointer to the new thread
CPSIE i ; Enable interrupts
;
; /* Increment the thread run count. */
;
__tx_ts_restore:
LDR r7, [r1, #4] ; Pickup the current thread run count
MOV32 r4, _tx_timer_time_slice ; Build address of time-slice variable
LDR r5, [r1, #24] ; Pickup thread's current time-slice
ADD r7, r7, #1 ; Increment the thread run count
STR r7, [r1, #4] ; Store the new run count
;
; /* Setup global time-slice with thread's current time-slice. */
;
STR r5, [r4] ; Setup global time-slice
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
STMDB r12!, {LR} // Save LR on the stack
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
;
; /* Call the thread entry function to indicate the thread is executing. */
;
PUSH {r0, r1} ; Save r0/r1
BL _tx_execution_thread_enter ; Call the thread execution enter function
POP {r0, r1} ; Recover r3
/* Determine if time-slice is active. If it isn't, skip time handling processing. */
LDR r5, [r4] // Pickup current time-slice
STR r12, [r1, #8] // Save the thread stack pointer
CBZ r5, __tx_ts_new // If not active, skip processing
/* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */
STR r5, [r1, #24] // Save current time-slice
/* Clear the global time-slice. */
STR r3, [r4] // Clear time-slice
/* Executing thread is now completely preserved!!! */
__tx_ts_new:
/* Now we are looking for a new thread to execute! */
CPSID i // Disable interrupts
LDR r1, [r2] // Is there another thread ready to execute?
CBZ r1, __tx_ts_wait // No, skip to the wait processing
/* Yes, another thread is ready for else, make the current thread the new thread. */
STR r1, [r0] // Setup the current thread pointer to the new thread
CPSIE i // Enable interrupts
/* Increment the thread run count. */
__tx_ts_restore:
LDR r7, [r1, #4] // Pickup the current thread run count
LDR r4, =_tx_timer_time_slice // Build address of time-slice variable
LDR r5, [r1, #24] // Pickup thread's current time-slice
ADD r7, r7, #1 // Increment the thread run count
STR r7, [r1, #4] // Store the new run count
/* Setup global time-slice with thread's current time-slice. */
STR r5, [r4] // Setup global time-slice
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
/* Call the thread entry function to indicate the thread is executing. */
PUSH {r0, r1} // Save r0 and r1
BL _tx_execution_thread_enter // Call the thread execution enter function
POP {r0, r1} // Recover r0 and r1
#endif
;
; /* Restore the thread context and PSP. */
;
LDR r12, [r1, #8] ; Pickup thread's stack pointer
LDMIA r12!, {LR} ; Pickup LR
/* Restore the thread context and PSP. */
LDR r12, [r1, #8] // Pickup thread's stack pointer
LDMIA r12!, {LR} // Pickup LR
#ifdef __ARMVFP__
TST LR, #0x10 ; Determine if the VFP extended frame is present
BNE _skip_vfp_restore ; If not, skip VFP restore
VLDMIA r12!, {s16-s31} ; Yes, restore additional VFP registers
TST LR, #0x10 // Determine if the VFP extended frame is present
BNE _skip_vfp_restore // If not, skip VFP restore
VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers
_skip_vfp_restore:
#endif
LDMIA r12!, {r4-r11} ; Recover thread's registers
MSR PSP, r12 ; Setup the thread's stack pointer
;
; /* Return to thread. */
;
BX lr ; Return to thread!
;
; /* The following is the idle wait processing... in this case, no threads are ready for execution and the
; system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
; are disabled to allow use of WFI for waiting for a thread to arrive. */
;
LDMIA r12!, {r4-r11} // Recover thread's registers
MSR PSP, r12 // Setup the thread's stack pointer
/* Return to thread. */
BX lr // Return to thread!
/* The following is the idle wait processing... in this case, no threads are ready for execution and the
system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts
are disabled to allow use of WFI for waiting for a thread to arrive. */
__tx_ts_wait:
CPSID i ; Disable interrupts
LDR r1, [r2] ; Pickup the next thread to execute pointer
STR r1, [r0] ; Store it in the current pointer
CBNZ r1, __tx_ts_ready ; If non-NULL, a new thread is ready!
CPSID i // Disable interrupts
LDR r1, [r2] // Pickup the next thread to execute pointer
STR r1, [r0] // Store it in the current pointer
CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready!
#ifdef TX_LOW_POWER
PUSH {r0-r3}
BL tx_low_power_enter ; Possibly enter low power mode
POP {r0-r3}
BL tx_low_power_enter // Possibly enter low power mode
#endif
#ifdef TX_ENABLE_WFI
DSB ; Ensure no outstanding memory transactions
WFI ; Wait for interrupt
ISB ; Ensure pipeline is flushed
DSB // Ensure no outstanding memory transactions
WFI // Wait for interrupt
ISB // Ensure pipeline is flushed
#endif
#ifdef TX_LOW_POWER
PUSH {r0-r3}
BL tx_low_power_exit ; Exit low power mode
POP {r0-r3}
BL tx_low_power_exit // Exit low power mode
#endif
CPSIE i ; Enable interrupts
B __tx_ts_wait ; Loop to continue waiting
;
; /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
; already in the handler! */
;
CPSIE i // Enable interrupts
B __tx_ts_wait // Loop to continue waiting
/* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are
already in the handler! */
__tx_ts_ready:
MOV r7, #0x08000000 ; Build clear PendSV value
MOV r8, #0xE000E000 ; Build base NVIC address
STR r7, [r8, #0xD04] ; Clear any PendSV
;
; /* Re-enable interrupts and restore new thread. */
;
CPSIE i ; Enable interrupts
B __tx_ts_restore ; Restore the thread
;}
;
MOV r7, #0x08000000 // Build clear PendSV value
MOV r8, #0xE000E000 // Build base NVIC address
STR r7, [r8, #0xD04] // Clear any PendSV
/* Re-enable interrupts and restore new thread. */
CPSIE i // Enable interrupts
B __tx_ts_restore // Restore the thread
// }
#ifdef __ARMVFP__
PUBLIC tx_thread_fpu_enable
tx_thread_fpu_enable:
;
; /* Automatic VPF logic is supported, this function is present only for
; backward compatibility purposes and therefore simply returns. */
;
BX LR ; Return to caller
PUBLIC tx_thread_fpu_disable
tx_thread_fpu_disable:
;
; /* Automatic VPF logic is supported, this function is present only for
; backward compatibility purposes and therefore simply returns. */
;
BX LR ; Return to caller
/* Automatic VPF logic is supported, this function is present only for
backward compatibility purposes and therefore simply returns. */
BX LR // Return to caller
#endif
END

View File

@@ -1,134 +1,132 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
SECTION `.text`:CODE:NOROOT(2)
THUMB
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_stack_build Cortex-M4/IAR */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function builds a stack frame on the supplied thread's stack. */
;/* The stack frame results in a fake interrupt return to the supplied */
;/* function pointer. */
;/* */
;/* INPUT */
;/* */
;/* thread_ptr Pointer to thread control blk */
;/* function_ptr Pointer to return function */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* None */
;/* */
;/* CALLED BY */
;/* */
;/* _tx_thread_create Create thread service */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_stack_build Cortex-M4/IAR */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function builds a stack frame on the supplied thread's stack. */
/* The stack frame results in a fake interrupt return to the supplied */
/* function pointer. */
/* */
/* INPUT */
/* */
/* thread_ptr Pointer to thread control blk */
/* function_ptr Pointer to return function */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* None */
/* */
/* CALLED BY */
/* */
/* _tx_thread_create Create thread service */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
// {
PUBLIC _tx_thread_stack_build
_tx_thread_stack_build:
;
;
; /* Build a fake interrupt frame. The form of the fake interrupt stack
; on the Cortex-M should look like the following after it is built:
;
; Stack Top:
; LR Interrupted LR (LR at time of PENDSV)
; r4 Initial value for r4
; r5 Initial value for r5
; r6 Initial value for r6
; r7 Initial value for r7
; r8 Initial value for r8
; r9 Initial value for r9
; r10 Initial value for r10
; r11 Initial value for r11
; r0 Initial value for r0 (Hardware stack starts here!!)
; r1 Initial value for r1
; r2 Initial value for r2
; r3 Initial value for r3
; r12 Initial value for r12
; lr Initial value for lr
; pc Initial value for pc
; xPSR Initial value for xPSR
;
; Stack Bottom: (higher memory address) */
;
LDR r2, [r0, #16] ; Pickup end of stack area
BIC r2, r2, #0x7 ; Align frame for 8-byte alignment
SUB r2, r2, #68 ; Subtract frame size
LDR r3, =0xFFFFFFFD ; Build initial LR value
STR r3, [r2, #0] ; Save on the stack
;
; /* Actually build the stack frame. */
;
MOV r3, #0 ; Build initial register value
STR r3, [r2, #4] ; Store initial r4
STR r3, [r2, #8] ; Store initial r5
STR r3, [r2, #12] ; Store initial r6
STR r3, [r2, #16] ; Store initial r7
STR r3, [r2, #20] ; Store initial r8
STR r3, [r2, #24] ; Store initial r9
STR r3, [r2, #28] ; Store initial r10
STR r3, [r2, #32] ; Store initial r11
;
; /* Hardware stack follows. */
;
STR r3, [r2, #36] ; Store initial r0
STR r3, [r2, #40] ; Store initial r1
STR r3, [r2, #44] ; Store initial r2
STR r3, [r2, #48] ; Store initial r3
STR r3, [r2, #52] ; Store initial r12
MOV r3, #0xFFFFFFFF ; Poison EXC_RETURN value
STR r3, [r2, #56] ; Store initial lr
STR r1, [r2, #60] ; Store initial pc
MOV r3, #0x01000000 ; Only T-bit need be set
STR r3, [r2, #64] ; Store initial xPSR
;
; /* Setup stack pointer. */
; thread_ptr -> tx_thread_stack_ptr = r2;
;
STR r2, [r0, #8] ; Save stack pointer in thread's
; control block
BX lr ; Return to caller
;}
/* Build a fake interrupt frame. The form of the fake interrupt stack
on the Cortex-M should look like the following after it is built:
Stack Top:
LR Interrupted LR (LR at time of PENDSV)
r4 Initial value for r4
r5 Initial value for r5
r6 Initial value for r6
r7 Initial value for r7
r8 Initial value for r8
r9 Initial value for r9
r10 Initial value for r10
r11 Initial value for r11
r0 Initial value for r0 (Hardware stack starts here!!)
r1 Initial value for r1
r2 Initial value for r2
r3 Initial value for r3
r12 Initial value for r12
lr Initial value for lr
pc Initial value for pc
xPSR Initial value for xPSR
Stack Bottom: (higher memory address) */
LDR r2, [r0, #16] // Pickup end of stack area
BIC r2, r2, #0x7 // Align frame for 8-byte alignment
SUB r2, r2, #68 // Subtract frame size
LDR r3, =0xFFFFFFFD // Build initial LR value
STR r3, [r2, #0] // Save on the stack
/* Actually build the stack frame. */
MOV r3, #0 // Build initial register value
STR r3, [r2, #4] // Store initial r4
STR r3, [r2, #8] // Store initial r5
STR r3, [r2, #12] // Store initial r6
STR r3, [r2, #16] // Store initial r7
STR r3, [r2, #20] // Store initial r8
STR r3, [r2, #24] // Store initial r9
STR r3, [r2, #28] // Store initial r10
STR r3, [r2, #32] // Store initial r11
/* Hardware stack follows. */
STR r3, [r2, #36] // Store initial r0
STR r3, [r2, #40] // Store initial r1
STR r3, [r2, #44] // Store initial r2
STR r3, [r2, #48] // Store initial r3
STR r3, [r2, #52] // Store initial r12
MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value
STR r3, [r2, #56] // Store initial lr
STR r1, [r2, #60] // Store initial pc
MOV r3, #0x01000000 // Only T-bit need be set
STR r3, [r2, #64] // Store initial xPSR
/* Setup stack pointer. */
// thread_ptr -> tx_thread_stack_ptr = r2;
STR r2, [r0, #8] // Save stack pointer in thread's
// control block
BX lr // Return to caller
// }
END

View File

@@ -1,87 +1,92 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Thread */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Thread */
/** */
/**************************************************************************/
/**************************************************************************/
SECTION `.text`:CODE:NOROOT(2)
THUMB
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_thread_system_return Cortex-M4/IAR */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function is target processor specific. It is used to transfer */
;/* control from a thread back to the ThreadX system. Only a */
;/* minimal context is saved since the compiler assumes temp registers */
;/* are going to get slicked by a function call anyway. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* _tx_thread_schedule Thread scheduling loop */
;/* */
;/* CALLED BY */
;/* */
;/* ThreadX components */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;VOID _tx_thread_system_return(VOID)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_thread_system_return Cortex-M4/IAR */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function is target processor specific. It is used to transfer */
/* control from a thread back to the ThreadX system. Only a */
/* minimal context is saved since the compiler assumes temp registers */
/* are going to get slicked by a function call anyway. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _tx_thread_schedule Thread scheduling loop */
/* */
/* CALLED BY */
/* */
/* ThreadX components */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_thread_system_return(VOID)
// {
PUBLIC _tx_thread_system_return
_tx_thread_system_return??rA:
_tx_thread_system_return:
;
; /* Return to real scheduler via PendSV. Note that this routine is often
; replaced with in-line assembly in tx_port.h to improved performance. */
;
MOV r0, #0x10000000 ; Load PENDSVSET bit
MOV r1, #0xE000E000 ; Load NVIC base
STR r0, [r1, #0xD04] ; Set PENDSVBIT in ICSR
MRS r0, IPSR ; Pickup IPSR
CMP r0, #0 ; Is it a thread returning?
BNE _isr_context ; If ISR, skip interrupt enable
MRS r1, PRIMASK ; Thread context returning, pickup PRIMASK
CPSIE i ; Enable interrupts
MSR PRIMASK, r1 ; Restore original interrupt posture
/* Return to real scheduler via PendSV. Note that this routine is often
replaced with in-line assembly in tx_port.h to improved performance. */
MOV r0, #0x10000000 // Load PENDSVSET bit
MOV r1, #0xE000E000 // Load NVIC base
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
MRS r0, IPSR // Pickup IPSR
CMP r0, #0 // Is it a thread returning?
BNE _isr_context // If ISR, skip interrupt enable
#ifdef TX_PORT_USE_BASEPRI
MRS r1, BASEPRI // Thread context returning, pickup BASEPRI
MOV r0, #0
MSR BASEPRI, r0 // Enable interrupts
MSR BASEPRI, r1 // Restore original interrupt posture
#else
MRS r1, PRIMASK // Thread context returning, pickup PRIMASK
CPSIE i // Enable interrupts
MSR PRIMASK, r1 // Restore original interrupt posture
#endif
_isr_context:
BX lr ; Return to caller
;}
BX lr // Return to caller
// }
END

View File

@@ -1,26 +1,25 @@
;/**************************************************************************/
;/* */
;/* Copyright (c) Microsoft Corporation. All rights reserved. */
;/* */
;/* This software is licensed under the Microsoft Software License */
;/* Terms for Microsoft Azure RTOS. Full text of the license can be */
;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
;/* and in the root directory of this software. */
;/* */
;/**************************************************************************/
;
;
;/**************************************************************************/
;/**************************************************************************/
;/** */
;/** ThreadX Component */
;/** */
;/** Timer */
;/** */
;/**************************************************************************/
;/**************************************************************************/
;
;
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Timer */
/** */
/**************************************************************************/
/**************************************************************************/
EXTERN _tx_timer_time_slice
EXTERN _tx_timer_system_clock
EXTERN _tx_timer_current_ptr
@@ -33,224 +32,221 @@
EXTERN _tx_thread_current_ptr
EXTERN _tx_thread_execute_ptr
EXTERN _tx_thread_preempt_disable
;
;
SECTION `.text`:CODE:NOROOT(2)
THUMB
;/**************************************************************************/
;/* */
;/* FUNCTION RELEASE */
;/* */
;/* _tx_timer_interrupt Cortex-M4/IAR */
;/* 6.1 */
;/* AUTHOR */
;/* */
;/* William E. Lamie, Microsoft Corporation */
;/* */
;/* DESCRIPTION */
;/* */
;/* This function processes the hardware timer interrupt. This */
;/* processing includes incrementing the system clock and checking for */
;/* time slice and/or timer expiration. If either is found, the */
;/* expiration functions are called. */
;/* */
;/* INPUT */
;/* */
;/* None */
;/* */
;/* OUTPUT */
;/* */
;/* None */
;/* */
;/* CALLS */
;/* */
;/* _tx_timer_expiration_process Timer expiration processing */
;/* _tx_thread_time_slice Time slice interrupted thread */
;/* */
;/* CALLED BY */
;/* */
;/* interrupt vector */
;/* */
;/* RELEASE HISTORY */
;/* */
;/* DATE NAME DESCRIPTION */
;/* */
;/* 09-30-2020 William E. Lamie Initial Version 6.1 */
;/* */
;/**************************************************************************/
;VOID _tx_timer_interrupt(VOID)
;{
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_timer_interrupt Cortex-M4/IAR */
/* 6.1.7 */
/* AUTHOR */
/* */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
/* This function processes the hardware timer interrupt. This */
/* processing includes incrementing the system clock and checking for */
/* time slice and/or timer expiration. If either is found, the */
/* expiration functions are called. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _tx_timer_expiration_process Timer expiration processing */
/* _tx_thread_time_slice Time slice interrupted thread */
/* */
/* CALLED BY */
/* */
/* interrupt vector */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
// VOID _tx_timer_interrupt(VOID)
// {
PUBLIC _tx_timer_interrupt
_tx_timer_interrupt:
;
; /* Upon entry to this routine, it is assumed that the compiler scratch registers are available
; for use. */
;
; /* Increment the system clock. */
; _tx_timer_system_clock++;
;
MOV32 r1, _tx_timer_system_clock ; Pickup address of system clock
LDR r0, [r1, #0] ; Pickup system clock
ADD r0, r0, #1 ; Increment system clock
STR r0, [r1, #0] ; Store new system clock
;
; /* Test for time-slice expiration. */
; if (_tx_timer_time_slice)
; {
;
MOV32 r3, _tx_timer_time_slice ; Pickup address of time-slice
LDR r2, [r3, #0] ; Pickup time-slice
CBZ r2, __tx_timer_no_time_slice ; Is it non-active?
; Yes, skip time-slice processing
;
; /* Decrement the time_slice. */
; _tx_timer_time_slice--;
;
SUB r2, r2, #1 ; Decrement the time-slice
STR r2, [r3, #0] ; Store new time-slice value
;
; /* Check for expiration. */
; if (__tx_timer_time_slice == 0)
;
CBNZ r2, __tx_timer_no_time_slice ; Has it expired?
;
; /* Set the time-slice expired flag. */
; _tx_timer_expired_time_slice = TX_TRUE;
;
MOV32 r3, _tx_timer_expired_time_slice ; Pickup address of expired flag
MOV r0, #1 ; Build expired value
STR r0, [r3, #0] ; Set time-slice expiration flag
;
; }
;
__tx_timer_no_time_slice:
;
; /* Test for timer expiration. */
; if (*_tx_timer_current_ptr)
; {
;
MOV32 r1, _tx_timer_current_ptr ; Pickup current timer pointer address
LDR r0, [r1, #0] ; Pickup current timer
LDR r2, [r0, #0] ; Pickup timer list entry
CBZ r2, __tx_timer_no_timer ; Is there anything in the list?
; No, just increment the timer
;
; /* Set expiration flag. */
; _tx_timer_expired = TX_TRUE;
;
MOV32 r3, _tx_timer_expired ; Pickup expiration flag address
MOV r2, #1 ; Build expired value
STR r2, [r3, #0] ; Set expired flag
B __tx_timer_done ; Finished timer processing
;
; }
; else
; {
__tx_timer_no_timer:
;
; /* No timer expired, increment the timer pointer. */
; _tx_timer_current_ptr++;
;
ADD r0, r0, #4 ; Move to next timer
;
; /* Check for wrap-around. */
; if (_tx_timer_current_ptr == _tx_timer_list_end)
;
MOV32 r3, _tx_timer_list_end ; Pickup addr of timer list end
LDR r2, [r3, #0] ; Pickup list end
CMP r0, r2 ; Are we at list end?
BNE __tx_timer_skip_wrap ; No, skip wrap-around logic
;
; /* Wrap to beginning of list. */
; _tx_timer_current_ptr = _tx_timer_list_start;
;
MOV32 r3, _tx_timer_list_start ; Pickup addr of timer list start
LDR r0, [r3, #0] ; Set current pointer to list start
;
__tx_timer_skip_wrap:
;
STR r0, [r1, #0] ; Store new current timer pointer
; }
;
__tx_timer_done:
;
;
; /* See if anything has expired. */
; if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
; {
;
MOV32 r3, _tx_timer_expired_time_slice ; Pickup addr of expired flag
LDR r2, [r3, #0] ; Pickup time-slice expired flag
CBNZ r2, __tx_something_expired ; Did a time-slice expire?
; If non-zero, time-slice expired
MOV32 r1, _tx_timer_expired ; Pickup addr of other expired flag
LDR r0, [r1, #0] ; Pickup timer expired flag
CBZ r0, __tx_timer_nothing_expired ; Did a timer expire?
; No, nothing expired
;
__tx_something_expired:
;
;
STMDB sp!, {r0, lr} ; Save the lr register on the stack
; and save r0 just to keep 8-byte alignment
;
; /* Did a timer expire? */
; if (_tx_timer_expired)
; {
;
MOV32 r1, _tx_timer_expired ; Pickup addr of expired flag
LDR r0, [r1, #0] ; Pickup timer expired flag
CBZ r0, __tx_timer_dont_activate ; Check for timer expiration
; If not set, skip timer activation
;
; /* Process timer expiration. */
; _tx_timer_expiration_process();
;
BL _tx_timer_expiration_process ; Call the timer expiration handling routine
;
; }
__tx_timer_dont_activate:
;
; /* Did time slice expire? */
; if (_tx_timer_expired_time_slice)
; {
;
MOV32 r3, _tx_timer_expired_time_slice ; Pickup addr of time-slice expired
LDR r2, [r3, #0] ; Pickup the actual flag
CBZ r2, __tx_timer_not_ts_expiration ; See if the flag is set
; No, skip time-slice processing
;
; /* Time slice interrupted thread. */
; _tx_thread_time_slice();
BL _tx_thread_time_slice ; Call time-slice processing
MOV32 r0, _tx_thread_preempt_disable ; Build address of preempt disable flag
LDR r1, [r0] ; Is the preempt disable flag set?
CBNZ r1, __tx_timer_skip_time_slice ; Yes, skip the PendSV logic
MOV32 r0, _tx_thread_current_ptr ; Build current thread pointer address
LDR r1, [r0] ; Pickup the current thread pointer
MOV32 r2, _tx_thread_execute_ptr ; Build execute thread pointer address
LDR r3, [r2] ; Pickup the execute thread pointer
MOV32 r0, 0xE000ED04 ; Build address of control register
MOV32 r2, 0x10000000 ; Build value for PendSV bit
CMP r1, r3 ; Are they the same?
BEQ __tx_timer_skip_time_slice ; If the same, there was no time-slice performed
STR r2, [r0] ; Not the same, issue the PendSV for preemption
/* Upon entry to this routine, it is assumed that the compiler scratch registers are available
for use. */
/* Increment the system clock. */
// _tx_timer_system_clock++;
LDR r1, =_tx_timer_system_clock // Pickup address of system clock
LDR r0, [r1, #0] // Pickup system clock
ADD r0, r0, #1 // Increment system clock
STR r0, [r1, #0] // Store new system clock
/* Test for time-slice expiration. */
// if (_tx_timer_time_slice)
// {
LDR r3, =_tx_timer_time_slice // Pickup address of time-slice
LDR r2, [r3, #0] // Pickup time-slice
CBZ r2, __tx_timer_no_time_slice // Is it non-active?
// Yes, skip time-slice processing
/* Decrement the time_slice. */
// _tx_timer_time_slice--;
SUB r2, r2, #1 // Decrement the time-slice
STR r2, [r3, #0] // Store new time-slice value
/* Check for expiration. */
// if (__tx_timer_time_slice == 0)
CBNZ r2, __tx_timer_no_time_slice // Has it expired?
// No, skip expiration processing
/* Set the time-slice expired flag. */
// _tx_timer_expired_time_slice = TX_TRUE;
LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag
MOV r0, #1 // Build expired value
STR r0, [r3, #0] // Set time-slice expiration flag
// }
__tx_timer_no_time_slice:
/* Test for timer expiration. */
// if (*_tx_timer_current_ptr)
// {
LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address
LDR r0, [r1, #0] // Pickup current timer
LDR r2, [r0, #0] // Pickup timer list entry
CBZ r2, __tx_timer_no_timer // Is there anything in the list?
// No, just increment the timer
/* Set expiration flag. */
// _tx_timer_expired = TX_TRUE;
LDR r3, =_tx_timer_expired // Pickup expiration flag address
MOV r2, #1 // Build expired value
STR r2, [r3, #0] // Set expired flag
B __tx_timer_done // Finished timer processing
// }
// else
// {
__tx_timer_no_timer:
/* No timer expired, increment the timer pointer. */
// _tx_timer_current_ptr++;
ADD r0, r0, #4 // Move to next timer
/* Check for wrap-around. */
// if (_tx_timer_current_ptr == _tx_timer_list_end)
LDR r3, =_tx_timer_list_end // Pickup addr of timer list end
LDR r2, [r3, #0] // Pickup list end
CMP r0, r2 // Are we at list end?
BNE __tx_timer_skip_wrap // No, skip wrap-around logic
/* Wrap to beginning of list. */
// _tx_timer_current_ptr = _tx_timer_list_start;
LDR r3, =_tx_timer_list_start // Pickup addr of timer list start
LDR r0, [r3, #0] // Set current pointer to list start
__tx_timer_skip_wrap:
STR r0, [r1, #0] // Store new current timer pointer
// }
__tx_timer_done:
/* See if anything has expired. */
// if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
// {
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
LDR r2, [r3, #0] // Pickup time-slice expired flag
CBNZ r2, __tx_something_expired // Did a time-slice expire?
// If non-zero, time-slice expired
LDR r1, =_tx_timer_expired // Pickup addr of other expired flag
LDR r0, [r1, #0] // Pickup timer expired flag
CBZ r0, __tx_timer_nothing_expired // Did a timer expire?
// No, nothing expired
__tx_something_expired:
STMDB sp!, {r0, lr} // Save the lr register on the stack
// and save r0 just to keep 8-byte alignment
/* Did a timer expire? */
// if (_tx_timer_expired)
// {
LDR r1, =_tx_timer_expired // Pickup addr of expired flag
LDR r0, [r1, #0] // Pickup timer expired flag
CBZ r0, __tx_timer_dont_activate // Check for timer expiration
// If not set, skip timer activation
/* Process timer expiration. */
// _tx_timer_expiration_process();
BL _tx_timer_expiration_process // Call the timer expiration handling routine
// }
__tx_timer_dont_activate:
/* Did time slice expire? */
// if (_tx_timer_expired_time_slice)
// {
LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
LDR r2, [r3, #0] // Pickup the actual flag
CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set
// No, skip time-slice processing
/* Time slice interrupted thread. */
// _tx_thread_time_slice();
BL _tx_thread_time_slice // Call time-slice processing
LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag
LDR r1, [r0] // Is the preempt disable flag set?
CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic
LDR r0, =_tx_thread_current_ptr // Build current thread pointer address
LDR r1, [r0] // Pickup the current thread pointer
LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address
LDR r3, [r2] // Pickup the execute thread pointer
LDR r0, =0xE000ED04 // Build address of control register
LDR r2, =0x10000000 // Build value for PendSV bit
CMP r1, r3 // Are they the same?
BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed
STR r2, [r0] // Not the same, issue the PendSV for preemption
__tx_timer_skip_time_slice:
;
; }
;
// }
__tx_timer_not_ts_expiration:
;
LDMIA sp!, {r0, lr} ; Recover lr register (r0 is just there for
; the 8-byte stack alignment
;
; }
;
LDMIA sp!, {r0, lr} // Recover lr register (r0 is just there for
// the 8-byte stack alignment
// }
__tx_timer_nothing_expired:
DSB ; Complete all memory access
BX lr ; Return to caller
;
;}
DSB // Complete all memory access
BX lr // Return to caller
// }
END

View File

@@ -26,11 +26,11 @@
/* PORT SPECIFIC C INFORMATION RELEASE */
/* */
/* tx_port.h Cortex-M4/Keil */
/* 6.1.6 */
/* 6.1.7 */
/* */
/* AUTHOR */
/* */
/* William E. Lamie, Microsoft Corporation */
/* Scott Larson, Microsoft Corporation */
/* */
/* DESCRIPTION */
/* */
@@ -43,14 +43,14 @@
/* own special types that can be mapped to actual data types by this */
/* file to guarantee consistency in the interface and functionality. */
/* */
/* This file replaces the previous Cortex-M3/M4/M7 files. It unifies */
/* the ARMv7-M architecture and compilers into one common file. */
/* */
/* RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
/* 04-02-2021 Bhupendra Naphade Modified comment(s),updated */
/* macro definition, */
/* resulting in version 6.1.6 */
/* 06-02-2021 Scott Larson Initial Version 6.1.7 */
/* */
/**************************************************************************/
@@ -62,7 +62,7 @@
#ifdef TX_INCLUDE_USER_DEFINE_FILE
/* Yes, include the user defines in tx_user.h. The defines in this file may
/* Yes, include the user defines in tx_user.h. The defines in this file may
alternately be defined on the command line. */
#include "tx_user.h"
@@ -74,6 +74,28 @@
#include <stdlib.h>
#include <string.h>
#ifdef __ICCARM__
#include <intrinsics.h> /* IAR Intrinsics */
#define __asm__ __asm /* Define to make all inline asm look similar */
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#include <yvals.h>
#endif
#endif /* __ICCARM__ */
#ifdef __ghs__
#include <arm_ghs.h>
#include "tx_ghs.h"
#endif /* __ghs__ */
#if !defined(__GNUC__) && !defined(__CC_ARM)
#define __get_control_value __get_CONTROL
#define __set_control_value __set_CONTROL
#endif
#ifndef __GNUC__
#define __get_ipsr_value __get_IPSR
#endif
/* Define ThreadX basic types for this port. */
@@ -84,9 +106,10 @@ typedef int INT;
typedef unsigned int UINT;
typedef long LONG;
typedef unsigned long ULONG;
typedef unsigned long long ULONG64;
typedef short SHORT;
typedef unsigned short USHORT;
#define ULONG64_DEFINED
/* Define the priority levels for ThreadX. Legal values range
from 32 to 1024 and MUST be evenly divisible by 32. */
@@ -111,19 +134,19 @@ typedef unsigned short USHORT;
#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
/* Define various constants for the ThreadX Cortex-M3 port. */
/* Define various constants for the ThreadX Cortex-M port. */
#define TX_INT_DISABLE 1 /* Disable interrupts */
#define TX_INT_ENABLE 0 /* Enable interrupts */
/* 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
/* 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
source constants would be:
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
@@ -133,7 +156,7 @@ typedef unsigned short USHORT;
#ifndef TX_MISRA_ENABLE
#ifndef TX_TRACE_TIME_SOURCE
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
#endif
#else
ULONG _tx_misra_time_stamp_get(VOID);
@@ -144,6 +167,20 @@ ULONG _tx_misra_time_stamp_get(VOID);
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
#endif
#ifdef __ghs__
/* Define constants for Green Hills EventAnalyzer. */
/* Define the number of ticks per second. This informs the EventAnalyzer what the timestamps
represent. By default, this is set to 1,000,000 i.e., one tick every microsecond. */
#define TX_EL_TICKS_PER_SECOND 1000000
/* Define the method of how to get the upper and lower 32-bits of the time stamp. By default, simply
simulate the time-stamp source with a counter. */
#define read_tbu() _tx_el_time_base_upper
#define read_tbl() ++_tx_el_time_base_lower
#endif /* __ghs__ */
/* Define the port specific options for the _tx_build_options variable. This variable indicates
how the ThreadX library was built. */
@@ -162,7 +199,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
@@ -176,13 +213,24 @@ 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
#define TX_THREAD_EXTENSION_1
#define TX_THREAD_EXTENSION_2
#define TX_THREAD_EXTENSION_3
#define TX_THREAD_EXTENSION_0
#define TX_THREAD_EXTENSION_1
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer;
#elif defined(__ghs__)
#define TX_THREAD_EXTENSION_2 VOID * tx_thread_eh_globals; \
int Errno; /* errno. */ \
char * strtok_saved_pos; /* strtok() position. */
#else
#define TX_THREAD_EXTENSION_2
#endif
#define TX_THREAD_EXTENSION_3
/* Define the port extensions of the remaining ThreadX objects. */
@@ -196,11 +244,11 @@ ULONG _tx_misra_time_stamp_get(VOID);
#define TX_TIMER_EXTENSION
/* 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
#define TX_THREAD_USER_EXTENSION
#define TX_THREAD_USER_EXTENSION
#endif
@@ -208,18 +256,28 @@ ULONG _tx_misra_time_stamp_get(VOID);
tx_thread_shell_entry, and tx_thread_terminate. */
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
#ifndef TX_MISRA_ENABLE
register unsigned int _ipsr __asm("ipsr");
#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
#if (__VER__ < 8000000)
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL;
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0);
#else
void *_tx_iar_create_per_thread_tls_area(void);
void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
void __iar_Initlocks(void);
#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area();
#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \
thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0);
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0);
#endif
#else
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
#endif
#ifdef __TARGET_FPU_VFP
#if defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__TARGET_FPU_VFP) || defined(__VFP__)
#ifdef TX_MISRA_ENABLE
@@ -228,35 +286,71 @@ void _tx_misra_control_set(ULONG value);
ULONG _tx_misra_fpccr_get(void);
void _tx_misra_vfp_touch(void);
#else
#else /* TX_MISRA_ENABLE not defined */
#ifdef TX_SOURCE_CODE
/* Define some helper functions (these are intrinsics in some compilers). */
#ifdef __GNUC__ /* GCC and ARM Compiler 6 */
register ULONG _control __asm("control");
__attribute__( ( always_inline ) ) static inline ULONG __get_control_value(void)
{
ULONG control_value;
__asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) );
return(control_value);
}
__attribute__( ( always_inline ) ) static inline void __set_control_value(ULONG control_value)
{
__asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" );
}
#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
#elif defined(__CC_ARM) /* ARM Compiler 5 */
__attribute__( ( always_inline ) ) ULONG __get_control_value(void)
{
ULONG control_value;
__asm volatile ("MRS control_value,CONTROL");
return(control_value);
}
__attribute__( ( always_inline ) ) void __set_control_value(ULONG control_value)
{
__asm__ volatile ("MSR CONTROL,control_value");
}
/* Can't access VFP registers with inline asm, so define this in tx_thread_schedule. */
void _tx_vfp_access(void);
#define TX_VFP_TOUCH() _tx_vfp_access();
#elif defined(__ICCARM__) /* IAR */
#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0");
#endif /* Helper functions for different compilers */
#endif /* TX_MISRA_ENABLE */
#endif
#endif
/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA
in order to ensure no lazy stacking will occur. */
#ifndef TX_MISRA_ENABLE
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = _control; \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_control = _tx_vfp_state; \
}
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
}
#else
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
}
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
}
#endif
/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR.
@@ -266,78 +360,76 @@ register ULONG _control __asm("control");
#ifndef TX_MISRA_ENABLE
void _tx_vfp_access(void);
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _control; \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_control = _tx_vfp_state; \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = *((ULONG *) 0xE000EF34); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _control; \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
_tx_vfp_access(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = _control; \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_control = _tx_vfp_state; \
} \
} \
} \
}
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = *((ULONG *) 0xE000EF34); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
TX_VFP_TOUCH(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = __get_control_value(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
__set_control_value(_tx_vfp_state); \
} \
} \
} \
}
#else
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = _tx_misra_fpccr_get(); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
_tx_misra_vfp_touch(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
} \
} \
}
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \
ULONG _tx_system_state; \
_tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \
if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
else \
{ \
ULONG _tx_fpccr; \
_tx_fpccr = _tx_misra_fpccr_get(); \
_tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \
if (_tx_fpccr == ((ULONG) 0x01)) \
{ \
ULONG _tx_vfp_state; \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \
_tx_misra_vfp_touch(); \
if (_tx_vfp_state == ((ULONG) 0)) \
{ \
_tx_vfp_state = _tx_misra_control_get(); \
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
_tx_misra_control_set(_tx_vfp_state); \
} \
} \
} \
}
#endif
#else
#else /* No VFP in use */
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
#endif
#endif /* defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) */
/* Define the ThreadX object creation extensions for the remaining objects. */
@@ -362,16 +454,38 @@ void _tx_vfp_access(void);
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
/* Define the get system state macro. */
/* Define the get system state macro. */
#ifndef TX_THREAD_GET_SYSTEM_STATE
#ifndef TX_MISRA_ENABLE
#ifdef __CC_ARM /* ARM Compiler 5 */
register unsigned int _ipsr __asm("ipsr");
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _ipsr)
#else
#elif defined(__GNUC__) /* GCC and ARM Compiler 6 */
__attribute__( ( always_inline ) ) static inline unsigned int __get_ipsr_value(void)
{
unsigned int ipsr_value;
__asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) );
return(ipsr_value);
}
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_ipsr_value())
#elif defined(__ICCARM__) /* IAR */
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | __get_IPSR())
#endif /* TX_THREAD_GET_SYSTEM_STATE for different compilers */
#else /* TX_MISRA_ENABLE is defined, use MISRA function. */
ULONG _tx_misra_ipsr_get(VOID);
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
#endif
#endif
#endif /* TX_MISRA_ENABLE */
#endif /* TX_THREAD_GET_SYSTEM_STATE */
/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value
@@ -380,35 +494,189 @@ ULONG _tx_misra_ipsr_get(VOID);
zero after initialization for Cortex-M ports. */
#ifndef TX_THREAD_SYSTEM_RETURN_CHECK
#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable);
#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
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __clz(__rbit((m)));
/* Define the TX_LOWEST_SET_BIT_CALCULATE macro for each compiler. */
#ifdef __ICCARM__ /* IAR Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __CLZ(__RBIT((m)));
#elif defined(__CC_ARM) /* AC5 Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __clz(__rbit((m)));
#elif defined(__GNUC__) /* GCC and AC6 Compiler */
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \
__asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) );
#endif
/* Define ThreadX interrupt lockout and restore macros for protection on
access of critical kernel information. The restore interrupt macro must
restore the interrupt posture of the running thread prior to the value
present prior to the disable macro. In most cases, the save area macro
is used to define a local function save area for the disable and restore
macros. */
#ifdef TX_DISABLE_INLINE
/* Define the interrupt disable/restore macros for each compiler. */
#if defined(__GNUC__) || defined(__ICCARM__)
/*** GCC/AC6 and IAR ***/
__attribute__( ( always_inline ) ) static inline unsigned int __get_interrupt_posture(void)
{
unsigned int posture;
#ifdef TX_PORT_USE_BASEPRI
__asm__ volatile ("MRS %0, BASEPRI ": "=r" (posture));
#else
__asm__ volatile ("MRS %0, PRIMASK ": "=r" (posture));
#endif
return(posture);
}
#ifdef TX_PORT_USE_BASEPRI
__attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value)
{
__asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value));
}
#else
__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
{
__asm__ volatile ("CPSIE i": : : "memory");
}
#endif
__attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsigned int int_posture)
{
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(int_posture);
//__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory");
#else
__asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory");
#endif
}
__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
{
unsigned int int_posture;
int_posture = __get_interrupt_posture();
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(TX_PORT_BASEPRI);
#else
__asm__ volatile ("CPSID i" : : : "memory");
#endif
return(int_posture);
}
__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void)
{
unsigned int interrupt_save;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (__get_ipsr_value() == 0)
{
interrupt_save = __get_interrupt_posture();
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(0);
#else
__enable_interrupts();
#endif
__restore_interrupt(interrupt_save);
}
}
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
#define TX_DISABLE interrupt_save = __disable_interrupts();
#define TX_RESTORE __restore_interrupt(interrupt_save);
/*** End GCC/AC6 and IAR ***/
#elif defined(__CC_ARM)
/*** AC5 ***/
static __inline unsigned int __get_interrupt_posture(void)
{
unsigned int posture;
#ifdef TX_PORT_USE_BASEPRI
__asm__ volatile ("MRS #posture, BASEPRI");
#else
__asm__ volatile ("MRS #posture, PRIMASK");
#endif
return(posture);
}
#ifdef TX_PORT_USE_BASEPRI
static __inline void __set_basepri_value(unsigned int basepri_value)
{
__asm__ volatile ("MSR BASEPRI, #basepri_value");
}
#endif
static __inline unsigned int __disable_interrupts(void)
{
unsigned int int_posture;
int_posture = __get_interrupt_posture();
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(TX_PORT_BASEPRI);
#else
__asm__ volatile ("CPSID i");
#endif
return(int_posture);
}
static __inline void __restore_interrupt(unsigned int int_posture)
{
#ifdef TX_PORT_USE_BASEPRI
__set_basepri_value(int_posture);
#else
__asm__ volatile ("MSR PRIMASK, #int_posture");
#endif
}
static void _tx_thread_system_return_inline(void)
{
unsigned int interrupt_save;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (_ipsr == 0)
{
#ifdef TX_PORT_USE_BASEPRI
interrupt_save = __get_interrupt_posture();
__set_basepri_value(0);
__set_basepri_value(interrupt_save);
#else
interrupt_save = __disable_irq();
__enable_irq();
if (interrupt_save != 0)
__disable_irq();
#endif
}
}
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
#define TX_DISABLE interrupt_save = __disable_interrupts();
#define TX_RESTORE __restore_interrupt(interrupt_save);
/*** End AC5 ***/
#endif /* Interrupt disable/restore macros for each compiler. */
/* Redefine _tx_thread_system_return for improved performance. */
#define _tx_thread_system_return _tx_thread_system_return_inline
#else /* TX_DISABLE_INLINE is defined */
UINT _tx_thread_interrupt_disable(VOID);
VOID _tx_thread_interrupt_restore(UINT previous_posture);
@@ -416,37 +684,11 @@ VOID _tx_thread_interrupt_restore(UIN
#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
#else
#define TX_INTERRUPT_SAVE_AREA UINT was_masked;
#define TX_DISABLE was_masked = __disable_irq();
#define TX_RESTORE if (was_masked == 0) __enable_irq();
#define _tx_thread_system_return _tx_thread_system_return_inline
#endif /* TX_DISABLE_INLINE */
static void _tx_thread_system_return_inline(void)
{
unsigned int was_masked;
/* Set PendSV to invoke ThreadX scheduler. */
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
if (_ipsr == 0)
{
was_masked = __disable_irq();
__enable_irq();
if (was_masked != 0)
__disable_irq();
}
}
#endif
/* Define FPU extension for the Cortex-M4. Each is assumed to be called in the context of the executing
/* Define FPU extension for the Cortex-M. 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);
@@ -456,8 +698,8 @@ void tx_thread_fpu_disable(void);
/* 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-M4/Keil Version 6.1.6 *";
CHAR _tx_version_id[] =
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX Cortex-M4/Keil Version 6.1.7 *";
#else
#ifdef TX_MISRA_ENABLE
extern CHAR _tx_version_id[100];
@@ -468,7 +710,3 @@ extern CHAR _tx_version_id[];
#endif