Initial commit
This commit is contained in:
21
ports/cortex_m0/gnu/CMakeLists.txt
Normal file
21
ports/cortex_m0/gnu/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
# {{BEGIN_TARGET_SOURCES}}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S
|
||||
|
||||
# {{END_TARGET_SOURCES}}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc
|
||||
)
|
||||
371
ports/cortex_m0/gnu/inc/tx_port.h
Normal file
371
ports/cortex_m0/gnu/inc/tx_port.h
Normal file
@@ -0,0 +1,371 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Port Specific */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M0/GNU */
|
||||
/* 6.0 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains data type definitions that make the ThreadX */
|
||||
/* real-time kernel function identically on a variety of different */
|
||||
/* processor architectures. For example, the size or number of bits */
|
||||
/* in an "int" data type vary between microprocessor architectures and */
|
||||
/* even C compilers for the same microprocessor. ThreadX does not */
|
||||
/* directly use native C data types. Instead, ThreadX creates its */
|
||||
/* own special types that can be mapped to actual data types by this */
|
||||
/* file to guarantee consistency in the interface and functionality. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_PORT_H
|
||||
#define TX_PORT_H
|
||||
|
||||
|
||||
/* Determine if the optional ThreadX user define file should be used. */
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
|
||||
/* 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"
|
||||
#endif
|
||||
|
||||
|
||||
/* Define compiler library include files. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Define ThreadX basic types for this port. */
|
||||
|
||||
#define VOID void
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef long LONG;
|
||||
typedef unsigned long ULONG;
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
|
||||
|
||||
/* Define the TX_MEMSET macro to remove library reference. */
|
||||
|
||||
#define TX_MEMSET(a,b,c) { \
|
||||
UCHAR *ptr; \
|
||||
UCHAR value; \
|
||||
UINT i, size; \
|
||||
ptr = (UCHAR *) ((VOID *) a); \
|
||||
value = (UCHAR) b; \
|
||||
size = (UINT) c; \
|
||||
for (i = 0; i < size; i++) \
|
||||
{ \
|
||||
*ptr++ = value; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Define the priority levels for ThreadX. Legal values range
|
||||
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||
|
||||
#ifndef TX_MAX_PRIORITIES
|
||||
#define TX_MAX_PRIORITIES 32
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||
thread creation is less than this value, the thread create call will return an error. */
|
||||
|
||||
#ifndef TX_MINIMUM_STACK
|
||||
#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||
|
||||
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
|
||||
#endif
|
||||
|
||||
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define various constants for the ThreadX Cortex-M0 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
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#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
|
||||
|
||||
|
||||
/* 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 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
|
||||
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
|
||||
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 the port extensions of the remaining ThreadX objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_EXTENSION
|
||||
#define TX_BYTE_POOL_EXTENSION
|
||||
#define TX_EVENT_FLAGS_GROUP_EXTENSION
|
||||
#define TX_MUTEX_EXTENSION
|
||||
#define TX_QUEUE_EXTENSION
|
||||
#define TX_SEMAPHORE_EXTENSION
|
||||
#define TX_TIMER_EXTENSION
|
||||
|
||||
|
||||
/* 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
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
|
||||
tx_thread_shell_entry, and tx_thread_terminate. */
|
||||
|
||||
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
|
||||
|
||||
|
||||
/* Define the ThreadX object creation extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Define the ThreadX object deletion extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Define the get system state macro. */
|
||||
|
||||
#ifndef TX_THREAD_GET_SYSTEM_STATE
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
|
||||
__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
|
||||
ULONG _tx_misra_ipsr_get(VOID);
|
||||
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
#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
|
||||
prevent early scheduling on Cortex-M parts. */
|
||||
|
||||
#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++;
|
||||
|
||||
|
||||
#ifndef TX_DISABLE_INLINE
|
||||
|
||||
/* Define GNU specific macros, with in-line assembly for performance. */
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
|
||||
{
|
||||
|
||||
unsigned int primask_value;
|
||||
|
||||
__asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
|
||||
__asm__ volatile (" CPSID i" : : : "memory" );
|
||||
return(primask_value);
|
||||
}
|
||||
|
||||
__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;
|
||||
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_ipsr_value() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
__enable_interrupts();
|
||||
__restore_interrupts(interrupt_save);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = __disable_interrupts();
|
||||
#define TX_RESTORE __restore_interrupts(interrupt_save);
|
||||
|
||||
|
||||
/* Redefine _tx_thread_system_return for improved performance. */
|
||||
|
||||
#define _tx_thread_system_return _tx_thread_system_return_inline
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
|
||||
#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
|
||||
#endif
|
||||
|
||||
|
||||
/* 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-M0/GNU Version 6.0 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
185
ports/cortex_m0/gnu/src/tx_initialize_low_level_sample.S
Executable file
185
ports/cortex_m0/gnu/src/tx_initialize_low_level_sample.S
Executable file
@@ -0,0 +1,185 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/** Initialize */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_initialize.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
@
|
||||
.global _tx_thread_system_stack_ptr
|
||||
.global _tx_initialize_unused_memory
|
||||
.global __RAM_segment_used_end__
|
||||
.global _tx_thread_context_save
|
||||
.global _tx_thread_context_restore
|
||||
.global _tx_timer_interrupt
|
||||
.global _vectors
|
||||
@
|
||||
@
|
||||
SYSTEM_CLOCK = 8000000
|
||||
SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_initialize_low_level Cortex-M0/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* This function is responsible for any low-level processor */
|
||||
@/* initialization, including setting up interrupt vectors, setting */
|
||||
@/* up a periodic timer interrupt source, saving the system stack */
|
||||
@/* pointer for use in ISR processing later, and finding the first */
|
||||
@/* available RAM memory address for tx_application_define. */
|
||||
@/* */
|
||||
@/* INPUT */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* OUTPUT */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* CALLS */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* CALLED BY */
|
||||
@/* */
|
||||
@/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
@/* */
|
||||
@/* RELEASE HISTORY */
|
||||
@/* */
|
||||
@/* DATE NAME DESCRIPTION */
|
||||
@/* */
|
||||
@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_initialize_low_level(VOID)
|
||||
@{
|
||||
.global _tx_initialize_low_level
|
||||
.thumb_func
|
||||
_tx_initialize_low_level:
|
||||
@
|
||||
@ /* Disable interrupts during ThreadX initialization. */
|
||||
@
|
||||
CPSID i
|
||||
@
|
||||
@ /* Set base of available memory to end of non-initialised RAM area. */
|
||||
@
|
||||
LDR r0, =_tx_initialize_unused_memory @ Build address of unused memory pointer
|
||||
LDR r1, =__RAM_segment_used_end__ @ Build first free address
|
||||
ADDS r1, r1, #4 @
|
||||
STR r1, [r0] @ Setup first unused memory pointer
|
||||
@
|
||||
@ /* Enable the cycle count register. */
|
||||
@
|
||||
LDR r0, =0xE0001000 @ Build address of DWT register
|
||||
LDR r1, [r0] @ Pickup the current value
|
||||
MOVS r2, #1
|
||||
ORRS r1, r1, r2 @ Set the CYCCNTENA bit
|
||||
STR r1, [r0] @ Enable the cycle count register
|
||||
@
|
||||
@ /* Setup Vector Table Offset Register. */
|
||||
@
|
||||
LDR r0, =0xE000E000 @ Build address of NVIC registers
|
||||
LDR r2, =0xD08 @ Offset to vector base register
|
||||
ADD r0, r0, r2 @ Build vector base register
|
||||
LDR r1, =_vectors @ Pickup address of vector table
|
||||
STR r1, [r0] @ Set vector table address
|
||||
@
|
||||
@ /* Set system stack pointer from vector value. */
|
||||
@
|
||||
LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer
|
||||
LDR r1, =_vectors @ Pickup address of vector table
|
||||
LDR r1, [r1] @ Pickup reset stack pointer
|
||||
STR r1, [r0] @ Save system stack pointer
|
||||
@
|
||||
@ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */
|
||||
@
|
||||
LDR r0, =0xE000E000 @ Build address of NVIC registers
|
||||
LDR r1, =SYSTICK_CYCLES
|
||||
STR r1, [r0, #0x14] @ Setup SysTick Reload Value
|
||||
LDR r1, =0x7 @ Build SysTick Control Enable Value
|
||||
STR r1, [r0, #0x10] @ Setup SysTick Control
|
||||
@
|
||||
@ /* Configure handler priorities. */
|
||||
@
|
||||
LDR r1, =0x00000000 @ Rsrv, UsgF, BusF, MemM
|
||||
LDR r0, =0xE000E000 @ Build address of NVIC registers
|
||||
LDR r2, =0xD18 @
|
||||
ADD r0, r0, r2 @
|
||||
STR r1, [r0] @ Setup System Handlers 4-7 Priority Registers
|
||||
LDR r1, =0xFF000000 @ SVCl, Rsrv, Rsrv, Rsrv
|
||||
LDR r0, =0xE000E000 @ Build address of NVIC registers
|
||||
LDR r2, =0xD1C @
|
||||
ADD r0, r0, r2 @
|
||||
STR r1, [r0] @ Setup System Handlers 8-11 Priority Registers
|
||||
@ Note: SVC must be lowest priority, which is 0xFF
|
||||
LDR r1, =0x40FF0000 @ SysT, PnSV, Rsrv, DbgM
|
||||
LDR r0, =0xE000E000 @ Build address of NVIC registers
|
||||
LDR r2, =0xD20 @
|
||||
ADD r0, r0, r2 @
|
||||
STR r1, [r0] @ Setup System Handlers 12-15 Priority Registers
|
||||
@ Note: PnSV must be lowest priority, which is 0xFF
|
||||
|
||||
@
|
||||
@ /* Return to caller. */
|
||||
@
|
||||
BX lr
|
||||
@}
|
||||
@
|
||||
@ /* System Tick timer interrupt handler */
|
||||
.global __tx_SysTickHandler
|
||||
.global SysTick_Handler
|
||||
.thumb_func
|
||||
__tx_SysTickHandler:
|
||||
.thumb_func
|
||||
SysTick_Handler:
|
||||
@ VOID SysTick_Handler (VOID)
|
||||
@ {
|
||||
@
|
||||
PUSH {r0, lr}
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_enter @ Call the ISR enter function
|
||||
#endif
|
||||
BL _tx_timer_interrupt
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_exit @ Call the ISR exit function
|
||||
#endif
|
||||
POP {r0, r1}
|
||||
MOV lr, r1
|
||||
BX lr
|
||||
@ }
|
||||
96
ports/cortex_m0/gnu/src/tx_thread_context_restore.S
Executable file
96
ports/cortex_m0/gnu/src/tx_thread_context_restore.S
Executable file
@@ -0,0 +1,96 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
@
|
||||
.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
|
||||
@
|
||||
@
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_context_restore Cortex-M0/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_thread_context_restore(VOID)
|
||||
@{
|
||||
.global _tx_thread_context_restore
|
||||
.thumb_func
|
||||
_tx_thread_context_restore:
|
||||
@
|
||||
@ /* Not needed for this port - just return! */
|
||||
BX lr
|
||||
@}
|
||||
|
||||
90
ports/cortex_m0/gnu/src/tx_thread_context_save.S
Executable file
90
ports/cortex_m0/gnu/src/tx_thread_context_save.S
Executable file
@@ -0,0 +1,90 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
@
|
||||
.global _tx_thread_system_state
|
||||
.global _tx_thread_current_ptr
|
||||
.global _tx_execution_isr_enter
|
||||
@
|
||||
@
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_context_save Cortex-M0/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_thread_context_save(VOID)
|
||||
@{
|
||||
.global _tx_thread_context_save
|
||||
.thumb_func
|
||||
_tx_thread_context_save:
|
||||
@
|
||||
@ /* Not needed for this port - just return! */
|
||||
BX lr
|
||||
@}
|
||||
|
||||
94
ports/cortex_m0/gnu/src/tx_thread_interrupt_control.S
Executable file
94
ports/cortex_m0/gnu/src/tx_thread_interrupt_control.S
Executable file
@@ -0,0 +1,94 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
|
||||
@/* #define TX_SOURCE_CODE */
|
||||
|
||||
|
||||
@/* Include necessary system files. */
|
||||
|
||||
@/* #include "tx_api.h"
|
||||
#include "tx_thread.h" */
|
||||
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_interrupt_control Cortex-M0/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@/* 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
|
||||
|
||||
@/* } */
|
||||
|
||||
|
||||
|
||||
88
ports/cortex_m0/gnu/src/tx_thread_interrupt_disable.S
Executable file
88
ports/cortex_m0/gnu/src/tx_thread_interrupt_disable.S
Executable file
@@ -0,0 +1,88 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
|
||||
@/* #define TX_SOURCE_CODE */
|
||||
|
||||
|
||||
@/* Include necessary system files. */
|
||||
|
||||
@/* #include "tx_api.h"
|
||||
#include "tx_thread.h" */
|
||||
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_interrupt_disable Cortex-M0/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* This function is responsible for disabling interrupts. */
|
||||
@/* */
|
||||
@/* INPUT */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@/* UINT _tx_thread_interrupt_disable(VOID)
|
||||
{ */
|
||||
.global _tx_thread_interrupt_disable
|
||||
.thumb_func
|
||||
_tx_thread_interrupt_disable:
|
||||
|
||||
@/* Pickup current interrupt lockout posture. */
|
||||
|
||||
MRS r0, PRIMASK
|
||||
CPSID i
|
||||
BX lr
|
||||
|
||||
@/* } */
|
||||
|
||||
|
||||
|
||||
86
ports/cortex_m0/gnu/src/tx_thread_interrupt_restore.S
Executable file
86
ports/cortex_m0/gnu/src/tx_thread_interrupt_restore.S
Executable file
@@ -0,0 +1,86 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
|
||||
@/* #define TX_SOURCE_CODE */
|
||||
|
||||
|
||||
@/* Include necessary system files. */
|
||||
|
||||
@/* #include "tx_api.h"
|
||||
#include "tx_thread.h" */
|
||||
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_interrupt_restore Cortex-M0/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* This function is responsible for restoring the interrupt lockout */
|
||||
@/* posture of the system. */
|
||||
@/* */
|
||||
@/* INPUT */
|
||||
@/* */
|
||||
@/* old_posture Old interrupt lockout posture */
|
||||
@/* */
|
||||
@/* OUTPUT */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* CALLS */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* CALLED BY */
|
||||
@/* */
|
||||
@/* Application Code */
|
||||
@/* */
|
||||
@/* RELEASE HISTORY */
|
||||
@/* */
|
||||
@/* DATE NAME DESCRIPTION */
|
||||
@/* */
|
||||
@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@/* VOID _tx_thread_interrupt_restore(UINT old_posture)
|
||||
{ */
|
||||
.global _tx_thread_interrupt_restore
|
||||
.thumb_func
|
||||
_tx_thread_interrupt_restore:
|
||||
|
||||
MSR PRIMASK, r0
|
||||
BX lr
|
||||
|
||||
@/* } */
|
||||
|
||||
|
||||
|
||||
278
ports/cortex_m0/gnu/src/tx_thread_schedule.S
Executable file
278
ports/cortex_m0/gnu/src/tx_thread_schedule.S
Executable file
@@ -0,0 +1,278 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
.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
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_schedule Cortex-M0/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_thread_schedule(VOID)
|
||||
@{
|
||||
.global _tx_thread_schedule
|
||||
.thumb_func
|
||||
_tx_thread_schedule:
|
||||
@
|
||||
@ /* This function should only ever be called on Cortex-M0
|
||||
@ 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. */
|
||||
@
|
||||
MOVS 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
|
||||
@
|
||||
@ /* Enable interrupts */
|
||||
@
|
||||
CPSIE i
|
||||
@
|
||||
@ /* Enter the scheduler for the first time. */
|
||||
@
|
||||
LDR r0, =#0x10000000 @ Load PENDSVSET bit
|
||||
LDR r1, =#0xE000ED04 @ Load NVIC base
|
||||
STR r0, [r1] @ 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. */
|
||||
@
|
||||
.global PendSV_Handler
|
||||
.thumb_func
|
||||
.thumb_func
|
||||
PendSV_Handler:
|
||||
.global __tx_PendSVHandler
|
||||
.global __tx_SVCallHandler
|
||||
.thumb_func
|
||||
__tx_PendSVHandler:
|
||||
.thumb_func
|
||||
__tx_SVCallHandler:
|
||||
@
|
||||
@ /* Get current thread value and new thread pointer. */
|
||||
@
|
||||
.thumb_func
|
||||
__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, r1} @ Recover LR
|
||||
MOV lr, r1 @
|
||||
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
|
||||
MOVS r3, #0 @ Build NULL value
|
||||
LDR r1, [r0] @ Pickup current thread pointer
|
||||
@
|
||||
@ /* Determine if there is a current thread to finish preserving. */
|
||||
@
|
||||
CMP r1,#0 @ If NULL, skip preservation
|
||||
BEQ __tx_ts_new @
|
||||
@
|
||||
@ /* Recover PSP and preserve current thread context. */
|
||||
@
|
||||
STR r3, [r0] @ Set _tx_thread_current_ptr to NULL
|
||||
MRS r3, PSP @ Pickup PSP pointer (thread's stack pointer)
|
||||
SUBS r3, r3, #16 @ Allocate stack space
|
||||
STM r3!, {r4-r7} @ Save its remaining registers (M3 Instruction: STMDB r12!, {r4-r11})
|
||||
MOV r4,r8 @
|
||||
MOV r5,r9 @
|
||||
MOV r6,r10 @
|
||||
MOV r7,r11 @
|
||||
SUBS r3, r3, #32 @ Allocate stack space
|
||||
STM r3!,{r4-r7} @
|
||||
SUBS r3, r3, #20 @ Allocate stack space
|
||||
MOV r5, lr @ Move LR into R4
|
||||
STR r5, [r3] @ Save LR
|
||||
STR r3, [r1, #8] @ Save its stack pointer
|
||||
@
|
||||
@ /* Determine if time-slice is active. If it isn't, skip time handling processing. */
|
||||
@
|
||||
LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
|
||||
LDR r5, [r4] @ Pickup current time-slice
|
||||
CMP r5, #0 @ If not active, skip processing
|
||||
BEQ __tx_ts_new @
|
||||
@
|
||||
@ /* 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. */
|
||||
@
|
||||
MOVS r5, #0 @ Build clear value
|
||||
STR r5, [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?
|
||||
CMP r1, #0 @
|
||||
BEQ __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
|
||||
ADDS 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
|
||||
|
||||
#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
|
||||
#endif
|
||||
@
|
||||
@ /* Restore the thread context and PSP. */
|
||||
@
|
||||
LDR r3, [r1, #8] @ Pickup thread's stack pointer
|
||||
LDR r5, [r3] @ Recover saved LR
|
||||
ADDS r3, r3, #4 @ Position past LR
|
||||
MOV lr, r5 @ Restore LR
|
||||
LDM r3!,{r4-r7} @ Recover thread's registers (r4-r11)
|
||||
MOV r11,r7 @
|
||||
MOV r10,r6 @
|
||||
MOV r9,r5 @
|
||||
MOV r8,r4 @
|
||||
LDM r3!,{r4-r7} @
|
||||
MSR PSP, r3 @ 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
|
||||
CMP r1, #0 @ If non-NULL, a new thread is ready!
|
||||
BNE __tx_ts_ready @
|
||||
#ifdef TX_ENABLE_WFI
|
||||
DSB @ Ensure no outstanding memory transactions
|
||||
WFI @ Wait for interrupt
|
||||
ISB @ Ensure pipeline is flushed
|
||||
#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! */
|
||||
@
|
||||
__tx_ts_ready:
|
||||
LDR r7, =0x08000000 @ Build clear PendSV value
|
||||
LDR r5, =0xE000ED04 @ Build base NVIC address
|
||||
STR r7, [r5] @ Clear any PendSV
|
||||
@
|
||||
@ /* Re-enable interrupts and restore new thread. */
|
||||
@
|
||||
CPSIE i @ Enable interrupts
|
||||
B __tx_ts_restore @ Restore the thread
|
||||
|
||||
149
ports/cortex_m0/gnu/src/tx_thread_stack_build.S
Executable file
149
ports/cortex_m0/gnu/src/tx_thread_stack_build.S
Executable file
@@ -0,0 +1,149 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_stack_build Cortex-M0/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@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-M0 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 (sl) Initial value for r10 (sl)
|
||||
@ 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
|
||||
MOVS r3, #0x7 @
|
||||
BICS r2, r2, r3 @ Align frame for 8-byte alignment
|
||||
SUBS 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. */
|
||||
@
|
||||
MOVS 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
|
||||
LDR r3, [r0, #12] @ Pickup stack starting address
|
||||
STR r3, [r2, #28] @ Store initial r10 (sl)
|
||||
MOVS r3, #0 @ Build initial register value
|
||||
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
|
||||
LDR r3, =0xFFFFFFFF @ Poison EXC_RETURN value
|
||||
STR r3, [r2, #56] @ Store initial lr
|
||||
STR r1, [r2, #60] @ Store initial pc
|
||||
LDR 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
|
||||
@}
|
||||
|
||||
|
||||
97
ports/cortex_m0/gnu/src/tx_thread_system_return.S
Executable file
97
ports/cortex_m0/gnu/src/tx_thread_system_return.S
Executable file
@@ -0,0 +1,97 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@/* #define TX_SOURCE_CODE */
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@/* #include "tx_api.h"
|
||||
@ #include "tx_thread.h"
|
||||
@ #include "tx_timer.h" */
|
||||
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_system_return Cortex-M0/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@/* 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. */
|
||||
@
|
||||
LDR r0, =0x10000000 @ Load PENDSVSET bit
|
||||
LDR r1, =0xE000ED04 @ Load NVIC base
|
||||
STR r0, [r1] @ 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
|
||||
@/* } */
|
||||
|
||||
271
ports/cortex_m0/gnu/src/tx_timer_interrupt.S
Executable file
271
ports/cortex_m0/gnu/src/tx_timer_interrupt.S
Executable file
@@ -0,0 +1,271 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_timer.h"
|
||||
@#include "tx_thread.h"
|
||||
@
|
||||
@
|
||||
@Define Assembly language external references...
|
||||
@
|
||||
.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-M0/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@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
|
||||
ADDS 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--;
|
||||
@
|
||||
SUBS 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
|
||||
MOVS 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
|
||||
MOVS 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++;
|
||||
@
|
||||
ADDS 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
|
||||
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
|
||||
@
|
||||
__tx_something_expired:
|
||||
@
|
||||
@
|
||||
PUSH {r0, lr} @ Save the lr register on the stack
|
||||
@ and save r0 just to keep 8-byte alignment
|
||||
@
|
||||
@ /* Did a timer expire? */
|
||||
@ if (_tx_timer_expired)
|
||||
@ {
|
||||
@
|
||||
LDR r1, =_tx_timer_expired @ Pickup addr of expired flag
|
||||
LDR r0, [r1, #0] @ Pickup timer expired flag
|
||||
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
|
||||
@
|
||||
@ }
|
||||
__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?
|
||||
CMP r1, #0 @
|
||||
BNE __tx_timer_skip_time_slice @ Yes, skip the PendSV logic
|
||||
LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address
|
||||
LDR r1, [r0] @ Pickup the current thread pointer
|
||||
LDR r2, =_tx_thread_execute_ptr @ Build execute thread pointer address
|
||||
LDR r3, [r2] @ Pickup the execute thread pointer
|
||||
LDR r0, =0xE000ED04 @ Build address of control register
|
||||
LDR r2, =0x10000000 @ Build value for PendSV bit
|
||||
CMP r1, r3 @ Are they the same?
|
||||
BEQ __tx_timer_skip_time_slice @ If the same, there was no time-slice performed
|
||||
STR r2, [r0] @ Not the same, issue the PendSV for preemption
|
||||
__tx_timer_skip_time_slice:
|
||||
@
|
||||
@ }
|
||||
@
|
||||
__tx_timer_not_ts_expiration:
|
||||
@
|
||||
POP {r0, r1} @ Recover lr register (r0 is just there for
|
||||
MOV lr, r1 @ the 8-byte stack alignment
|
||||
@
|
||||
@ }
|
||||
@
|
||||
__tx_timer_nothing_expired:
|
||||
|
||||
DSB @ Complete all memory access
|
||||
BX lr @ Return to caller
|
||||
@
|
||||
@}
|
||||
|
||||
|
||||
102
ports/cortex_m0/gnu/src/tx_vector_table_sample.S
Normal file
102
ports/cortex_m0/gnu/src/tx_vector_table_sample.S
Normal file
@@ -0,0 +1,102 @@
|
||||
|
||||
|
||||
.global reset_handler
|
||||
|
||||
.global __tx_NMIHandler
|
||||
.global __tx_BadHandler
|
||||
.global __tx_SVCallHandler
|
||||
.global __tx_DBGHandler
|
||||
.global __tx_PendSVHandler
|
||||
.global __tx_SysTickHandler
|
||||
.global __tx_BadHandler
|
||||
.global __tx_HardfaultHandler
|
||||
|
||||
|
||||
.syntax unified
|
||||
.section .vectors, "ax"
|
||||
.code 16
|
||||
.align 0
|
||||
.global _vectors
|
||||
|
||||
_vectors:
|
||||
.word __stack_end__
|
||||
.word reset_handler
|
||||
.word __tx_NMIHandler
|
||||
.word __tx_HardfaultHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word __tx_SVCallHandler //_SVC_Handler - used by Threadx scheduler //
|
||||
.word __tx_DBGHandler
|
||||
.word 0 // Reserved
|
||||
.word __tx_PendSVHandler
|
||||
.word __tx_SysTickHandler // Used by Threadx timer functionality
|
||||
.word __tx_BadHandler // Populate with user Interrupt handler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
|
||||
|
||||
|
||||
.section .init, "ax"
|
||||
.thumb_func
|
||||
reset_handler:
|
||||
|
||||
// low level hardware config, such as PLL setup goes here
|
||||
|
||||
b _start
|
||||
|
||||
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
|
||||
|
||||
__tx_NMIHandler:
|
||||
b __tx_NMIHandler
|
||||
|
||||
__tx_BadHandler:
|
||||
b __tx_BadHandler
|
||||
|
||||
__tx_DBGHandler:
|
||||
b __tx_DBGHandler
|
||||
|
||||
__tx_HardfaultHandler:
|
||||
b __tx_HardfaultHandler
|
||||
|
||||
19
ports/cortex_m3/gnu/CMakeLists.txt
Normal file
19
ports/cortex_m3/gnu/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
# {{BEGIN_TARGET_SOURCES}}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S
|
||||
|
||||
# {{END_TARGET_SOURCES}}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc
|
||||
)
|
||||
357
ports/cortex_m3/gnu/inc/tx_port.h
Normal file
357
ports/cortex_m3/gnu/inc/tx_port.h
Normal file
@@ -0,0 +1,357 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Port Specific */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M3/GNU */
|
||||
/* 6.0 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains data type definitions that make the ThreadX */
|
||||
/* real-time kernel function identically on a variety of different */
|
||||
/* processor architectures. For example, the size or number of bits */
|
||||
/* in an "int" data type vary between microprocessor architectures and */
|
||||
/* even C compilers for the same microprocessor. ThreadX does not */
|
||||
/* directly use native C data types. Instead, ThreadX creates its */
|
||||
/* own special types that can be mapped to actual data types by this */
|
||||
/* file to guarantee consistency in the interface and functionality. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_PORT_H
|
||||
#define TX_PORT_H
|
||||
|
||||
|
||||
/* Determine if the optional ThreadX user define file should be used. */
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
|
||||
/* 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"
|
||||
#endif
|
||||
|
||||
|
||||
/* Define compiler library include files. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Define ThreadX basic types for this port. */
|
||||
|
||||
#define VOID void
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef long LONG;
|
||||
typedef unsigned long ULONG;
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
|
||||
|
||||
/* Define the priority levels for ThreadX. Legal values range
|
||||
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||
|
||||
#ifndef TX_MAX_PRIORITIES
|
||||
#define TX_MAX_PRIORITIES 32
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||
thread creation is less than this value, the thread create call will return an error. */
|
||||
|
||||
#ifndef TX_MINIMUM_STACK
|
||||
#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||
|
||||
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
|
||||
#endif
|
||||
|
||||
#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 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
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
#endif
|
||||
|
||||
|
||||
/* 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 the in-line initialization constant so that modules with in-line
|
||||
initialization capabilities can prevent their initialization from being
|
||||
a function call. */
|
||||
|
||||
#define TX_INLINE_INITIALIZATION
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
#undef TX_DISABLE_STACK_FILLING
|
||||
#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
|
||||
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 the port extensions of the remaining ThreadX objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_EXTENSION
|
||||
#define TX_BYTE_POOL_EXTENSION
|
||||
#define TX_EVENT_FLAGS_GROUP_EXTENSION
|
||||
#define TX_MUTEX_EXTENSION
|
||||
#define TX_QUEUE_EXTENSION
|
||||
#define TX_SEMAPHORE_EXTENSION
|
||||
#define TX_TIMER_EXTENSION
|
||||
|
||||
|
||||
/* 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
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
|
||||
tx_thread_shell_entry, and tx_thread_terminate. */
|
||||
|
||||
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
|
||||
|
||||
|
||||
/* Define the ThreadX object creation extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Define the ThreadX object deletion extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Define the get system state macro. */
|
||||
|
||||
#ifndef TX_THREAD_GET_SYSTEM_STATE
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
|
||||
__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
|
||||
ULONG _tx_misra_ipsr_get(VOID);
|
||||
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
#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
|
||||
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 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. */
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
|
||||
{
|
||||
|
||||
unsigned int primask_value;
|
||||
|
||||
__asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
|
||||
__asm__ volatile (" CPSID i" : : : "memory" );
|
||||
return(primask_value);
|
||||
}
|
||||
|
||||
__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;
|
||||
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_ipsr_value() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
__enable_interrupts();
|
||||
__restore_interrupts(interrupt_save);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = __disable_interrupts();
|
||||
#define TX_RESTORE __restore_interrupts(interrupt_save);
|
||||
|
||||
|
||||
/* Redefine _tx_thread_system_return for improved performance. */
|
||||
|
||||
#define _tx_thread_system_return _tx_thread_system_return_inline
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
|
||||
#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
|
||||
#endif
|
||||
|
||||
|
||||
/* 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-M3/GNU Version 6.0 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
244
ports/cortex_m3/gnu/src/tx_initialize_low_level_sample.S
Normal file
244
ports/cortex_m3/gnu/src/tx_initialize_low_level_sample.S
Normal file
@@ -0,0 +1,244 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/** Initialize */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_initialize.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
@
|
||||
.global _tx_thread_system_stack_ptr
|
||||
.global _tx_initialize_unused_memory
|
||||
.global __RAM_segment_used_end__
|
||||
.global _tx_timer_interrupt
|
||||
.global __main
|
||||
.global __tx_SVCallHandler
|
||||
.global __tx_PendSVHandler
|
||||
.global _vectors
|
||||
.global __tx_NMIHandler @ NMI
|
||||
.global __tx_BadHandler @ HardFault
|
||||
.global __tx_SVCallHandler @ SVCall
|
||||
.global __tx_DBGHandler @ Monitor
|
||||
.global __tx_PendSVHandler @ PendSV
|
||||
.global __tx_SysTickHandler @ SysTick
|
||||
.global __tx_IntHandler @ Int 0
|
||||
@
|
||||
@
|
||||
SYSTEM_CLOCK = 6000000
|
||||
SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_initialize_low_level Cortex-M3/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* This function is responsible for any low-level processor */
|
||||
@/* initialization, including setting up interrupt vectors, setting */
|
||||
@/* up a periodic timer interrupt source, saving the system stack */
|
||||
@/* pointer for use in ISR processing later, and finding the first */
|
||||
@/* available RAM memory address for tx_application_define. */
|
||||
@/* */
|
||||
@/* INPUT */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* OUTPUT */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* CALLS */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* CALLED BY */
|
||||
@/* */
|
||||
@/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
@/* */
|
||||
@/* RELEASE HISTORY */
|
||||
@/* */
|
||||
@/* DATE NAME DESCRIPTION */
|
||||
@/* */
|
||||
@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_initialize_low_level(VOID)
|
||||
@{
|
||||
.global _tx_initialize_low_level
|
||||
.thumb_func
|
||||
_tx_initialize_low_level:
|
||||
@
|
||||
@ /* Disable interrupts during ThreadX initialization. */
|
||||
@
|
||||
CPSID i
|
||||
@
|
||||
@ /* Set base of available memory to end of non-initialised RAM area. */
|
||||
@
|
||||
LDR r0, =_tx_initialize_unused_memory @ Build address of unused memory pointer
|
||||
LDR r1, =__RAM_segment_used_end__ @ Build first free address
|
||||
ADD r1, r1, #4 @
|
||||
STR r1, [r0] @ Setup first unused memory pointer
|
||||
@
|
||||
@ /* Setup Vector Table Offset Register. */
|
||||
@
|
||||
MOV r0, #0xE000E000 @ Build address of NVIC registers
|
||||
LDR r1, =_vectors @ Pickup address of vector table
|
||||
STR r1, [r0, #0xD08] @ Set vector table address
|
||||
@
|
||||
@ /* Set system stack pointer from vector value. */
|
||||
@
|
||||
LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer
|
||||
LDR r1, =_vectors @ Pickup address of vector table
|
||||
LDR r1, [r1] @ Pickup reset stack pointer
|
||||
STR r1, [r0] @ Save system stack pointer
|
||||
@
|
||||
@ /* Enable the cycle count register. */
|
||||
@
|
||||
LDR r0, =0xE0001000 @ Build address of DWT register
|
||||
LDR r1, [r0] @ Pickup the current value
|
||||
ORR r1, r1, #1 @ Set the CYCCNTENA bit
|
||||
STR r1, [r0] @ Enable the cycle count register
|
||||
@
|
||||
@ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */
|
||||
@
|
||||
MOV r0, #0xE000E000 @ Build address of NVIC registers
|
||||
LDR r1, =SYSTICK_CYCLES
|
||||
STR r1, [r0, #0x14] @ Setup SysTick Reload Value
|
||||
MOV r1, #0x7 @ Build SysTick Control Enable Value
|
||||
STR r1, [r0, #0x10] @ Setup SysTick Control
|
||||
@
|
||||
@ /* Configure handler priorities. */
|
||||
@
|
||||
LDR r1, =0x00000000 @ Rsrv, UsgF, BusF, MemM
|
||||
STR r1, [r0, #0xD18] @ Setup System Handlers 4-7 Priority Registers
|
||||
|
||||
LDR r1, =0xFF000000 @ SVCl, Rsrv, Rsrv, Rsrv
|
||||
STR r1, [r0, #0xD1C] @ Setup System Handlers 8-11 Priority Registers
|
||||
@ Note: SVC must be lowest priority, which is 0xFF
|
||||
|
||||
LDR r1, =0x40FF0000 @ SysT, PnSV, Rsrv, DbgM
|
||||
STR r1, [r0, #0xD20] @ Setup System Handlers 12-15 Priority Registers
|
||||
@ Note: PnSV must be lowest priority, which is 0xFF
|
||||
|
||||
@
|
||||
@ /* Return to caller. */
|
||||
@
|
||||
BX lr
|
||||
@}
|
||||
@
|
||||
|
||||
@/* Define shells for each of the unused vectors. */
|
||||
@
|
||||
.global __tx_BadHandler
|
||||
.thumb_func
|
||||
__tx_BadHandler:
|
||||
B __tx_BadHandler
|
||||
|
||||
@ /* added to catch the hardfault */
|
||||
|
||||
.global __tx_HardfaultHandler
|
||||
.thumb_func
|
||||
__tx_HardfaultHandler:
|
||||
B __tx_HardfaultHandler
|
||||
|
||||
|
||||
@ /* added to catch the SVC */
|
||||
|
||||
.global __tx_SVCallHandler
|
||||
.thumb_func
|
||||
__tx_SVCallHandler:
|
||||
B __tx_SVCallHandler
|
||||
|
||||
|
||||
@ /* Generic interrupt handler template */
|
||||
.global __tx_IntHandler
|
||||
.thumb_func
|
||||
__tx_IntHandler:
|
||||
@ VOID InterruptHandler (VOID)
|
||||
@ {
|
||||
PUSH {r0, lr}
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_enter ; Call the ISR enter function
|
||||
#endif
|
||||
|
||||
@ /* Do interrupt handler work here */
|
||||
@ /* BL <your C Function>.... */
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_exit ; Call the ISR exit function
|
||||
#endif
|
||||
POP {r0, lr}
|
||||
BX LR
|
||||
@ }
|
||||
|
||||
@ /* System Tick timer interrupt handler */
|
||||
.global __tx_SysTickHandler
|
||||
.global SysTick_Handler
|
||||
.thumb_func
|
||||
__tx_SysTickHandler:
|
||||
.thumb_func
|
||||
SysTick_Handler:
|
||||
@ VOID TimerInterruptHandler (VOID)
|
||||
@ {
|
||||
@
|
||||
PUSH {r0, lr}
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_enter ; Call the ISR enter function
|
||||
#endif
|
||||
BL _tx_timer_interrupt
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_exit ; Call the ISR exit function
|
||||
#endif
|
||||
POP {r0, lr}
|
||||
BX LR
|
||||
@ }
|
||||
|
||||
|
||||
@ /* NMI, DBG handlers */
|
||||
.global __tx_NMIHandler
|
||||
.thumb_func
|
||||
__tx_NMIHandler:
|
||||
B __tx_NMIHandler
|
||||
|
||||
.global __tx_DBGHandler
|
||||
.thumb_func
|
||||
__tx_DBGHandler:
|
||||
B __tx_DBGHandler
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
96
ports/cortex_m3/gnu/src/tx_thread_context_restore.S
Normal file
96
ports/cortex_m3/gnu/src/tx_thread_context_restore.S
Normal file
@@ -0,0 +1,96 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
@
|
||||
.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
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_context_restore Cortex-M3/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_thread_context_restore(VOID)
|
||||
@{
|
||||
.global _tx_thread_context_restore
|
||||
.thumb_func
|
||||
_tx_thread_context_restore:
|
||||
@
|
||||
@ /* Not needed for this port - just return! */
|
||||
BX lr
|
||||
@}
|
||||
|
||||
89
ports/cortex_m3/gnu/src/tx_thread_context_save.S
Normal file
89
ports/cortex_m3/gnu/src/tx_thread_context_save.S
Normal file
@@ -0,0 +1,89 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
@
|
||||
.global _tx_thread_system_state
|
||||
.global _tx_thread_current_ptr
|
||||
.global _tx_execution_isr_enter
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_context_save Cortex-M3/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_thread_context_save(VOID)
|
||||
@{
|
||||
.global _tx_thread_context_save
|
||||
.thumb_func
|
||||
_tx_thread_context_save:
|
||||
@
|
||||
@ /* Not needed for this port - just return! */
|
||||
BX lr
|
||||
@}
|
||||
92
ports/cortex_m3/gnu/src/tx_thread_interrupt_control.S
Normal file
92
ports/cortex_m3/gnu/src/tx_thread_interrupt_control.S
Normal file
@@ -0,0 +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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
|
||||
@/* #define TX_SOURCE_CODE */
|
||||
|
||||
|
||||
@/* Include necessary system files. */
|
||||
|
||||
@/* #include "tx_api.h"
|
||||
#include "tx_thread.h" */
|
||||
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_interrupt_control Cortex-M3/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@/* 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
|
||||
|
||||
@/* } */
|
||||
|
||||
|
||||
|
||||
252
ports/cortex_m3/gnu/src/tx_thread_schedule.S
Normal file
252
ports/cortex_m3/gnu/src/tx_thread_schedule.S
Normal file
@@ -0,0 +1,252 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
.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
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_schedule Cortex-M3/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_thread_schedule(VOID)
|
||||
@{
|
||||
.global _tx_thread_schedule
|
||||
.thumb_func
|
||||
_tx_thread_schedule:
|
||||
@
|
||||
@ /* This function should only ever be called on Cortex-M3
|
||||
@ 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
|
||||
@
|
||||
@ /* Enable interrupts */
|
||||
@
|
||||
CPSIE i
|
||||
@
|
||||
@ /* Enter the scheduler for the first time. */
|
||||
@
|
||||
MOV r0, #0x10000000 @ Load PENDSVSET bit
|
||||
MOV r1, #0xE000E000 @ Load NVIC base
|
||||
STR r0, [r1, #0xD04] @ Set PENDSVBIT in ICSR
|
||||
DSB @ Complete all memory accesses
|
||||
ISB @ Flush pipeline
|
||||
@
|
||||
@ /* Wait here for the PendSV to take place. */
|
||||
@
|
||||
__tx_wait_here:
|
||||
B __tx_wait_here @ Wait for the PendSV to happen
|
||||
@}
|
||||
@
|
||||
@ /* Generic context switch-out switch-in handler... Note that this handler is
|
||||
@ common for both PendSV and SVCall. */
|
||||
@
|
||||
.global PendSV_Handler
|
||||
.global __tx_PendSVHandler
|
||||
.thumb_func
|
||||
PendSV_Handler:
|
||||
.thumb_func
|
||||
__tx_PendSVHandler:
|
||||
@
|
||||
@ /* 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
|
||||
#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
|
||||
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
|
||||
|
||||
#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
|
||||
#endif
|
||||
@
|
||||
@ /* Restore the thread context and PSP. */
|
||||
@
|
||||
LDR r12, [r1, #8] @ Pickup thread's stack pointer
|
||||
LDMIA r12!, {LR} @ Pickup LR
|
||||
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!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
DSB @ Ensure no outstanding memory transactions
|
||||
WFI @ Wait for interrupt
|
||||
ISB @ Ensure pipeline is flushed
|
||||
#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! */
|
||||
@
|
||||
__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
|
||||
|
||||
148
ports/cortex_m3/gnu/src/tx_thread_stack_build.S
Normal file
148
ports/cortex_m3/gnu/src/tx_thread_stack_build.S
Normal file
@@ -0,0 +1,148 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_stack_build Cortex-M3/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@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-M3 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 (sl) Initial value for r10 (sl)
|
||||
@ 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
|
||||
LDR r3, [r0, #12] @ Pickup stack starting address
|
||||
STR r3, [r2, #28] @ Store initial r10 (sl)
|
||||
MOV r3, #0 @ Build initial register value
|
||||
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
|
||||
@}
|
||||
|
||||
|
||||
98
ports/cortex_m3/gnu/src/tx_thread_system_return.S
Normal file
98
ports/cortex_m3/gnu/src/tx_thread_system_return.S
Normal file
@@ -0,0 +1,98 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@/* #define TX_SOURCE_CODE */
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@/* #include "tx_api.h"
|
||||
@ #include "tx_thread.h"
|
||||
@ #include "tx_timer.h" */
|
||||
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_system_return Cortex-M3/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@/* 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
|
||||
|
||||
@/* } */
|
||||
|
||||
270
ports/cortex_m3/gnu/src/tx_timer_interrupt.S
Normal file
270
ports/cortex_m3/gnu/src/tx_timer_interrupt.S
Normal file
@@ -0,0 +1,270 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_timer.h"
|
||||
@#include "tx_thread.h"
|
||||
@
|
||||
@
|
||||
@Define Assembly language external references...
|
||||
@
|
||||
.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-M3/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@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
|
||||
@
|
||||
@ }
|
||||
@
|
||||
__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
|
||||
@ {
|
||||
__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
|
||||
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
|
||||
@
|
||||
__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
|
||||
@
|
||||
@ }
|
||||
__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
|
||||
__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
|
||||
@
|
||||
@ }
|
||||
@
|
||||
__tx_timer_nothing_expired:
|
||||
|
||||
DSB @ Complete all memory access
|
||||
BX lr @ Return to caller
|
||||
@
|
||||
@}
|
||||
|
||||
|
||||
84
ports/cortex_m3/gnu/src/tx_vector_table_sample.S
Normal file
84
ports/cortex_m3/gnu/src/tx_vector_table_sample.S
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
|
||||
.global reset_handler
|
||||
|
||||
.global __tx_NMIHandler
|
||||
.global __tx_BadHandler
|
||||
.global __tx_SVCallHandler
|
||||
.global __tx_DBGHandler
|
||||
.global __tx_PendSVHandler
|
||||
.global __tx_SysTickHandler
|
||||
.global __tx_BadHandler
|
||||
|
||||
|
||||
.syntax unified
|
||||
.section .vectors, "ax"
|
||||
.code 16
|
||||
.align 0
|
||||
.global _vectors
|
||||
|
||||
_vectors:
|
||||
.word __stack_end__
|
||||
.word reset_handler
|
||||
.word __tx_NMIHandler
|
||||
.word __tx_HardfaultHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word __tx_SVCallHandler //_SVC_Handler - used by Threadx scheduler //
|
||||
.word __tx_DBGHandler
|
||||
.word 0 // Reserved
|
||||
.word __tx_PendSVHandler
|
||||
.word __tx_SysTickHandler // Used by Threadx timer functionality
|
||||
.word __tx_BadHandler // Populate with user Interrupt handler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
|
||||
|
||||
|
||||
.section .init, "ax"
|
||||
.thumb_func
|
||||
reset_handler:
|
||||
|
||||
// low level hardware config, such as PLL setup goes here
|
||||
|
||||
b _start
|
||||
|
||||
|
||||
|
||||
19
ports/cortex_m4/gnu/CMakeLists.txt
Normal file
19
ports/cortex_m4/gnu/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
# {{BEGIN_TARGET_SOURCES}}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S
|
||||
|
||||
# {{END_TARGET_SOURCES}}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc
|
||||
)
|
||||
499
ports/cortex_m4/gnu/inc/tx_port.h
Normal file
499
ports/cortex_m4/gnu/inc/tx_port.h
Normal file
@@ -0,0 +1,499 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Port Specific */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M4/GNU */
|
||||
/* 6.0 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains data type definitions that make the ThreadX */
|
||||
/* real-time kernel function identically on a variety of different */
|
||||
/* processor architectures. For example, the size or number of bits */
|
||||
/* in an "int" data type vary between microprocessor architectures and */
|
||||
/* even C compilers for the same microprocessor. ThreadX does not */
|
||||
/* directly use native C data types. Instead, ThreadX creates its */
|
||||
/* own special types that can be mapped to actual data types by this */
|
||||
/* file to guarantee consistency in the interface and functionality. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_PORT_H
|
||||
#define TX_PORT_H
|
||||
|
||||
|
||||
/* Determine if the optional ThreadX user define file should be used. */
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
|
||||
/* 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"
|
||||
#endif
|
||||
|
||||
|
||||
/* Define compiler library include files. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Define ThreadX basic types for this port. */
|
||||
|
||||
#define VOID void
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef long LONG;
|
||||
typedef unsigned long ULONG;
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
|
||||
|
||||
/* Define the priority levels for ThreadX. Legal values range
|
||||
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||
|
||||
#ifndef TX_MAX_PRIORITIES
|
||||
#define TX_MAX_PRIORITIES 32
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||
thread creation is less than this value, the thread create call will return an error. */
|
||||
|
||||
#ifndef TX_MINIMUM_STACK
|
||||
#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||
|
||||
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
|
||||
#endif
|
||||
|
||||
#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 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
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
#endif
|
||||
|
||||
|
||||
/* 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 the in-line initialization constant so that modules with in-line
|
||||
initialization capabilities can prevent their initialization from being
|
||||
a function call. */
|
||||
|
||||
#define TX_INLINE_INITIALIZATION
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
#undef TX_DISABLE_STACK_FILLING
|
||||
#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
|
||||
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 the port extensions of the remaining ThreadX objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_EXTENSION
|
||||
#define TX_BYTE_POOL_EXTENSION
|
||||
#define TX_EVENT_FLAGS_GROUP_EXTENSION
|
||||
#define TX_MUTEX_EXTENSION
|
||||
#define TX_QUEUE_EXTENSION
|
||||
#define TX_SEMAPHORE_EXTENSION
|
||||
#define TX_TIMER_EXTENSION
|
||||
|
||||
|
||||
/* 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
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
|
||||
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_FPU_SUPPORT
|
||||
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
|
||||
ULONG _tx_misra_control_get(void);
|
||||
void _tx_misra_control_set(ULONG value);
|
||||
ULONG _tx_misra_fpccr_get(void);
|
||||
void _tx_misra_vfp_touch(void);
|
||||
|
||||
#else
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline ULONG __get_control(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)
|
||||
{
|
||||
|
||||
__asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" );
|
||||
}
|
||||
|
||||
|
||||
#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 = __get_control(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
__set_control(_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
|
||||
|
||||
|
||||
/* 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
|
||||
this one, so if the FPCCR.LSPACT bit is set, we need to save the CONTROL.FPCA state, touch the FPU to flush
|
||||
the lazy FPU save, then restore the CONTROL.FPCA state. */
|
||||
|
||||
#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); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#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); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/* Define the ThreadX object creation extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Define the ThreadX object deletion extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Define the get system state macro. */
|
||||
|
||||
#ifndef TX_THREAD_GET_SYSTEM_STATE
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
|
||||
__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
|
||||
ULONG _tx_misra_ipsr_get(VOID);
|
||||
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
#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
|
||||
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 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. */
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
|
||||
{
|
||||
|
||||
unsigned int primask_value;
|
||||
|
||||
__asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
|
||||
__asm__ volatile (" CPSID i" : : : "memory" );
|
||||
return(primask_value);
|
||||
}
|
||||
|
||||
__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;
|
||||
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_ipsr_value() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
__enable_interrupts();
|
||||
__restore_interrupts(interrupt_save);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = __disable_interrupts();
|
||||
#define TX_RESTORE __restore_interrupts(interrupt_save);
|
||||
|
||||
|
||||
/* Redefine _tx_thread_system_return for improved performance. */
|
||||
|
||||
#define _tx_thread_system_return _tx_thread_system_return_inline
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
|
||||
#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
|
||||
#endif
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
void tx_thread_fpu_enable(void);
|
||||
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.0 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
240
ports/cortex_m4/gnu/src/tx_initialize_low_level_sample.S
Normal file
240
ports/cortex_m4/gnu/src/tx_initialize_low_level_sample.S
Normal file
@@ -0,0 +1,240 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/** Initialize */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_initialize.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
@
|
||||
.global _tx_thread_system_stack_ptr
|
||||
.global _tx_initialize_unused_memory
|
||||
.global __RAM_segment_used_end__
|
||||
.global _tx_timer_interrupt
|
||||
.global __main
|
||||
.global __tx_SVCallHandler
|
||||
.global __tx_PendSVHandler
|
||||
.global _vectors
|
||||
.global __tx_NMIHandler @ NMI
|
||||
.global __tx_BadHandler @ HardFault
|
||||
.global __tx_SVCallHandler @ SVCall
|
||||
.global __tx_DBGHandler @ Monitor
|
||||
.global __tx_PendSVHandler @ PendSV
|
||||
.global __tx_SysTickHandler @ SysTick
|
||||
.global __tx_IntHandler @ Int 0
|
||||
@
|
||||
@
|
||||
SYSTEM_CLOCK = 6000000
|
||||
SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_initialize_low_level Cortex-M4/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* This function is responsible for any low-level processor */
|
||||
@/* initialization, including setting up interrupt vectors, setting */
|
||||
@/* up a periodic timer interrupt source, saving the system stack */
|
||||
@/* pointer for use in ISR processing later, and finding the first */
|
||||
@/* available RAM memory address for tx_application_define. */
|
||||
@/* */
|
||||
@/* INPUT */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* OUTPUT */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* CALLS */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* CALLED BY */
|
||||
@/* */
|
||||
@/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
@/* */
|
||||
@/* RELEASE HISTORY */
|
||||
@/* */
|
||||
@/* DATE NAME DESCRIPTION */
|
||||
@/* */
|
||||
@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_initialize_low_level(VOID)
|
||||
@{
|
||||
.global _tx_initialize_low_level
|
||||
.thumb_func
|
||||
_tx_initialize_low_level:
|
||||
@
|
||||
@ /* Disable interrupts during ThreadX initialization. */
|
||||
@
|
||||
CPSID i
|
||||
@
|
||||
@ /* Set base of available memory to end of non-initialised RAM area. */
|
||||
@
|
||||
LDR r0, =_tx_initialize_unused_memory @ Build address of unused memory pointer
|
||||
LDR r1, =__RAM_segment_used_end__ @ Build first free address
|
||||
ADD r1, r1, #4 @
|
||||
STR r1, [r0] @ Setup first unused memory pointer
|
||||
@
|
||||
@ /* Setup Vector Table Offset Register. */
|
||||
@
|
||||
MOV r0, #0xE000E000 @ Build address of NVIC registers
|
||||
LDR r1, =_vectors @ Pickup address of vector table
|
||||
STR r1, [r0, #0xD08] @ Set vector table address
|
||||
@
|
||||
@ /* Set system stack pointer from vector value. */
|
||||
@
|
||||
LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer
|
||||
LDR r1, =_vectors @ Pickup address of vector table
|
||||
LDR r1, [r1] @ Pickup reset stack pointer
|
||||
STR r1, [r0] @ Save system stack pointer
|
||||
@
|
||||
@ /* Enable the cycle count register. */
|
||||
@
|
||||
LDR r0, =0xE0001000 @ Build address of DWT register
|
||||
LDR r1, [r0] @ Pickup the current value
|
||||
ORR r1, r1, #1 @ Set the CYCCNTENA bit
|
||||
STR r1, [r0] @ Enable the cycle count register
|
||||
@
|
||||
@ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */
|
||||
@
|
||||
MOV r0, #0xE000E000 @ Build address of NVIC registers
|
||||
LDR r1, =SYSTICK_CYCLES
|
||||
STR r1, [r0, #0x14] @ Setup SysTick Reload Value
|
||||
MOV r1, #0x7 @ Build SysTick Control Enable Value
|
||||
STR r1, [r0, #0x10] @ Setup SysTick Control
|
||||
@
|
||||
@ /* Configure handler priorities. */
|
||||
@
|
||||
LDR r1, =0x00000000 @ Rsrv, UsgF, BusF, MemM
|
||||
STR r1, [r0, #0xD18] @ Setup System Handlers 4-7 Priority Registers
|
||||
|
||||
LDR r1, =0xFF000000 @ SVCl, Rsrv, Rsrv, Rsrv
|
||||
STR r1, [r0, #0xD1C] @ Setup System Handlers 8-11 Priority Registers
|
||||
@ Note: SVC must be lowest priority, which is 0xFF
|
||||
|
||||
LDR r1, =0x40FF0000 @ SysT, PnSV, Rsrv, DbgM
|
||||
STR r1, [r0, #0xD20] @ Setup System Handlers 12-15 Priority Registers
|
||||
@ Note: PnSV must be lowest priority, which is 0xFF
|
||||
|
||||
@
|
||||
@ /* Return to caller. */
|
||||
@
|
||||
BX lr
|
||||
@}
|
||||
@
|
||||
|
||||
@/* Define shells for each of the unused vectors. */
|
||||
@
|
||||
.global __tx_BadHandler
|
||||
.thumb_func
|
||||
__tx_BadHandler:
|
||||
B __tx_BadHandler
|
||||
|
||||
@ /* added to catch the hardfault */
|
||||
|
||||
.global __tx_HardfaultHandler
|
||||
.thumb_func
|
||||
__tx_HardfaultHandler:
|
||||
B __tx_HardfaultHandler
|
||||
|
||||
|
||||
@ /* added to catch the SVC */
|
||||
|
||||
.global __tx_SVCallHandler
|
||||
.thumb_func
|
||||
__tx_SVCallHandler:
|
||||
B __tx_SVCallHandler
|
||||
|
||||
|
||||
@ /* Generic interrupt handler template */
|
||||
.global __tx_IntHandler
|
||||
.thumb_func
|
||||
__tx_IntHandler:
|
||||
@ VOID InterruptHandler (VOID)
|
||||
@ {
|
||||
PUSH {r0, lr}
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_enter ; Call the ISR enter function
|
||||
#endif
|
||||
|
||||
@ /* Do interrupt handler work here */
|
||||
@ /* BL <your C Function>.... */
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_exit ; Call the ISR exit function
|
||||
#endif
|
||||
POP {r0, lr}
|
||||
BX LR
|
||||
@ }
|
||||
|
||||
@ /* System Tick timer interrupt handler */
|
||||
.global __tx_SysTickHandler
|
||||
.global SysTick_Handler
|
||||
.thumb_func
|
||||
__tx_SysTickHandler:
|
||||
.thumb_func
|
||||
SysTick_Handler:
|
||||
@ VOID TimerInterruptHandler (VOID)
|
||||
@ {
|
||||
@
|
||||
PUSH {r0, lr}
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_enter ; Call the ISR enter function
|
||||
#endif
|
||||
BL _tx_timer_interrupt
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_exit ; Call the ISR exit function
|
||||
#endif
|
||||
POP {r0, lr}
|
||||
BX LR
|
||||
@ }
|
||||
|
||||
|
||||
@ /* NMI, DBG handlers */
|
||||
.global __tx_NMIHandler
|
||||
.thumb_func
|
||||
__tx_NMIHandler:
|
||||
B __tx_NMIHandler
|
||||
|
||||
.global __tx_DBGHandler
|
||||
.thumb_func
|
||||
__tx_DBGHandler:
|
||||
B __tx_DBGHandler
|
||||
|
||||
96
ports/cortex_m4/gnu/src/tx_thread_context_restore.S
Normal file
96
ports/cortex_m4/gnu/src/tx_thread_context_restore.S
Normal file
@@ -0,0 +1,96 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
@
|
||||
.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
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_context_restore Cortex-M4/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_thread_context_restore(VOID)
|
||||
@{
|
||||
.global _tx_thread_context_restore
|
||||
.thumb_func
|
||||
_tx_thread_context_restore:
|
||||
@
|
||||
@ /* Not needed for this port - just return! */
|
||||
BX lr
|
||||
@}
|
||||
|
||||
89
ports/cortex_m4/gnu/src/tx_thread_context_save.S
Normal file
89
ports/cortex_m4/gnu/src/tx_thread_context_save.S
Normal file
@@ -0,0 +1,89 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
@
|
||||
.global _tx_thread_system_state
|
||||
.global _tx_thread_current_ptr
|
||||
.global _tx_execution_isr_enter
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_context_save Cortex-M4/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_thread_context_save(VOID)
|
||||
@{
|
||||
.global _tx_thread_context_save
|
||||
.thumb_func
|
||||
_tx_thread_context_save:
|
||||
@
|
||||
@ /* Not needed for this port - just return! */
|
||||
BX lr
|
||||
@}
|
||||
92
ports/cortex_m4/gnu/src/tx_thread_interrupt_control.S
Normal file
92
ports/cortex_m4/gnu/src/tx_thread_interrupt_control.S
Normal file
@@ -0,0 +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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
|
||||
@/* #define TX_SOURCE_CODE */
|
||||
|
||||
|
||||
@/* Include necessary system files. */
|
||||
|
||||
@/* #include "tx_api.h"
|
||||
#include "tx_thread.h" */
|
||||
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_interrupt_control Cortex-M4/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@/* 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
|
||||
|
||||
@/* } */
|
||||
|
||||
|
||||
|
||||
296
ports/cortex_m4/gnu/src/tx_thread_schedule.S
Normal file
296
ports/cortex_m4/gnu/src/tx_thread_schedule.S
Normal file
@@ -0,0 +1,296 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
.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
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_schedule Cortex-M4/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@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
|
||||
#endif
|
||||
@
|
||||
@ /* Enable interrupts */
|
||||
@
|
||||
CPSIE i
|
||||
@
|
||||
@ /* Enter the scheduler for the first time. */
|
||||
@
|
||||
MOV r0, #0x10000000 @ Load PENDSVSET bit
|
||||
MOV r1, #0xE000E000 @ Load NVIC base
|
||||
STR r0, [r1, #0xD04] @ Set PENDSVBIT in ICSR
|
||||
DSB @ Complete all memory accesses
|
||||
ISB @ Flush pipeline
|
||||
@
|
||||
@ /* Wait here for the PendSV to take place. */
|
||||
@
|
||||
__tx_wait_here:
|
||||
B __tx_wait_here @ Wait for the PendSV to happen
|
||||
@}
|
||||
@
|
||||
@ /* Generic context switch-out switch-in handler... Note that this handler is
|
||||
@ common for both PendSV and SVCall. */
|
||||
@
|
||||
.global PendSV_Handler
|
||||
.global __tx_PendSVHandler
|
||||
.thumb_func
|
||||
PendSV_Handler:
|
||||
.thumb_func
|
||||
__tx_PendSVHandler:
|
||||
@
|
||||
@ /* 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
|
||||
#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
|
||||
BNE _skip_vfp_save
|
||||
VSTMDB r12!,{s16-s31} @ Yes, save additional VFP registers
|
||||
_skip_vfp_save:
|
||||
#endif
|
||||
LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
|
||||
STMDB r12!, {LR} @ Save LR on the stack
|
||||
@
|
||||
@ /* 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
|
||||
|
||||
#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
|
||||
#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
|
||||
_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. */
|
||||
@
|
||||
__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!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
DSB @ Ensure no outstanding memory transactions
|
||||
WFI @ Wait for interrupt
|
||||
ISB @ Ensure pipeline is flushed
|
||||
#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! */
|
||||
@
|
||||
__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
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_FPU_SUPPORT
|
||||
|
||||
.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
|
||||
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
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
148
ports/cortex_m4/gnu/src/tx_thread_stack_build.S
Normal file
148
ports/cortex_m4/gnu/src/tx_thread_stack_build.S
Normal file
@@ -0,0 +1,148 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_stack_build Cortex-M4/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@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 (sl) Initial value for r10 (sl)
|
||||
@ 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
|
||||
LDR r3, [r0, #12] @ Pickup stack starting address
|
||||
STR r3, [r2, #28] @ Store initial r10 (sl)
|
||||
MOV r3, #0 @ Build initial register value
|
||||
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
|
||||
@}
|
||||
|
||||
|
||||
98
ports/cortex_m4/gnu/src/tx_thread_system_return.S
Normal file
98
ports/cortex_m4/gnu/src/tx_thread_system_return.S
Normal file
@@ -0,0 +1,98 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@/* #define TX_SOURCE_CODE */
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@/* #include "tx_api.h"
|
||||
@ #include "tx_thread.h"
|
||||
@ #include "tx_timer.h" */
|
||||
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_system_return Cortex-M4/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@/* 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
|
||||
|
||||
@/* } */
|
||||
|
||||
270
ports/cortex_m4/gnu/src/tx_timer_interrupt.S
Normal file
270
ports/cortex_m4/gnu/src/tx_timer_interrupt.S
Normal file
@@ -0,0 +1,270 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_timer.h"
|
||||
@#include "tx_thread.h"
|
||||
@
|
||||
@
|
||||
@Define Assembly language external references...
|
||||
@
|
||||
.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.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@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
|
||||
@
|
||||
@ }
|
||||
@
|
||||
__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
|
||||
@ {
|
||||
__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
|
||||
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
|
||||
@
|
||||
__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
|
||||
@
|
||||
@ }
|
||||
__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
|
||||
__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
|
||||
@
|
||||
@ }
|
||||
@
|
||||
__tx_timer_nothing_expired:
|
||||
|
||||
DSB @ Complete all memory access
|
||||
BX lr @ Return to caller
|
||||
@
|
||||
@}
|
||||
|
||||
|
||||
84
ports/cortex_m4/gnu/src/tx_vector_table_sample.S
Normal file
84
ports/cortex_m4/gnu/src/tx_vector_table_sample.S
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
|
||||
.global reset_handler
|
||||
|
||||
.global __tx_NMIHandler
|
||||
.global __tx_BadHandler
|
||||
.global __tx_SVCallHandler
|
||||
.global __tx_DBGHandler
|
||||
.global __tx_PendSVHandler
|
||||
.global __tx_SysTickHandler
|
||||
.global __tx_BadHandler
|
||||
|
||||
|
||||
.syntax unified
|
||||
.section .vectors, "ax"
|
||||
.code 16
|
||||
.align 0
|
||||
.global _vectors
|
||||
|
||||
_vectors:
|
||||
.word __stack_end__
|
||||
.word reset_handler
|
||||
.word __tx_NMIHandler
|
||||
.word __tx_HardfaultHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word __tx_SVCallHandler //_SVC_Handler - used by Threadx scheduler //
|
||||
.word __tx_DBGHandler
|
||||
.word 0 // Reserved
|
||||
.word __tx_PendSVHandler
|
||||
.word __tx_SysTickHandler // Used by Threadx timer functionality
|
||||
.word __tx_BadHandler // Populate with user Interrupt handler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
|
||||
|
||||
|
||||
.section .init, "ax"
|
||||
.thumb_func
|
||||
reset_handler:
|
||||
|
||||
// low level hardware config, such as PLL setup goes here
|
||||
|
||||
b _start
|
||||
|
||||
|
||||
|
||||
17
ports/cortex_m7/gnu/CMakeLists.txt
Normal file
17
ports/cortex_m7/gnu/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
# {{BEGIN_TARGET_SOURCES}}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S
|
||||
|
||||
# {{END_TARGET_SOURCES}}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc
|
||||
)
|
||||
496
ports/cortex_m7/gnu/inc/tx_port.h
Normal file
496
ports/cortex_m7/gnu/inc/tx_port.h
Normal file
@@ -0,0 +1,496 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Port Specific */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Cortex-M7/GNU */
|
||||
/* 6.0 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains data type definitions that make the ThreadX */
|
||||
/* real-time kernel function identically on a variety of different */
|
||||
/* processor architectures. For example, the size or number of bits */
|
||||
/* in an "int" data type vary between microprocessor architectures and */
|
||||
/* even C compilers for the same microprocessor. ThreadX does not */
|
||||
/* directly use native C data types. Instead, ThreadX creates its */
|
||||
/* own special types that can be mapped to actual data types by this */
|
||||
/* file to guarantee consistency in the interface and functionality. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_PORT_H
|
||||
#define TX_PORT_H
|
||||
|
||||
|
||||
/* Determine if the optional ThreadX user define file should be used. */
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
|
||||
/* 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"
|
||||
#endif
|
||||
|
||||
|
||||
/* Define compiler library include files. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Define ThreadX basic types for this port. */
|
||||
|
||||
#define VOID void
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef long LONG;
|
||||
typedef unsigned long ULONG;
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
|
||||
|
||||
/* Define the priority levels for ThreadX. Legal values range
|
||||
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||
|
||||
#ifndef TX_MAX_PRIORITIES
|
||||
#define TX_MAX_PRIORITIES 32
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||
thread creation is less than this value, the thread create call will return an error. */
|
||||
|
||||
#ifndef TX_MINIMUM_STACK
|
||||
#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||
|
||||
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
|
||||
#endif
|
||||
|
||||
#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 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
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0xE0001004)
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
#endif
|
||||
|
||||
|
||||
/* 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 the in-line initialization constant so that modules with in-line
|
||||
initialization capabilities can prevent their initialization from being
|
||||
a function call. */
|
||||
|
||||
#define TX_INLINE_INITIALIZATION
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
#undef TX_DISABLE_STACK_FILLING
|
||||
#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
|
||||
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 the port extensions of the remaining ThreadX objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_EXTENSION
|
||||
#define TX_BYTE_POOL_EXTENSION
|
||||
#define TX_EVENT_FLAGS_GROUP_EXTENSION
|
||||
#define TX_MUTEX_EXTENSION
|
||||
#define TX_QUEUE_EXTENSION
|
||||
#define TX_SEMAPHORE_EXTENSION
|
||||
#define TX_TIMER_EXTENSION
|
||||
|
||||
|
||||
/* 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
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
|
||||
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_FPU_SUPPORT
|
||||
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
|
||||
ULONG _tx_misra_control_get(void);
|
||||
void _tx_misra_control_set(ULONG value);
|
||||
ULONG _tx_misra_fpccr_get(void);
|
||||
void _tx_misra_vfp_touch(void);
|
||||
|
||||
#else
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline ULONG __get_control(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)
|
||||
{
|
||||
|
||||
__asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" );
|
||||
}
|
||||
|
||||
|
||||
#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 = __get_control(); \
|
||||
_tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \
|
||||
__set_control(_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
|
||||
|
||||
|
||||
/* 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
|
||||
this one, so if the FPCCR.LSPACT bit is set, we need to save the CONTROL.FPCA state, touch the FPU to flush
|
||||
the lazy FPU save, then restore the CONTROL.FPCA state. */
|
||||
|
||||
#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); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#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); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the ThreadX object creation extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Define the ThreadX object deletion extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Define the get system state macro. */
|
||||
|
||||
#ifndef TX_THREAD_GET_SYSTEM_STATE
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
|
||||
__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
|
||||
ULONG _tx_misra_ipsr_get(VOID);
|
||||
#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get())
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
#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
|
||||
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 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. */
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
|
||||
{
|
||||
|
||||
unsigned int primask_value;
|
||||
|
||||
__asm__ volatile (" MRS %0,PRIMASK ": "=r" (primask_value) );
|
||||
__asm__ volatile (" CPSID i" : : : "memory" );
|
||||
return(primask_value);
|
||||
}
|
||||
|
||||
__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;
|
||||
|
||||
*((ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
|
||||
if (__get_ipsr_value() == 0)
|
||||
{
|
||||
interrupt_save = __get_primask_value();
|
||||
__enable_interrupts();
|
||||
__restore_interrupts(interrupt_save);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = __disable_interrupts();
|
||||
#define TX_RESTORE __restore_interrupts(interrupt_save);
|
||||
|
||||
|
||||
/* Redefine _tx_thread_system_return for improved performance. */
|
||||
|
||||
#define _tx_thread_system_return _tx_thread_system_return_inline
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA unsigned int interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
|
||||
#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
|
||||
#endif
|
||||
|
||||
|
||||
/* Define FPU extension for the Cortex-M7. Each is assumed to be called in the context of the executing
|
||||
thread. This is for legacy only, and not needed any longer. */
|
||||
|
||||
void tx_thread_fpu_enable(void);
|
||||
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-M7/GNU Version 6.0 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
239
ports/cortex_m7/gnu/src/tx_initialize_low_level_sample.S
Executable file
239
ports/cortex_m7/gnu/src/tx_initialize_low_level_sample.S
Executable file
@@ -0,0 +1,239 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/** Initialize */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_initialize.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
@
|
||||
.global _tx_thread_system_stack_ptr
|
||||
.global _tx_initialize_unused_memory
|
||||
.global __RAM_segment_used_end__
|
||||
.global _tx_timer_interrupt
|
||||
.global __main
|
||||
.global __tx_SVCallHandler
|
||||
.global __tx_PendSVHandler
|
||||
.global _vectors
|
||||
.global __tx_NMIHandler @ NMI
|
||||
.global __tx_BadHandler @ HardFault
|
||||
.global __tx_SVCallHandler @ SVCall
|
||||
.global __tx_DBGHandler @ Monitor
|
||||
.global __tx_PendSVHandler @ PendSV
|
||||
.global __tx_SysTickHandler @ SysTick
|
||||
.global __tx_IntHandler @ Int 0
|
||||
@
|
||||
@
|
||||
SYSTEM_CLOCK = 6000000
|
||||
SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1)
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_initialize_low_level Cortex-M7/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* This function is responsible for any low-level processor */
|
||||
@/* initialization, including setting up interrupt vectors, setting */
|
||||
@/* up a periodic timer interrupt source, saving the system stack */
|
||||
@/* pointer for use in ISR processing later, and finding the first */
|
||||
@/* available RAM memory address for tx_application_define. */
|
||||
@/* */
|
||||
@/* INPUT */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* OUTPUT */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* CALLS */
|
||||
@/* */
|
||||
@/* None */
|
||||
@/* */
|
||||
@/* CALLED BY */
|
||||
@/* */
|
||||
@/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
@/* */
|
||||
@/* RELEASE HISTORY */
|
||||
@/* */
|
||||
@/* DATE NAME DESCRIPTION */
|
||||
@/* */
|
||||
@/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_initialize_low_level(VOID)
|
||||
@{
|
||||
.global _tx_initialize_low_level
|
||||
.thumb_func
|
||||
_tx_initialize_low_level:
|
||||
@
|
||||
@ /* Disable interrupts during ThreadX initialization. */
|
||||
@
|
||||
CPSID i
|
||||
@
|
||||
@ /* Set base of available memory to end of non-initialised RAM area. */
|
||||
@
|
||||
LDR r0, =_tx_initialize_unused_memory @ Build address of unused memory pointer
|
||||
LDR r1, =__RAM_segment_used_end__ @ Build first free address
|
||||
ADD r1, r1, #4 @
|
||||
STR r1, [r0] @ Setup first unused memory pointer
|
||||
@
|
||||
@ /* Setup Vector Table Offset Register. */
|
||||
@
|
||||
MOV r0, #0xE000E000 @ Build address of NVIC registers
|
||||
LDR r1, =_vectors @ Pickup address of vector table
|
||||
STR r1, [r0, #0xD08] @ Set vector table address
|
||||
@
|
||||
@ /* Set system stack pointer from vector value. */
|
||||
@
|
||||
LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer
|
||||
LDR r1, =_vectors @ Pickup address of vector table
|
||||
LDR r1, [r1] @ Pickup reset stack pointer
|
||||
STR r1, [r0] @ Save system stack pointer
|
||||
@
|
||||
@ /* Enable the cycle count register. */
|
||||
@
|
||||
LDR r0, =0xE0001000 @ Build address of DWT register
|
||||
LDR r1, [r0] @ Pickup the current value
|
||||
ORR r1, r1, #1 @ Set the CYCCNTENA bit
|
||||
STR r1, [r0] @ Enable the cycle count register
|
||||
@
|
||||
@ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */
|
||||
@
|
||||
MOV r0, #0xE000E000 @ Build address of NVIC registers
|
||||
LDR r1, =SYSTICK_CYCLES
|
||||
STR r1, [r0, #0x14] @ Setup SysTick Reload Value
|
||||
MOV r1, #0x7 @ Build SysTick Control Enable Value
|
||||
STR r1, [r0, #0x10] @ Setup SysTick Control
|
||||
@
|
||||
@ /* Configure handler priorities. */
|
||||
@
|
||||
LDR r1, =0x00000000 @ Rsrv, UsgF, BusF, MemM
|
||||
STR r1, [r0, #0xD18] @ Setup System Handlers 4-7 Priority Registers
|
||||
|
||||
LDR r1, =0xFF000000 @ SVCl, Rsrv, Rsrv, Rsrv
|
||||
STR r1, [r0, #0xD1C] @ Setup System Handlers 8-11 Priority Registers
|
||||
@ Note: SVC must be lowest priority, which is 0xFF
|
||||
|
||||
LDR r1, =0x40FF0000 @ SysT, PnSV, Rsrv, DbgM
|
||||
STR r1, [r0, #0xD20] @ Setup System Handlers 12-15 Priority Registers
|
||||
@ Note: PnSV must be lowest priority, which is 0xFF
|
||||
|
||||
@
|
||||
@ /* Return to caller. */
|
||||
@
|
||||
BX lr
|
||||
@}
|
||||
@
|
||||
|
||||
@/* Define shells for each of the unused vectors. */
|
||||
@
|
||||
.global __tx_BadHandler
|
||||
.thumb_func
|
||||
__tx_BadHandler:
|
||||
B __tx_BadHandler
|
||||
|
||||
@ /* added to catch the hardfault */
|
||||
|
||||
.global __tx_HardfaultHandler
|
||||
.thumb_func
|
||||
__tx_HardfaultHandler:
|
||||
B __tx_HardfaultHandler
|
||||
|
||||
|
||||
@ /* added to catch the SVC */
|
||||
|
||||
.global __tx_SVCallHandler
|
||||
.thumb_func
|
||||
__tx_SVCallHandler:
|
||||
B __tx_SVCallHandler
|
||||
|
||||
|
||||
@ /* Generic interrupt handler template */
|
||||
.global __tx_IntHandler
|
||||
.thumb_func
|
||||
__tx_IntHandler:
|
||||
@ VOID InterruptHandler (VOID)
|
||||
@ {
|
||||
PUSH {r0, lr}
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_enter ; Call the ISR enter function
|
||||
#endif
|
||||
|
||||
@ /* Do interrupt handler work here */
|
||||
@ /* BL <your C Function>.... */
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_exit ; Call the ISR exit function
|
||||
#endif
|
||||
POP {r0, lr}
|
||||
BX LR
|
||||
@ }
|
||||
|
||||
@ /* System Tick timer interrupt handler */
|
||||
.global __tx_SysTickHandler
|
||||
.global SysTick_Handler
|
||||
.thumb_func
|
||||
__tx_SysTickHandler:
|
||||
.thumb_func
|
||||
SysTick_Handler:
|
||||
@ VOID TimerInterruptHandler (VOID)
|
||||
@ {
|
||||
@
|
||||
PUSH {r0, lr}
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_enter ; Call the ISR enter function
|
||||
#endif
|
||||
BL _tx_timer_interrupt
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
BL _tx_execution_isr_exit ; Call the ISR exit function
|
||||
#endif
|
||||
POP {r0, lr}
|
||||
BX LR
|
||||
@ }
|
||||
|
||||
|
||||
@ /* NMI, DBG handlers */
|
||||
.global __tx_NMIHandler
|
||||
.thumb_func
|
||||
__tx_NMIHandler:
|
||||
B __tx_NMIHandler
|
||||
|
||||
.global __tx_DBGHandler
|
||||
.thumb_func
|
||||
__tx_DBGHandler:
|
||||
B __tx_DBGHandler
|
||||
96
ports/cortex_m7/gnu/src/tx_thread_context_restore.S
Executable file
96
ports/cortex_m7/gnu/src/tx_thread_context_restore.S
Executable file
@@ -0,0 +1,96 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
@
|
||||
.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
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_context_restore Cortex-M7/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_thread_context_restore(VOID)
|
||||
@{
|
||||
.global _tx_thread_context_restore
|
||||
.thumb_func
|
||||
_tx_thread_context_restore:
|
||||
@
|
||||
@ /* Not needed for this port - just return! */
|
||||
BX lr
|
||||
@}
|
||||
|
||||
89
ports/cortex_m7/gnu/src/tx_thread_context_save.S
Executable file
89
ports/cortex_m7/gnu/src/tx_thread_context_save.S
Executable file
@@ -0,0 +1,89 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
@
|
||||
.global _tx_thread_system_state
|
||||
.global _tx_thread_current_ptr
|
||||
.global _tx_execution_isr_enter
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_context_save Cortex-M7/GNU */
|
||||
@/* 6.0 */
|
||||
@/* AUTHOR */
|
||||
@/* */
|
||||
@/* William E. Lamie, Microsoft Corporation */
|
||||
@/* */
|
||||
@/* DESCRIPTION */
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_thread_context_save(VOID)
|
||||
@{
|
||||
.global _tx_thread_context_save
|
||||
.thumb_func
|
||||
_tx_thread_context_save:
|
||||
@
|
||||
@ /* Not needed for this port - just return! */
|
||||
BX lr
|
||||
@}
|
||||
92
ports/cortex_m7/gnu/src/tx_thread_interrupt_control.S
Executable file
92
ports/cortex_m7/gnu/src/tx_thread_interrupt_control.S
Executable file
@@ -0,0 +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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
|
||||
@/* #define TX_SOURCE_CODE */
|
||||
|
||||
|
||||
@/* Include necessary system files. */
|
||||
|
||||
@/* #include "tx_api.h"
|
||||
#include "tx_thread.h" */
|
||||
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_interrupt_control Cortex-M7/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@/* 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
|
||||
|
||||
@/* } */
|
||||
|
||||
|
||||
|
||||
296
ports/cortex_m7/gnu/src/tx_thread_schedule.S
Executable file
296
ports/cortex_m7/gnu/src/tx_thread_schedule.S
Executable file
@@ -0,0 +1,296 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@#include "tx_timer.h"
|
||||
@
|
||||
.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
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_schedule Cortex-M7/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@VOID _tx_thread_schedule(VOID)
|
||||
@{
|
||||
.global _tx_thread_schedule
|
||||
.thumb_func
|
||||
_tx_thread_schedule:
|
||||
@
|
||||
@ /* This function should only ever be called on Cortex-M7
|
||||
@ 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
|
||||
#endif
|
||||
@
|
||||
@ /* Enable interrupts */
|
||||
@
|
||||
CPSIE i
|
||||
@
|
||||
@ /* Enter the scheduler for the first time. */
|
||||
@
|
||||
MOV r0, #0x10000000 @ Load PENDSVSET bit
|
||||
MOV r1, #0xE000E000 @ Load NVIC base
|
||||
STR r0, [r1, #0xD04] @ Set PENDSVBIT in ICSR
|
||||
DSB @ Complete all memory accesses
|
||||
ISB @ Flush pipeline
|
||||
@
|
||||
@ /* Wait here for the PendSV to take place. */
|
||||
@
|
||||
__tx_wait_here:
|
||||
B __tx_wait_here @ Wait for the PendSV to happen
|
||||
@}
|
||||
@
|
||||
@ /* Generic context switch-out switch-in handler... Note that this handler is
|
||||
@ common for both PendSV and SVCall. */
|
||||
@
|
||||
.global PendSV_Handler
|
||||
.global __tx_PendSVHandler
|
||||
.thumb_func
|
||||
PendSV_Handler:
|
||||
.thumb_func
|
||||
__tx_PendSVHandler:
|
||||
@
|
||||
@ /* 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
|
||||
#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
|
||||
BNE _skip_vfp_save
|
||||
VSTMDB r12!,{s16-s31} @ Yes, save additional VFP registers
|
||||
_skip_vfp_save:
|
||||
#endif
|
||||
LDR r4, =_tx_timer_time_slice @ Build address of time-slice variable
|
||||
STMDB r12!, {LR} @ Save LR on the stack
|
||||
@
|
||||
@ /* 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
|
||||
|
||||
#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
|
||||
#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
|
||||
_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. */
|
||||
@
|
||||
__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!
|
||||
#ifdef TX_ENABLE_WFI
|
||||
DSB @ Ensure no outstanding memory transactions
|
||||
WFI @ Wait for interrupt
|
||||
ISB @ Ensure pipeline is flushed
|
||||
#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! */
|
||||
@
|
||||
__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
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_FPU_SUPPORT
|
||||
|
||||
.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
|
||||
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
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
148
ports/cortex_m7/gnu/src/tx_thread_stack_build.S
Executable file
148
ports/cortex_m7/gnu/src/tx_thread_stack_build.S
Executable file
@@ -0,0 +1,148 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_thread.h"
|
||||
@
|
||||
@
|
||||
.text
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_stack_build Cortex-M7/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@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-M7 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 (sl) Initial value for r10 (sl)
|
||||
@ 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
|
||||
LDR r3, [r0, #12] @ Pickup stack starting address
|
||||
STR r3, [r2, #28] @ Store initial r10 (sl)
|
||||
MOV r3, #0 @ Build initial register value
|
||||
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
|
||||
@}
|
||||
|
||||
|
||||
98
ports/cortex_m7/gnu/src/tx_thread_system_return.S
Executable file
98
ports/cortex_m7/gnu/src/tx_thread_system_return.S
Executable file
@@ -0,0 +1,98 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@/* #define TX_SOURCE_CODE */
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@/* #include "tx_api.h"
|
||||
@ #include "tx_thread.h"
|
||||
@ #include "tx_timer.h" */
|
||||
|
||||
|
||||
.text 32
|
||||
.align 4
|
||||
.syntax unified
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* FUNCTION RELEASE */
|
||||
@/* */
|
||||
@/* _tx_thread_system_return Cortex-M7/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@/* 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
|
||||
|
||||
@/* } */
|
||||
|
||||
270
ports/cortex_m7/gnu/src/tx_timer_interrupt.S
Executable file
270
ports/cortex_m7/gnu/src/tx_timer_interrupt.S
Executable file
@@ -0,0 +1,270 @@
|
||||
@/**************************************************************************/
|
||||
@/* */
|
||||
@/* 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 */
|
||||
@/** */
|
||||
@/**************************************************************************/
|
||||
@/**************************************************************************/
|
||||
@
|
||||
@#define TX_SOURCE_CODE
|
||||
@
|
||||
@
|
||||
@/* Include necessary system files. */
|
||||
@
|
||||
@#include "tx_api.h"
|
||||
@#include "tx_timer.h"
|
||||
@#include "tx_thread.h"
|
||||
@
|
||||
@
|
||||
@Define Assembly language external references...
|
||||
@
|
||||
.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-M7/GNU */
|
||||
@/* 6.0 */
|
||||
@/* 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 */
|
||||
@/* */
|
||||
@/**************************************************************************/
|
||||
@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
|
||||
@
|
||||
@ }
|
||||
@
|
||||
__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
|
||||
@ {
|
||||
__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
|
||||
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
|
||||
@
|
||||
__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
|
||||
@
|
||||
@ }
|
||||
__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
|
||||
__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
|
||||
@
|
||||
@ }
|
||||
@
|
||||
__tx_timer_nothing_expired:
|
||||
|
||||
DSB @ Complete all memory access
|
||||
BX lr @ Return to caller
|
||||
@
|
||||
@}
|
||||
|
||||
|
||||
84
ports/cortex_m7/gnu/src/tx_vector_table_sample.S
Normal file
84
ports/cortex_m7/gnu/src/tx_vector_table_sample.S
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
|
||||
.global reset_handler
|
||||
|
||||
.global __tx_NMIHandler
|
||||
.global __tx_BadHandler
|
||||
.global __tx_SVCallHandler
|
||||
.global __tx_DBGHandler
|
||||
.global __tx_PendSVHandler
|
||||
.global __tx_SysTickHandler
|
||||
.global __tx_BadHandler
|
||||
|
||||
|
||||
.syntax unified
|
||||
.section .vectors, "ax"
|
||||
.code 16
|
||||
.align 0
|
||||
.global _vectors
|
||||
|
||||
_vectors:
|
||||
.word __stack_end__
|
||||
.word reset_handler
|
||||
.word __tx_NMIHandler
|
||||
.word __tx_HardfaultHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word 0 // Reserved
|
||||
.word __tx_SVCallHandler //_SVC_Handler - used by Threadx scheduler //
|
||||
.word __tx_DBGHandler
|
||||
.word 0 // Reserved
|
||||
.word __tx_PendSVHandler
|
||||
.word __tx_SysTickHandler // Used by Threadx timer functionality
|
||||
.word __tx_BadHandler // Populate with user Interrupt handler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
.word __tx_BadHandler
|
||||
|
||||
|
||||
|
||||
.section .init, "ax"
|
||||
.thumb_func
|
||||
reset_handler:
|
||||
|
||||
// low level hardware config, such as PLL setup goes here
|
||||
|
||||
b _start
|
||||
|
||||
|
||||
|
||||
25
ports/linux/gnu/CMakeLists.txt
Normal file
25
ports/linux/gnu/CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
# For this port, we need to tell the common subdirectory to not include these files
|
||||
set(TX_SRC_OVERRIDES
|
||||
"tx_thread_delete.c"
|
||||
"tx_thread_reset.c"
|
||||
CACHE STRING "tx source overrides")
|
||||
|
||||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
# {{BEGIN_TARGET_SOURCES}}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.c
|
||||
|
||||
# {{END_TARGET_SOURCES}}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc
|
||||
)
|
||||
|
||||
575
ports/linux/gnu/inc/tx_port.h
Normal file
575
ports/linux/gnu/inc/tx_port.h
Normal file
@@ -0,0 +1,575 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Port Specific */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h Linux/GNU */
|
||||
/* 6.0 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains data type definitions that make the ThreadX */
|
||||
/* real-time kernel function identically on a variety of different */
|
||||
/* processor architectures. For example, the size or number of bits */
|
||||
/* in an "int" data type vary between microprocessor architectures and */
|
||||
/* even C compilers for the same microprocessor. ThreadX does not */
|
||||
/* directly use native C data types. Instead, ThreadX creates its */
|
||||
/* own special types that can be mapped to actual data types by this */
|
||||
/* file to guarantee consistency in the interface and functionality. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_PORT_H
|
||||
#define TX_PORT_H
|
||||
|
||||
|
||||
#define TX_MAX_PRIORITIES 32
|
||||
/* #define TX_MISRA_ENABLE */
|
||||
|
||||
|
||||
/* #define TX_INLINE_INITIALIZATION */
|
||||
|
||||
/* #define TX_NOT_INTERRUPTABLE */
|
||||
/* #define TX_TIMER_PROCESS_IN_ISR */
|
||||
/* #define TX_REACTIVATE_INLINE */
|
||||
/* #define TX_DISABLE_STACK_FILLING */
|
||||
/* #define TX_ENABLE_STACK_CHECKING */
|
||||
/* #define TX_DISABLE_PREEMPTION_THRESHOLD */
|
||||
/* #define TX_DISABLE_REDUNDANT_CLEARING */
|
||||
/* #define TX_DISABLE_NOTIFY_CALLBACKS */
|
||||
/* #define TX_INLINE_THREAD_RESUME_SUSPEND */
|
||||
/* #define TX_ENABLE_EVENT_TRACE */
|
||||
|
||||
|
||||
/* For MISRA, define enable performance info. Also, for MISRA TX_DISABLE_NOTIFY_CALLBACKS should not be defined. */
|
||||
|
||||
|
||||
/* #define TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
|
||||
#define TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
|
||||
#define TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
|
||||
#define TX_MUTEX_ENABLE_PERFORMANCE_INFO
|
||||
#define TX_QUEUE_ENABLE_PERFORMANCE_INFO
|
||||
#define TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
|
||||
#define TX_THREAD_ENABLE_PERFORMANCE_INFO
|
||||
#define TX_TIMER_ENABLE_PERFORMANCE_INFO */
|
||||
|
||||
|
||||
|
||||
/* Determine if the optional ThreadX user define file should be used. */
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
|
||||
|
||||
/* 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"
|
||||
#endif
|
||||
|
||||
|
||||
/* Define compiler library include files. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#ifndef __USE_POSIX199309
|
||||
#define __USE_POSIX199309
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <time.h>
|
||||
#undef __USE_POSIX199309
|
||||
#else /* __USE_POSIX199309 */
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <time.h>
|
||||
#endif /* __USE_POSIX199309 */
|
||||
|
||||
|
||||
/* Define ThreadX basic types for this port. */
|
||||
|
||||
typedef void VOID;
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
#if __x86_64__
|
||||
typedef int LONG;
|
||||
typedef unsigned int ULONG;
|
||||
#else /* __x86_64__ */
|
||||
typedef long LONG;
|
||||
typedef unsigned long ULONG;
|
||||
#endif /* __x86_64__ */
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
typedef uint64_t ULONG64;
|
||||
|
||||
|
||||
/* Override the alignment type to use 64-bit alignment and storage for pointers. */
|
||||
|
||||
#if __x86_64__
|
||||
#define ALIGN_TYPE_DEFINED
|
||||
typedef unsigned long long ALIGN_TYPE;
|
||||
|
||||
/* Override the free block marker for byte pools to be a 64-bit constant. */
|
||||
|
||||
#define TX_BYTE_BLOCK_FREE ((ALIGN_TYPE) 0xFFFFEEEEFFFFEEEE)
|
||||
#endif
|
||||
|
||||
/* Define automated coverage test extensions... These are required for the
|
||||
ThreadX regression test. */
|
||||
|
||||
typedef unsigned int TEST_FLAG;
|
||||
extern TEST_FLAG threadx_byte_allocate_loop_test;
|
||||
extern TEST_FLAG threadx_byte_release_loop_test;
|
||||
extern TEST_FLAG threadx_mutex_suspension_put_test;
|
||||
extern TEST_FLAG threadx_mutex_suspension_priority_test;
|
||||
#ifndef TX_TIMER_PROCESS_IN_ISR
|
||||
extern TEST_FLAG threadx_delete_timer_thread;
|
||||
#endif
|
||||
|
||||
extern void abort_and_resume_byte_allocating_thread(void);
|
||||
extern void abort_all_threads_suspended_on_mutex(void);
|
||||
extern void suspend_lowest_priority(void);
|
||||
#ifndef TX_TIMER_PROCESS_IN_ISR
|
||||
extern void delete_timer_thread(void);
|
||||
#endif
|
||||
extern TEST_FLAG test_stack_analyze_flag;
|
||||
extern TEST_FLAG test_initialize_flag;
|
||||
extern TEST_FLAG test_forced_mutex_timeout;
|
||||
|
||||
|
||||
#ifdef TX_REGRESSION_TEST
|
||||
|
||||
/* Define extension macros for automated coverage tests. */
|
||||
|
||||
|
||||
#define TX_BYTE_ALLOCATE_EXTENSION if (threadx_byte_allocate_loop_test == ((TEST_FLAG) 1)) \
|
||||
{ \
|
||||
pool_ptr -> tx_byte_pool_owner = TX_NULL; \
|
||||
threadx_byte_allocate_loop_test = ((TEST_FLAG) 0); \
|
||||
}
|
||||
|
||||
#define TX_BYTE_RELEASE_EXTENSION if (threadx_byte_release_loop_test == ((TEST_FLAG) 1)) \
|
||||
{ \
|
||||
threadx_byte_release_loop_test = ((TEST_FLAG) 0); \
|
||||
abort_and_resume_byte_allocating_thread(); \
|
||||
}
|
||||
|
||||
#define TX_MUTEX_PUT_EXTENSION_1 if (threadx_mutex_suspension_put_test == ((TEST_FLAG) 1)) \
|
||||
{ \
|
||||
threadx_mutex_suspension_put_test = ((TEST_FLAG) 0); \
|
||||
abort_all_threads_suspended_on_mutex(); \
|
||||
}
|
||||
|
||||
|
||||
#define TX_MUTEX_PUT_EXTENSION_2 if (test_forced_mutex_timeout == ((TEST_FLAG) 1)) \
|
||||
{ \
|
||||
test_forced_mutex_timeout = ((TEST_FLAG) 0); \
|
||||
_tx_thread_wait_abort(mutex_ptr -> tx_mutex_suspension_list); \
|
||||
}
|
||||
|
||||
|
||||
#define TX_MUTEX_PRIORITY_CHANGE_EXTENSION if (threadx_mutex_suspension_priority_test == ((TEST_FLAG) 1)) \
|
||||
{ \
|
||||
threadx_mutex_suspension_priority_test = ((TEST_FLAG) 0); \
|
||||
suspend_lowest_priority(); \
|
||||
}
|
||||
|
||||
#ifndef TX_TIMER_PROCESS_IN_ISR
|
||||
|
||||
#define TX_TIMER_INITIALIZE_EXTENSION(a) if (threadx_delete_timer_thread == ((TEST_FLAG) 1)) \
|
||||
{ \
|
||||
threadx_delete_timer_thread = ((TEST_FLAG) 0); \
|
||||
delete_timer_thread(); \
|
||||
(a) = ((UINT) 1); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define TX_THREAD_STACK_ANALYZE_EXTENSION if (test_stack_analyze_flag == ((TEST_FLAG) 1)) \
|
||||
{ \
|
||||
thread_ptr -> tx_thread_id = ((TEST_FLAG) 0); \
|
||||
test_stack_analyze_flag = ((TEST_FLAG) 0); \
|
||||
} \
|
||||
else if (test_stack_analyze_flag == ((TEST_FLAG) 2)) \
|
||||
{ \
|
||||
stack_ptr = thread_ptr -> tx_thread_stack_start; \
|
||||
test_stack_analyze_flag = ((TEST_FLAG) 0); \
|
||||
} \
|
||||
else if (test_stack_analyze_flag == ((TEST_FLAG) 3)) \
|
||||
{ \
|
||||
*stack_ptr = TX_STACK_FILL; \
|
||||
test_stack_analyze_flag = ((TEST_FLAG) 0); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
test_stack_analyze_flag = ((TEST_FLAG) 0); \
|
||||
}
|
||||
|
||||
#define TX_INITIALIZE_KERNEL_ENTER_EXTENSION if (test_initialize_flag == ((TEST_FLAG) 1)) \
|
||||
{ \
|
||||
test_initialize_flag = ((TEST_FLAG) 0); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Add Linux debug insert prototype. */
|
||||
|
||||
void _tx_linux_debug_entry_insert(char *action, char *file, unsigned long line);
|
||||
|
||||
#ifndef TX_LINUX_DEBUG_ENABLE
|
||||
|
||||
/* If Linux debug is not enabled, turn logging into white-space. */
|
||||
|
||||
#define _tx_linux_debug_entry_insert(a, b, c)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Define the TX_MEMSET macro to remove library reference. */
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#define TX_MEMSET(a,b,c) { \
|
||||
UCHAR *ptr; \
|
||||
UCHAR value; \
|
||||
UINT i, size; \
|
||||
ptr = (UCHAR *) ((VOID *) a); \
|
||||
value = (UCHAR) b; \
|
||||
size = (UINT) c; \
|
||||
for (i = 0; i < size; i++) \
|
||||
{ \
|
||||
*ptr++ = value; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the priority levels for ThreadX. Legal values range
|
||||
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||
|
||||
#ifndef TX_MAX_PRIORITIES
|
||||
#define TX_MAX_PRIORITIES 32
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||
thread creation is less than this value, the thread create call will return an error. */
|
||||
|
||||
#ifndef TX_MINIMUM_STACK
|
||||
#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||
|
||||
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||
#define TX_TIMER_THREAD_STACK_SIZE 400 /* Default timer thread stack size - Not used in Linux port! */
|
||||
#endif
|
||||
|
||||
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define various constants for the ThreadX 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
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE ((ULONG) (_tx_linux_time_stamp.tv_nsec));
|
||||
#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
|
||||
|
||||
|
||||
/* Define the port-specific trace extension to pickup the Windows timer. */
|
||||
|
||||
#define TX_TRACE_PORT_EXTENSION clock_gettime(CLOCK_REALTIME, &_tx_linux_time_stamp);
|
||||
|
||||
|
||||
/* 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 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
|
||||
|
||||
|
||||
/* Define the Linux-specific initialization code that is expanded in the generic source. */
|
||||
|
||||
void _tx_initialize_start_interrupts(void);
|
||||
|
||||
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION _tx_initialize_start_interrupts();
|
||||
|
||||
|
||||
/* 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
|
||||
existing ThreadX kernel awareness modules. */
|
||||
|
||||
#define TX_THREAD_EXTENSION_0 pthread_t tx_thread_linux_thread_id; \
|
||||
sem_t tx_thread_linux_thread_run_semaphore; \
|
||||
UINT tx_thread_linux_suspension_type; \
|
||||
UINT tx_thread_linux_int_disabled_flag;
|
||||
|
||||
#define TX_THREAD_EXTENSION_1 VOID *tx_thread_extension_ptr;
|
||||
#define TX_THREAD_EXTENSION_2
|
||||
#define TX_THREAD_EXTENSION_3
|
||||
|
||||
|
||||
/* Define the port extensions of the remaining ThreadX objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_EXTENSION
|
||||
#define TX_BYTE_POOL_EXTENSION
|
||||
#define TX_EVENT_FLAGS_GROUP_EXTENSION
|
||||
#define TX_MUTEX_EXTENSION
|
||||
#define TX_QUEUE_EXTENSION
|
||||
#define TX_SEMAPHORE_EXTENSION
|
||||
#define TX_TIMER_EXTENSION
|
||||
|
||||
|
||||
/* 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
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
|
||||
tx_thread_shell_entry, and tx_thread_terminate. */
|
||||
|
||||
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
|
||||
|
||||
|
||||
/* Define the ThreadX object creation extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Define the ThreadX object deletion extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
|
||||
|
||||
struct TX_THREAD_STRUCT;
|
||||
|
||||
/* Define post completion processing for tx_thread_delete, so that the Linux thread resources are properly removed. */
|
||||
|
||||
void _tx_thread_delete_port_completion(struct TX_THREAD_STRUCT *thread_ptr, UINT tx_saved_posture);
|
||||
#define TX_THREAD_DELETE_PORT_COMPLETION(thread_ptr) _tx_thread_delete_port_completion(thread_ptr, tx_saved_posture);
|
||||
|
||||
/* Define post completion processing for tx_thread_reset, so that the Linux thread resources are properly removed. */
|
||||
|
||||
void _tx_thread_reset_port_completion(struct TX_THREAD_STRUCT *thread_ptr, UINT tx_saved_posture);
|
||||
#define TX_THREAD_RESET_PORT_COMPLETION(thread_ptr) _tx_thread_reset_port_completion(thread_ptr, tx_saved_posture);
|
||||
|
||||
#if __x86_64__
|
||||
/* Define the ThreadX object deletion extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
|
||||
|
||||
/* Define the internal timer extension to also hold the thread pointer such that _tx_thread_timeout
|
||||
can figure out what thread timeout to process. */
|
||||
|
||||
#define TX_TIMER_INTERNAL_EXTENSION VOID *tx_timer_internal_extension_ptr;
|
||||
|
||||
|
||||
/* Define the thread timeout setup logic in _tx_thread_create. */
|
||||
|
||||
#define TX_THREAD_CREATE_TIMEOUT_SETUP(t) (t) -> tx_thread_timer.tx_timer_internal_timeout_function = &(_tx_thread_timeout); \
|
||||
(t) -> tx_thread_timer.tx_timer_internal_timeout_param = 0; \
|
||||
(t) -> tx_thread_timer.tx_timer_internal_extension_ptr = (VOID *) (t);
|
||||
|
||||
|
||||
/* Define the thread timeout pointer setup in _tx_thread_timeout. */
|
||||
|
||||
#define TX_THREAD_TIMEOUT_POINTER_SETUP(t) (t) = (TX_THREAD *) _tx_timer_expired_timer_ptr -> tx_timer_internal_extension_ptr;
|
||||
#endif /* __x86_64__ */
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
UINT _tx_thread_interrupt_disable(void);
|
||||
VOID _tx_thread_interrupt_restore(UINT previous_posture);
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA UINT tx_saved_posture;
|
||||
|
||||
#ifndef TX_LINUX_DEBUG_ENABLE
|
||||
#define TX_DISABLE tx_saved_posture = _tx_thread_interrupt_disable();
|
||||
#define TX_RESTORE _tx_thread_interrupt_restore(tx_saved_posture);
|
||||
#else
|
||||
#define TX_DISABLE _tx_linux_debug_entry_insert("DISABLE", __FILE__, __LINE__); \
|
||||
tx_saved_posture = _tx_thread_interrupt_disable();
|
||||
|
||||
#define TX_RESTORE _tx_linux_debug_entry_insert("RESTORE", __FILE__, __LINE__); \
|
||||
_tx_thread_interrupt_restore(tx_saved_posture);
|
||||
#endif /* TX_LINUX_DEBUG_ENABLE */
|
||||
#define tx_linux_mutex_lock(p) pthread_mutex_lock(&p)
|
||||
#define tx_linux_mutex_unlock(p) pthread_mutex_unlock(&p)
|
||||
#define tx_linux_mutex_recursive_unlock(p) {\
|
||||
int _recursive_count = tx_linux_mutex_recursive_count;\
|
||||
while(_recursive_count)\
|
||||
{\
|
||||
pthread_mutex_unlock(&p);\
|
||||
_recursive_count--;\
|
||||
}\
|
||||
}
|
||||
#define tx_linux_mutex_recursive_count _tx_linux_mutex.__data.__count
|
||||
#define tx_linux_sem_post(p) tx_linux_mutex_lock(_tx_linux_mutex);\
|
||||
sem_post(p);\
|
||||
tx_linux_mutex_unlock(_tx_linux_mutex)
|
||||
#define tx_linux_sem_post_nolock(p) sem_post(p)
|
||||
#define tx_linux_sem_wait(p) sem_wait(p)
|
||||
|
||||
|
||||
/* 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 * ThreadX Linux/gcc Version 6.0 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
|
||||
/* Define externals for the Linux port of ThreadX. */
|
||||
|
||||
extern pthread_mutex_t _tx_linux_mutex;
|
||||
extern sem_t _tx_linux_semaphore;
|
||||
extern sem_t _tx_linux_semaphore_no_idle;
|
||||
extern ULONG _tx_linux_global_int_disabled_flag;
|
||||
extern struct timespec _tx_linux_time_stamp;
|
||||
extern __thread int _tx_linux_threadx_thread;
|
||||
|
||||
/* Define functions for linux thread. */
|
||||
void _tx_linux_thread_suspend(pthread_t thread_id);
|
||||
void _tx_linux_thread_resume(pthread_t thread_id);
|
||||
void _tx_linux_thread_init();
|
||||
|
||||
#ifndef TX_LINUX_MEMORY_SIZE
|
||||
#define TX_LINUX_MEMORY_SIZE 64000
|
||||
#endif
|
||||
|
||||
#define TX_TIMER_TICKS_PER_SECOND 100UL
|
||||
|
||||
/* Define priorities of pthreads. */
|
||||
|
||||
#define TX_LINUX_PRIORITY_SCHEDULE (3)
|
||||
#define TX_LINUX_PRIORITY_ISR (2)
|
||||
#define TX_LINUX_PRIORITY_USER_THREAD (1)
|
||||
|
||||
#endif
|
||||
|
||||
443
ports/linux/gnu/src/tx_initialize_low_level_sample.c
Normal file
443
ports/linux/gnu/src/tx_initialize_low_level_sample.c
Normal file
@@ -0,0 +1,443 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Initialize */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
|
||||
/* Define various Linux objects used by the ThreadX port. */
|
||||
|
||||
pthread_mutex_t _tx_linux_mutex;
|
||||
sem_t _tx_linux_semaphore;
|
||||
sem_t _tx_linux_semaphore_no_idle;
|
||||
ULONG _tx_linux_global_int_disabled_flag;
|
||||
struct timespec _tx_linux_time_stamp;
|
||||
__thread int _tx_linux_threadx_thread = 0;
|
||||
|
||||
/* Define signals for linux thread. */
|
||||
#define SUSPEND_SIG SIGUSR1
|
||||
#define RESUME_SIG SIGUSR2
|
||||
|
||||
static sigset_t _tx_linux_thread_wait_mask;
|
||||
static __thread int _tx_linux_thread_suspended;
|
||||
static sem_t _tx_linux_thread_timer_wait;
|
||||
static sem_t _tx_linux_thread_other_wait;
|
||||
|
||||
/* Define simulated timer interrupt. This is done inside a thread, which is
|
||||
how other interrupts may be defined as well. See code below for an
|
||||
example. */
|
||||
|
||||
pthread_t _tx_linux_timer_id;
|
||||
sem_t _tx_linux_timer_semaphore;
|
||||
sem_t _tx_linux_isr_semaphore;
|
||||
void *_tx_linux_timer_interrupt(void *p);
|
||||
|
||||
|
||||
#ifdef TX_LINUX_DEBUG_ENABLE
|
||||
|
||||
extern ULONG _tx_thread_system_state;
|
||||
extern UINT _tx_thread_preempt_disable;
|
||||
extern TX_THREAD *_tx_thread_current_ptr;
|
||||
extern TX_THREAD *_tx_thread_execute_ptr;
|
||||
|
||||
|
||||
/* Define debug log in order to debug Linux issues with this port. */
|
||||
|
||||
typedef struct TX_LINUX_DEBUG_ENTRY_STRUCT
|
||||
{
|
||||
char *tx_linux_debug_entry_action;
|
||||
struct timespec tx_linux_debug_entry_timestamp;
|
||||
char *tx_linux_debug_entry_file;
|
||||
unsigned long tx_linux_debug_entry_line;
|
||||
pthread_mutex_t tx_linux_debug_entry_mutex;
|
||||
unsigned long tx_linux_debug_entry_int_disabled_flag;
|
||||
ULONG tx_linux_debug_entry_system_state;
|
||||
UINT tx_linux_debug_entry_preempt_disable;
|
||||
TX_THREAD *tx_linux_debug_entry_current_thread;
|
||||
TX_THREAD *tx_linux_debug_entry_execute_thread;
|
||||
} TX_LINUX_DEBUG_ENTRY;
|
||||
|
||||
|
||||
/* Define the maximum size of the Linux debug array. */
|
||||
|
||||
#ifndef TX_LINUX_DEBUG_EVENT_SIZE
|
||||
#define TX_LINUX_DEBUG_EVENT_SIZE 400
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the circular array of Linux debug entries. */
|
||||
|
||||
TX_LINUX_DEBUG_ENTRY _tx_linux_debug_entry_array[TX_LINUX_DEBUG_EVENT_SIZE];
|
||||
|
||||
|
||||
/* Define the Linux debug index. */
|
||||
|
||||
unsigned long _tx_linux_debug_entry_index = 0;
|
||||
|
||||
|
||||
/* Now define the debug entry function. */
|
||||
void _tx_linux_debug_entry_insert(char *action, char *file, unsigned long line)
|
||||
{
|
||||
|
||||
pthread_mutex_t temp_copy;
|
||||
|
||||
/* Save the current critical section value. */
|
||||
temp_copy = _tx_linux_mutex;
|
||||
|
||||
/* Lock mutex. */
|
||||
tx_linux_mutex_lock(_tx_linux_mutex);
|
||||
|
||||
/* Get the time stamp. */
|
||||
clock_gettime(CLOCK_REALTIME, &_tx_linux_time_stamp);
|
||||
|
||||
/* Setup the debub entry. */
|
||||
_tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_action = action;
|
||||
_tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_timestamp = _tx_linux_time_stamp;
|
||||
_tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_file = file;
|
||||
_tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_line = line;
|
||||
_tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_mutex = temp_copy;
|
||||
_tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_int_disabled_flag = _tx_linux_global_int_disabled_flag;
|
||||
_tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_system_state = _tx_thread_system_state;
|
||||
_tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_preempt_disable = _tx_thread_preempt_disable;
|
||||
_tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_current_thread = _tx_thread_current_ptr;
|
||||
_tx_linux_debug_entry_array[_tx_linux_debug_entry_index].tx_linux_debug_entry_execute_thread = _tx_thread_execute_ptr;
|
||||
|
||||
/* Now move to the next entry. */
|
||||
_tx_linux_debug_entry_index++;
|
||||
|
||||
/* Determine if we need to wrap the list. */
|
||||
if (_tx_linux_debug_entry_index >= TX_LINUX_DEBUG_EVENT_SIZE)
|
||||
{
|
||||
|
||||
/* Yes, wrap the list! */
|
||||
_tx_linux_debug_entry_index = 0;
|
||||
}
|
||||
|
||||
/* Unlock mutex. */
|
||||
tx_linux_mutex_unlock(_tx_linux_mutex);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the ThreadX timer interrupt handler. */
|
||||
|
||||
void _tx_timer_interrupt(void);
|
||||
|
||||
|
||||
/* Define other external function references. */
|
||||
|
||||
VOID _tx_initialize_low_level(VOID);
|
||||
VOID _tx_thread_context_save(VOID);
|
||||
VOID _tx_thread_context_restore(VOID);
|
||||
|
||||
|
||||
/* Define other external variable references. */
|
||||
|
||||
extern VOID *_tx_initialize_unused_memory;
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_initialize_low_level Linux/GNU */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for any low-level processor */
|
||||
/* initialization, including setting up interrupt vectors, setting */
|
||||
/* up a periodic timer interrupt source, saving the system stack */
|
||||
/* pointer for use in ISR processing later, and finding the first */
|
||||
/* available RAM memory address for tx_application_define. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* sched_setaffinity */
|
||||
/* getpid */
|
||||
/* _tx_linux_thread_init */
|
||||
/* pthread_setschedparam */
|
||||
/* pthread_mutexattr_init */
|
||||
/* pthread_mutex_init */
|
||||
/* _tx_linux_thread_suspend */
|
||||
/* sem_init */
|
||||
/* pthread_create */
|
||||
/* printf */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_initialize_low_level(VOID)
|
||||
{
|
||||
struct sched_param sp;
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
#ifdef TX_LINUX_MULTI_CORE
|
||||
cpu_set_t mask;
|
||||
|
||||
sched_getaffinity(getpid(), sizeof(mask), &mask);
|
||||
if (CPU_COUNT(&mask) > 1)
|
||||
{
|
||||
|
||||
srand((ULONG)pthread_self());
|
||||
|
||||
/* Limit this ThreadX simulation on Linux to a single core. */
|
||||
CPU_ZERO(&mask);
|
||||
CPU_SET(rand() % get_nprocs(), &mask);
|
||||
if (sched_setaffinity(getpid(), sizeof(mask), &mask) != 0)
|
||||
{
|
||||
|
||||
/* Error restricting the process to one core. */
|
||||
printf("ThreadX Linux error restricting the process to one core!\n");
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Pickup the first available memory address. */
|
||||
|
||||
/* Save the first available memory address. */
|
||||
_tx_initialize_unused_memory = malloc(TX_LINUX_MEMORY_SIZE);
|
||||
|
||||
/* Init Linux thread. */
|
||||
_tx_linux_thread_init();
|
||||
|
||||
/* Set priority and schedual of main thread. */
|
||||
sp.sched_priority = TX_LINUX_PRIORITY_SCHEDULE;
|
||||
pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp);
|
||||
|
||||
/* Create the system critical section. This is used by the
|
||||
scheduler thread (which is the main thread) to block all
|
||||
other stuff out. */
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&_tx_linux_mutex, &attr);
|
||||
sem_init(&_tx_linux_semaphore, 0, 0);
|
||||
#ifdef TX_LINUX_NO_IDLE_ENABLE
|
||||
sem_init(&_tx_linux_semaphore_no_idle, 0, 0);
|
||||
#endif /* TX_LINUX_NO_IDLE_ENABLE */
|
||||
|
||||
/* Initialize the global interrupt disabled flag. */
|
||||
_tx_linux_global_int_disabled_flag = TX_FALSE;
|
||||
|
||||
/* Create semaphore for timer thread. */
|
||||
sem_init(&_tx_linux_timer_semaphore, 0, 0);
|
||||
|
||||
/* Create semaphore for ISR thread. */
|
||||
sem_init(&_tx_linux_isr_semaphore, 0, 0);
|
||||
|
||||
/* Setup periodic timer interrupt. */
|
||||
if(pthread_create(&_tx_linux_timer_id, NULL, _tx_linux_timer_interrupt, NULL))
|
||||
{
|
||||
|
||||
/* Error creating the timer interrupt. */
|
||||
printf("ThreadX Linux error creating timer interrupt thread!\n");
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we have a good thread create. Now set the priority to
|
||||
a level lower than the system thread but higher than the application
|
||||
threads. */
|
||||
sp.sched_priority = TX_LINUX_PRIORITY_ISR;
|
||||
pthread_setschedparam(_tx_linux_timer_id, SCHED_FIFO, &sp);
|
||||
|
||||
/* Done, return to caller. */
|
||||
}
|
||||
|
||||
|
||||
/* This routine is called after initialization is complete in order to start
|
||||
all interrupt threads. Interrupt threads in addition to the timer may
|
||||
be added to this routine as well. */
|
||||
|
||||
void _tx_initialize_start_interrupts(void)
|
||||
{
|
||||
|
||||
/* Kick the timer thread off to generate the ThreadX periodic interrupt
|
||||
source. */
|
||||
tx_linux_sem_post(&_tx_linux_timer_semaphore);
|
||||
}
|
||||
|
||||
|
||||
/* Define the ThreadX system timer interrupt. Other interrupts may be simulated
|
||||
in a similar way. */
|
||||
|
||||
void *_tx_linux_timer_interrupt(void *p)
|
||||
{
|
||||
struct timespec ts;
|
||||
long timer_periodic_nsec;
|
||||
int err;
|
||||
|
||||
/* Calculate periodic timer. */
|
||||
timer_periodic_nsec = 1000000000 / TX_TIMER_TICKS_PER_SECOND;
|
||||
nice(10);
|
||||
|
||||
/* Wait startup semaphore. */
|
||||
tx_linux_sem_wait(&_tx_linux_timer_semaphore);
|
||||
|
||||
while(1)
|
||||
{
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ts.tv_nsec += timer_periodic_nsec;
|
||||
if (ts.tv_nsec > 1000000000)
|
||||
{
|
||||
ts.tv_nsec -= 1000000000;
|
||||
ts.tv_sec++;
|
||||
}
|
||||
do
|
||||
{
|
||||
if (sem_timedwait(&_tx_linux_timer_semaphore, &ts) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
err = errno;
|
||||
} while (err != ETIMEDOUT);
|
||||
|
||||
/* Call ThreadX context save for interrupt preparation. */
|
||||
_tx_thread_context_save();
|
||||
|
||||
/* Call trace ISR enter event insert. */
|
||||
_tx_trace_isr_enter_insert(0);
|
||||
|
||||
/* Call the ThreadX system timer interrupt processing. */
|
||||
_tx_timer_interrupt();
|
||||
|
||||
/* Call trace ISR exit event insert. */
|
||||
_tx_trace_isr_exit_insert(0);
|
||||
|
||||
/* Call ThreadX context restore for interrupt completion. */
|
||||
_tx_thread_context_restore();
|
||||
|
||||
#ifdef TX_LINUX_NO_IDLE_ENABLE
|
||||
tx_linux_mutex_lock(_tx_linux_mutex);
|
||||
|
||||
/* Make sure semaphore is 0. */
|
||||
while(!sem_trywait(&_tx_linux_semaphore_no_idle));
|
||||
|
||||
/* Wakeup the system thread by setting the system semaphore. */
|
||||
tx_linux_sem_post(&_tx_linux_semaphore_no_idle);
|
||||
|
||||
tx_linux_mutex_unlock(_tx_linux_mutex);
|
||||
#endif /* TX_LINUX_NO_IDLE_ENABLE */
|
||||
}
|
||||
}
|
||||
|
||||
/* Define functions for linux thread. */
|
||||
void _tx_linux_thread_resume_handler(int sig)
|
||||
{
|
||||
}
|
||||
|
||||
void _tx_linux_thread_suspend_handler(int sig)
|
||||
{
|
||||
if(pthread_equal(pthread_self(), _tx_linux_timer_id))
|
||||
tx_linux_sem_post_nolock(&_tx_linux_thread_timer_wait);
|
||||
else
|
||||
tx_linux_sem_post_nolock(&_tx_linux_thread_other_wait);
|
||||
|
||||
if(_tx_linux_thread_suspended)
|
||||
return;
|
||||
|
||||
_tx_linux_thread_suspended = 1;
|
||||
sigsuspend(&_tx_linux_thread_wait_mask);
|
||||
_tx_linux_thread_suspended = 0;
|
||||
}
|
||||
|
||||
void _tx_linux_thread_suspend(pthread_t thread_id)
|
||||
{
|
||||
|
||||
/* Send signal. */
|
||||
tx_linux_mutex_lock(_tx_linux_mutex);
|
||||
pthread_kill(thread_id, SUSPEND_SIG);
|
||||
tx_linux_mutex_unlock(_tx_linux_mutex);
|
||||
|
||||
/* Wait until signal is received. */
|
||||
if(pthread_equal(thread_id, _tx_linux_timer_id))
|
||||
tx_linux_sem_wait(&_tx_linux_thread_timer_wait);
|
||||
else
|
||||
tx_linux_sem_wait(&_tx_linux_thread_other_wait);
|
||||
}
|
||||
|
||||
void _tx_linux_thread_resume(pthread_t thread_id)
|
||||
{
|
||||
|
||||
/* Send signal. */
|
||||
tx_linux_mutex_lock(_tx_linux_mutex);
|
||||
pthread_kill(thread_id, RESUME_SIG);
|
||||
tx_linux_mutex_unlock(_tx_linux_mutex);
|
||||
}
|
||||
|
||||
void _tx_linux_thread_init()
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
/* Create semaphore for linux thread. */
|
||||
sem_init(&_tx_linux_thread_timer_wait, 0, 0);
|
||||
sem_init(&_tx_linux_thread_other_wait, 0, 0);
|
||||
|
||||
sigfillset(&_tx_linux_thread_wait_mask);
|
||||
sigdelset(&_tx_linux_thread_wait_mask, RESUME_SIG);
|
||||
|
||||
sigfillset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sa.sa_handler = _tx_linux_thread_resume_handler;
|
||||
sigaction(RESUME_SIG, &sa, NULL);
|
||||
|
||||
sa.sa_handler = _tx_linux_thread_suspend_handler;
|
||||
sigaction(SUSPEND_SIG, &sa, NULL);
|
||||
}
|
||||
|
||||
|
||||
163
ports/linux/gnu/src/tx_thread_context_restore.c
Normal file
163
ports/linux/gnu/src/tx_thread_context_restore.c
Normal file
@@ -0,0 +1,163 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_timer.h"
|
||||
|
||||
extern sem_t _tx_linux_isr_semaphore;
|
||||
UINT _tx_linux_timer_waiting = 0;
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_restore Linux/GNU */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* 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_linux_debug_entry_insert */
|
||||
/* tx_linux_mutex_lock */
|
||||
/* sem_trywait */
|
||||
/* tx_linux_sem_post */
|
||||
/* tx_linux_sem_wait */
|
||||
/* _tx_linux_thread_resume */
|
||||
/* tx_linux_mutex_recursive_unlock */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs Interrupt Service Routines */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_context_restore(VOID)
|
||||
{
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("CONTEXT_RESTORE", __FILE__, __LINE__);
|
||||
|
||||
/* Lock mutex to ensure other threads are not playing with
|
||||
the core ThreadX data structures. */
|
||||
tx_linux_mutex_lock(_tx_linux_mutex);
|
||||
|
||||
/* Decrement the nested interrupt count. */
|
||||
_tx_thread_system_state--;
|
||||
|
||||
/* Determine if this is the first nested interrupt and if a ThreadX
|
||||
application thread was running at the time. */
|
||||
if ((!_tx_thread_system_state) && (_tx_thread_current_ptr))
|
||||
{
|
||||
|
||||
/* Yes, this is the first and last interrupt processed. */
|
||||
|
||||
/* Check to see if preemption is required. */
|
||||
if ((_tx_thread_preempt_disable == 0) && (_tx_thread_current_ptr != _tx_thread_execute_ptr))
|
||||
{
|
||||
|
||||
/* Preempt the running application thread. We don't need to suspend the
|
||||
application thread since that is done in the context save processing. */
|
||||
|
||||
/* Indicate that this thread was suspended asynchronously. */
|
||||
_tx_thread_current_ptr -> tx_thread_linux_suspension_type = 1;
|
||||
|
||||
/* Save the remaining time-slice and disable it. */
|
||||
if (_tx_timer_time_slice)
|
||||
{
|
||||
|
||||
_tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
_tx_timer_time_slice = 0;
|
||||
}
|
||||
|
||||
/* Clear the current thread pointer. */
|
||||
_tx_thread_current_ptr = TX_NULL;
|
||||
|
||||
/* Make sure semaphore is 0. */
|
||||
while(!sem_trywait(&_tx_linux_semaphore));
|
||||
|
||||
/* Indicate it is in timer ISR. */
|
||||
_tx_linux_timer_waiting = 1;
|
||||
|
||||
/* Wakeup the system thread by setting the system semaphore. */
|
||||
tx_linux_sem_post(&_tx_linux_semaphore);
|
||||
|
||||
if(_tx_thread_execute_ptr)
|
||||
{
|
||||
if(_tx_thread_execute_ptr -> tx_thread_linux_suspension_type == 0)
|
||||
{
|
||||
|
||||
/* Unlock linux mutex. */
|
||||
tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
|
||||
|
||||
/* Wait until TX_THREAD start running. */
|
||||
tx_linux_sem_wait(&_tx_linux_isr_semaphore);
|
||||
|
||||
tx_linux_mutex_lock(_tx_linux_mutex);
|
||||
|
||||
/* Make sure semaphore is 0. */
|
||||
while(!sem_trywait(&_tx_linux_isr_semaphore));
|
||||
}
|
||||
}
|
||||
|
||||
/* Indicate it is not in timer ISR. */
|
||||
_tx_linux_timer_waiting = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Since preemption is not required, resume the interrupted thread. */
|
||||
_tx_linux_thread_resume(_tx_thread_current_ptr -> tx_thread_linux_thread_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unlock linux mutex. */
|
||||
tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
|
||||
}
|
||||
|
||||
107
ports/linux/gnu/src/tx_thread_context_save.c
Normal file
107
ports/linux/gnu/src/tx_thread_context_save.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_timer.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_save Linux/GNU */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* _tx_linux_debug_entry_insert */
|
||||
/* tx_linux_mutex_lock */
|
||||
/* _tx_linux_thread_suspend */
|
||||
/* tx_linux_mutex_unlock */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_context_save(VOID)
|
||||
{
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("CONTEXT_SAVE", __FILE__, __LINE__);
|
||||
|
||||
/* Lock mutex to ensure other threads are not playing with
|
||||
the core ThreadX data structures. */
|
||||
tx_linux_mutex_lock(_tx_linux_mutex);
|
||||
|
||||
/* If an application thread is running, suspend it to simulate preemption. */
|
||||
if ((_tx_thread_current_ptr) && (_tx_thread_system_state == 0))
|
||||
{
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("CONTEXT_SAVE-suspend_thread", __FILE__, __LINE__);
|
||||
|
||||
/* Yes, this is the first interrupt and an application thread is running...
|
||||
suspend it! */
|
||||
_tx_linux_thread_suspend(_tx_thread_current_ptr -> tx_thread_linux_thread_id);
|
||||
|
||||
/* Indicate that this thread was suspended asynchronously. */
|
||||
_tx_thread_current_ptr -> tx_thread_linux_suspension_type = 1;
|
||||
}
|
||||
|
||||
/* Increment the nested interrupt condition. */
|
||||
_tx_thread_system_state++;
|
||||
|
||||
/* Unlock linux mutex. */
|
||||
tx_linux_mutex_unlock(_tx_linux_mutex);
|
||||
}
|
||||
|
||||
183
ports/linux/gnu/src/tx_thread_interrupt_control.c
Normal file
183
ports/linux/gnu/src/tx_thread_interrupt_control.c
Normal file
@@ -0,0 +1,183 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
/* Define small routines used for the TX_DISABLE/TX_RESTORE macros. */
|
||||
|
||||
UINT _tx_thread_interrupt_disable(void)
|
||||
{
|
||||
|
||||
UINT previous_value;
|
||||
|
||||
|
||||
previous_value = _tx_thread_interrupt_control(TX_INT_DISABLE);
|
||||
return(previous_value);
|
||||
}
|
||||
|
||||
|
||||
VOID _tx_thread_interrupt_restore(UINT previous_posture)
|
||||
{
|
||||
|
||||
previous_posture = _tx_thread_interrupt_control(previous_posture);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_control Linux/GNU */
|
||||
/* 6.0 */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* tx_linux_mutex_lock */
|
||||
/* pthread_self */
|
||||
/* pthread_getschedparam */
|
||||
/* tx_linux_mutex_recursive_unlock */
|
||||
/* pthread_exit */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
UINT _tx_thread_interrupt_control(UINT new_posture)
|
||||
{
|
||||
|
||||
UINT old_posture;
|
||||
TX_THREAD *thread_ptr;
|
||||
pthread_t thread_id;
|
||||
int exit_code = 0;
|
||||
|
||||
|
||||
/* Lock Linux mutex. */
|
||||
tx_linux_mutex_lock(_tx_linux_mutex);
|
||||
|
||||
/* Pickup the id of the current thread. */
|
||||
thread_id = pthread_self();
|
||||
|
||||
/* Pickup the current thread pointer. */
|
||||
thread_ptr = _tx_thread_current_ptr;
|
||||
|
||||
/* Determine if this is a thread and it does not
|
||||
match the current thread pointer. */
|
||||
if ((_tx_linux_threadx_thread) &&
|
||||
((!thread_ptr) || (!pthread_equal(thread_ptr -> tx_thread_linux_thread_id, thread_id))))
|
||||
{
|
||||
|
||||
/* This indicates the Linux thread was actually terminated by ThreadX is only
|
||||
being allowed to run in order to cleanup its resources. */
|
||||
/* Unlock linux mutex. */
|
||||
tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
|
||||
pthread_exit((void *)&exit_code);
|
||||
}
|
||||
|
||||
/* Determine the current interrupt lockout condition. */
|
||||
if (tx_linux_mutex_recursive_count == 1)
|
||||
{
|
||||
|
||||
/* Interrupts are enabled. */
|
||||
old_posture = TX_INT_ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Interrupts are disabled. */
|
||||
old_posture = TX_INT_DISABLE;
|
||||
}
|
||||
|
||||
/* First, determine if this call is from a non-thread. */
|
||||
if (_tx_thread_system_state)
|
||||
{
|
||||
|
||||
/* Determine how to apply the new posture. */
|
||||
if (new_posture == TX_INT_ENABLE)
|
||||
{
|
||||
|
||||
/* Clear the disabled flag. */
|
||||
_tx_linux_global_int_disabled_flag = TX_FALSE;
|
||||
|
||||
/* Determine if the critical section is locked. */
|
||||
tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
|
||||
}
|
||||
else if (new_posture == TX_INT_DISABLE)
|
||||
{
|
||||
|
||||
/* Set the disabled flag. */
|
||||
_tx_linux_global_int_disabled_flag = TX_TRUE;
|
||||
}
|
||||
}
|
||||
else if (thread_ptr)
|
||||
{
|
||||
|
||||
/* Determine how to apply the new posture. */
|
||||
if (new_posture == TX_INT_ENABLE)
|
||||
{
|
||||
|
||||
/* Clear the disabled flag. */
|
||||
_tx_thread_current_ptr -> tx_thread_linux_int_disabled_flag = TX_FALSE;
|
||||
|
||||
/* Determine if the critical section is locked. */
|
||||
tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
|
||||
}
|
||||
else if (new_posture == TX_INT_DISABLE)
|
||||
{
|
||||
|
||||
/* Set the disabled flag. */
|
||||
_tx_thread_current_ptr -> tx_thread_linux_int_disabled_flag = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the previous interrupt disable posture. */
|
||||
return(old_posture);
|
||||
}
|
||||
|
||||
264
ports/linux/gnu/src/tx_thread_schedule.c
Normal file
264
ports/linux/gnu/src/tx_thread_schedule.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_timer.h"
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
extern sem_t _tx_linux_timer_semaphore;
|
||||
extern sem_t _tx_linux_isr_semaphore;
|
||||
extern UINT _tx_linux_timer_waiting;
|
||||
extern pthread_t _tx_linux_timer_id;
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Linux/GNU */
|
||||
/* 6.0 */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* tx_linux_mutex_lock */
|
||||
/* tx_linux_mutex_unlock */
|
||||
/* _tx_linux_debug_entry_insert */
|
||||
/* _tx_linux_thread_resume */
|
||||
/* tx_linux_sem_post */
|
||||
/* sem_trywait */
|
||||
/* tx_linux_sem_wait */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_schedule(VOID)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
/* Set timer. */
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 200000;
|
||||
|
||||
/* Loop forever. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Wait for a thread to execute and all ISRs to complete. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Lock Linux mutex. */
|
||||
tx_linux_mutex_lock(_tx_linux_mutex);
|
||||
|
||||
/* Determine if there is a thread ready to execute AND all ISRs
|
||||
are complete. */
|
||||
if ((_tx_thread_execute_ptr != TX_NULL) && (_tx_thread_system_state == 0))
|
||||
{
|
||||
|
||||
/* Get out of this loop and schedule the thread! */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Unlock linux mutex. */
|
||||
tx_linux_mutex_unlock(_tx_linux_mutex);
|
||||
|
||||
/* Don't waste all the processor time here in the master thread... */
|
||||
#ifdef TX_LINUX_NO_IDLE_ENABLE
|
||||
while(!sem_trywait(&_tx_linux_timer_semaphore));
|
||||
tx_linux_sem_post(&_tx_linux_timer_semaphore);
|
||||
/*nanosleep(&ts, &ts);*/
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ts.tv_nsec += 200000;
|
||||
if (ts.tv_nsec > 1000000000)
|
||||
{
|
||||
ts.tv_nsec -= 1000000000;
|
||||
ts.tv_sec++;
|
||||
}
|
||||
sem_timedwait(&_tx_linux_semaphore_no_idle, &ts);
|
||||
#else
|
||||
nanosleep(&ts, &ts);
|
||||
#endif /* TX_LINUX_NO_IDLE_ENABLE */
|
||||
}
|
||||
}
|
||||
|
||||
/* Yes! We have a thread to execute. Note that the critical section is already
|
||||
active from the scheduling loop above. */
|
||||
|
||||
/* Setup the current thread pointer. */
|
||||
_tx_thread_current_ptr = _tx_thread_execute_ptr;
|
||||
|
||||
/* Increment the run count for this thread. */
|
||||
_tx_thread_current_ptr -> tx_thread_run_count++;
|
||||
|
||||
/* Setup time-slice, if present. */
|
||||
_tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice;
|
||||
|
||||
/* Determine how the thread was suspended. */
|
||||
if (_tx_thread_current_ptr -> tx_thread_linux_suspension_type)
|
||||
{
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("SCHEDULE-resume_thread", __FILE__, __LINE__);
|
||||
|
||||
/* Pseudo interrupt suspension. The thread is not waiting on
|
||||
its run semaphore. */
|
||||
_tx_linux_thread_resume(_tx_thread_current_ptr -> tx_thread_linux_thread_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("SCHEDULE-release_sem", __FILE__, __LINE__);
|
||||
|
||||
/* Make sure semaphore is 0. */
|
||||
while(!sem_trywait(&_tx_thread_current_ptr -> tx_thread_linux_thread_run_semaphore));
|
||||
|
||||
/* Let the thread run again by releasing its run semaphore. */
|
||||
tx_linux_sem_post(&_tx_thread_current_ptr -> tx_thread_linux_thread_run_semaphore);
|
||||
|
||||
/* Block timer ISR. */
|
||||
if(_tx_linux_timer_waiting)
|
||||
{
|
||||
|
||||
/* It is woken up by timer ISR. */
|
||||
/* Let ThreadX thread wake up first. */
|
||||
tx_linux_sem_wait(&_tx_linux_semaphore);
|
||||
|
||||
/* Wake up timer ISR. */
|
||||
tx_linux_sem_post_nolock(&_tx_linux_isr_semaphore);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* It is woken up by TX_THREAD. */
|
||||
/* Suspend timer thread and let ThreadX thread wake up first. */
|
||||
_tx_linux_thread_suspend(_tx_linux_timer_id);
|
||||
tx_linux_sem_wait(&_tx_linux_semaphore);
|
||||
_tx_linux_thread_resume(_tx_linux_timer_id);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Unlock linux mutex. */
|
||||
tx_linux_mutex_unlock(_tx_linux_mutex);
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("SCHEDULE-self_suspend_sem", __FILE__, __LINE__);
|
||||
|
||||
/* Now suspend the main thread so the application thread can run. */
|
||||
tx_linux_sem_wait(&_tx_linux_semaphore);
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("SCHEDULE-wake_up", __FILE__, __LINE__);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void _tx_thread_delete_port_completion(TX_THREAD *thread_ptr, UINT tx_saved_posture)
|
||||
{
|
||||
INT linux_status;
|
||||
sem_t *threadrunsemaphore;
|
||||
pthread_t thread_id;
|
||||
struct timespec ts;
|
||||
|
||||
thread_id = thread_ptr -> tx_thread_linux_thread_id;
|
||||
threadrunsemaphore = &(thread_ptr -> tx_thread_linux_thread_run_semaphore);
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 1000000;
|
||||
TX_RESTORE
|
||||
do
|
||||
{
|
||||
linux_status = pthread_cancel(thread_id);
|
||||
if(linux_status != EAGAIN)
|
||||
{
|
||||
break;
|
||||
}
|
||||
_tx_linux_thread_resume(thread_id);
|
||||
tx_linux_sem_post(threadrunsemaphore);
|
||||
nanosleep(&ts, &ts);
|
||||
} while (1);
|
||||
pthread_join(thread_id, NULL);
|
||||
sem_destroy(threadrunsemaphore);
|
||||
TX_DISABLE
|
||||
}
|
||||
|
||||
void _tx_thread_reset_port_completion(TX_THREAD *thread_ptr, UINT tx_saved_posture)
|
||||
{
|
||||
INT linux_status;
|
||||
sem_t *threadrunsemaphore;
|
||||
pthread_t thread_id;
|
||||
struct timespec ts;
|
||||
|
||||
thread_id = thread_ptr -> tx_thread_linux_thread_id;
|
||||
threadrunsemaphore = &(thread_ptr -> tx_thread_linux_thread_run_semaphore);
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 1000000;
|
||||
TX_RESTORE
|
||||
do
|
||||
{
|
||||
linux_status = pthread_cancel(thread_id);
|
||||
if(linux_status != EAGAIN)
|
||||
{
|
||||
break;
|
||||
}
|
||||
_tx_linux_thread_resume(thread_id);
|
||||
tx_linux_sem_post(threadrunsemaphore);
|
||||
nanosleep(&ts, &ts);
|
||||
} while (1);
|
||||
pthread_join(thread_id, NULL);
|
||||
sem_destroy(threadrunsemaphore);
|
||||
TX_DISABLE
|
||||
}
|
||||
153
ports/linux/gnu/src/tx_thread_stack_build.c
Normal file
153
ports/linux/gnu/src/tx_thread_stack_build.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
/* Prototype for new thread entry function. */
|
||||
|
||||
void *_tx_linux_thread_entry(void *ptr);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_stack_build Linux/GNU */
|
||||
/* 6.0 */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* pthread_create */
|
||||
/* pthread_setschedparam */
|
||||
/* _tx_linux_thread_suspend */
|
||||
/* sem_init */
|
||||
/* printf */
|
||||
/* _tx_linux_thread_resume */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_create Create thread service */
|
||||
/* _tx_thread_reset Reset thread service */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
|
||||
{
|
||||
struct sched_param sp;
|
||||
|
||||
/* Create the run semaphore for the thread. This will allow the scheduler
|
||||
control over when the thread actually runs. */
|
||||
if(sem_init(&thread_ptr -> tx_thread_linux_thread_run_semaphore, 0, 0))
|
||||
{
|
||||
|
||||
/* Display an error message. */
|
||||
printf("ThreadX Linux error creating thread running semaphore!\n");
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a Linux thread for the application thread. */
|
||||
if(pthread_create(&thread_ptr -> tx_thread_linux_thread_id, NULL, _tx_linux_thread_entry, thread_ptr))
|
||||
{
|
||||
|
||||
/* Display an error message. */
|
||||
printf("ThreadX Linux error creating thread!\n");
|
||||
while(1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we have a good thread create. */
|
||||
sp.sched_priority = TX_LINUX_PRIORITY_USER_THREAD;
|
||||
pthread_setschedparam(thread_ptr -> tx_thread_linux_thread_id, SCHED_FIFO, &sp);
|
||||
|
||||
/* Setup the thread suspension type to solicited thread suspension.
|
||||
Pseudo interrupt handlers will suspend with this field set to 1. */
|
||||
thread_ptr -> tx_thread_linux_suspension_type = 0;
|
||||
|
||||
/* Clear the disabled count that will keep track of the
|
||||
tx_interrupt_control nesting. */
|
||||
thread_ptr -> tx_thread_linux_int_disabled_flag = 0;
|
||||
|
||||
/* Setup a fake thread stack pointer. */
|
||||
thread_ptr -> tx_thread_stack_ptr = (VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8);
|
||||
|
||||
/* Clear the first word of the stack. */
|
||||
*(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0;
|
||||
}
|
||||
|
||||
|
||||
void *_tx_linux_thread_entry(void *ptr)
|
||||
{
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
|
||||
/* Pickup the current thread pointer. */
|
||||
thread_ptr = (TX_THREAD *) ptr;
|
||||
_tx_linux_threadx_thread = 1;
|
||||
nice(20);
|
||||
|
||||
/* Now suspend the thread initially. If the thread has already
|
||||
been scheduled, this will return immediately. */
|
||||
tx_linux_sem_wait(&thread_ptr -> tx_thread_linux_thread_run_semaphore);
|
||||
tx_linux_sem_post_nolock(&_tx_linux_semaphore);
|
||||
|
||||
/* Call ThreadX thread entry point. */
|
||||
_tx_thread_shell_entry();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
207
ports/linux/gnu/src/tx_thread_system_return.c
Normal file
207
ports/linux/gnu/src/tx_thread_system_return.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_timer.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_system_return Linux/GNU */
|
||||
/* 6.0 */
|
||||
/* 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 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_linux_debug_entry_insert */
|
||||
/* tx_linux_mutex_lock */
|
||||
/* pthread_self */
|
||||
/* pthread_getschedparam */
|
||||
/* pthread_equal */
|
||||
/* tx_linux_mutex_recursive_unlock */
|
||||
/* tx_linux_mutex_unlock */
|
||||
/* pthread_exit */
|
||||
/* tx_linux_sem_post */
|
||||
/* sem_trywait */
|
||||
/* tx_linux_sem_wait */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ThreadX components */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_system_return(VOID)
|
||||
{
|
||||
|
||||
TX_THREAD *temp_thread_ptr;
|
||||
sem_t *temp_run_semaphore;
|
||||
UINT temp_thread_state;
|
||||
pthread_t thread_id;
|
||||
int exit_code = 0;
|
||||
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("SYSTEM_RETURN", __FILE__, __LINE__);
|
||||
|
||||
/* Lock Linux mutex. */
|
||||
tx_linux_mutex_lock(_tx_linux_mutex);
|
||||
|
||||
/* First, determine if the thread was terminated. */
|
||||
|
||||
/* Pickup the id of the current thread. */
|
||||
thread_id = pthread_self();
|
||||
|
||||
/* Pickup the current thread pointer. */
|
||||
temp_thread_ptr = _tx_thread_current_ptr;
|
||||
|
||||
/* Determine if this is a thread (0) and it does not
|
||||
match the current thread pointer. */
|
||||
if ((_tx_linux_threadx_thread) &&
|
||||
((!temp_thread_ptr) || (!pthread_equal(temp_thread_ptr -> tx_thread_linux_thread_id, thread_id))))
|
||||
{
|
||||
|
||||
/* This indicates the Linux thread was actually terminated by ThreadX is only
|
||||
being allowed to run in order to cleanup its resources. */
|
||||
/* Unlock linux mutex. */
|
||||
tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
|
||||
pthread_exit((void *)&exit_code);
|
||||
}
|
||||
|
||||
/* Determine if the time-slice is active. */
|
||||
if (_tx_timer_time_slice)
|
||||
{
|
||||
|
||||
/* Preserve current remaining time-slice for the thread and clear the current time-slice. */
|
||||
temp_thread_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
_tx_timer_time_slice = 0;
|
||||
}
|
||||
|
||||
/* Save the run semaphore into a temporary variable as well. */
|
||||
temp_run_semaphore = &temp_thread_ptr -> tx_thread_linux_thread_run_semaphore;
|
||||
|
||||
/* Pickup the current thread state. */
|
||||
temp_thread_state = temp_thread_ptr -> tx_thread_state;
|
||||
|
||||
/* Setup the suspension type for this thread. */
|
||||
temp_thread_ptr -> tx_thread_linux_suspension_type = 0;
|
||||
|
||||
/* Set the current thread pointer to NULL. */
|
||||
_tx_thread_current_ptr = TX_NULL;
|
||||
|
||||
/* Unlock Linux mutex. */
|
||||
tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("SYSTEM_RETURN-release_sem", __FILE__, __LINE__);
|
||||
|
||||
/* Make sure semaphore is 0. */
|
||||
while(!sem_trywait(&_tx_linux_semaphore));
|
||||
|
||||
/* Release the semaphore that the main scheduling thread is waiting
|
||||
on. Note that the main scheduling algorithm will take care of
|
||||
setting the current thread pointer to NULL. */
|
||||
tx_linux_sem_post(&_tx_linux_semaphore);
|
||||
|
||||
/* Determine if the thread was self-terminating. */
|
||||
if (temp_thread_state == TX_TERMINATED)
|
||||
{
|
||||
|
||||
/* Exit the thread instead of waiting on the semaphore! */
|
||||
pthread_exit((void *)&exit_code);
|
||||
}
|
||||
|
||||
/* Wait on the run semaphore for this thread. This won't get set again
|
||||
until the thread is scheduled. */
|
||||
tx_linux_sem_wait(temp_run_semaphore);
|
||||
tx_linux_sem_post_nolock(&_tx_linux_semaphore);
|
||||
|
||||
/* Lock Linux mutex. */
|
||||
tx_linux_mutex_lock(_tx_linux_mutex);
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("SYSTEM_RETURN-wake_up", __FILE__, __LINE__);
|
||||
|
||||
/* Determine if the thread was terminated. */
|
||||
|
||||
/* Pickup the current thread pointer. */
|
||||
temp_thread_ptr = _tx_thread_current_ptr;
|
||||
|
||||
/* Determine if this is a thread and it does not
|
||||
match the current thread pointer. */
|
||||
if ((_tx_linux_threadx_thread) &&
|
||||
((!temp_thread_ptr) || (!pthread_equal(temp_thread_ptr -> tx_thread_linux_thread_id, thread_id))))
|
||||
{
|
||||
|
||||
/* Unlock Linux mutex. */
|
||||
tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
|
||||
|
||||
/* This indicates the Linux thread was actually terminated by ThreadX and is only
|
||||
being allowed to run in order to cleanup its resources. */
|
||||
pthread_exit((void *)&exit_code);
|
||||
}
|
||||
|
||||
/* Now determine if the application thread last had interrupts disabled. */
|
||||
|
||||
/* Determine if this thread had interrupts disabled. */
|
||||
if (!_tx_thread_current_ptr -> tx_thread_linux_int_disabled_flag)
|
||||
{
|
||||
|
||||
/* Unlock Linux mutex. */
|
||||
tx_linux_mutex_recursive_unlock(_tx_linux_mutex);
|
||||
}
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("SYSTEM_RETURN-finish", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
153
ports/linux/gnu/src/tx_timer_interrupt.c
Normal file
153
ports/linux/gnu/src/tx_timer_interrupt.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_timer.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_timer_interrupt Linux/GNU */
|
||||
/* 6.0 */
|
||||
/* 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_linux_debug_entry_insert */
|
||||
/* tx_linux_mutex_lock */
|
||||
/* tx_linux_mutex_unlock */
|
||||
/* _tx_timer_expiration_process */
|
||||
/* _tx_thread_time_slice */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* interrupt vector */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_timer_interrupt(VOID)
|
||||
{
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("TIMER INTERRUPT", __FILE__, __LINE__);
|
||||
|
||||
/* Lock mutex to ensure other threads are not playing with
|
||||
the core ThreadX data structures. */
|
||||
tx_linux_mutex_lock(_tx_linux_mutex);
|
||||
|
||||
/* Increment the system clock. */
|
||||
_tx_timer_system_clock++;
|
||||
|
||||
/* Test for time-slice expiration. */
|
||||
if (_tx_timer_time_slice)
|
||||
{
|
||||
|
||||
/* Decrement the time_slice. */
|
||||
_tx_timer_time_slice--;
|
||||
|
||||
/* Check for expiration. */
|
||||
if (_tx_timer_time_slice == 0)
|
||||
{
|
||||
|
||||
/* Set the time-slice expired flag. */
|
||||
_tx_timer_expired_time_slice = TX_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test for timer expiration. */
|
||||
if (*_tx_timer_current_ptr)
|
||||
{
|
||||
|
||||
/* Set expiration flag. */
|
||||
_tx_timer_expired = TX_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* No timer expired, increment the timer pointer. */
|
||||
_tx_timer_current_ptr++;
|
||||
|
||||
/* Check for wrap-around. */
|
||||
if (_tx_timer_current_ptr == _tx_timer_list_end)
|
||||
{
|
||||
|
||||
/* Wrap to beginning of list. */
|
||||
_tx_timer_current_ptr = _tx_timer_list_start;
|
||||
}
|
||||
}
|
||||
|
||||
/* See if anything has expired. */
|
||||
if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
|
||||
{
|
||||
|
||||
/* Did a timer expire? */
|
||||
if (_tx_timer_expired)
|
||||
{
|
||||
|
||||
/* Process timer expiration. */
|
||||
_tx_timer_expiration_process();
|
||||
}
|
||||
|
||||
/* Did time slice expire? */
|
||||
if (_tx_timer_expired_time_slice)
|
||||
{
|
||||
|
||||
/* Time slice interrupted thread. */
|
||||
_tx_thread_time_slice();
|
||||
}
|
||||
}
|
||||
|
||||
/* Unlock linux mutex. */
|
||||
tx_linux_mutex_unlock(_tx_linux_mutex);
|
||||
}
|
||||
|
||||
18
ports/win32/gnu/CMakeLists.txt
Normal file
18
ports/win32/gnu/CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
# {{BEGIN_TARGET_SOURCES}}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.c
|
||||
# {{END_TARGET_SOURCES}}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/inc
|
||||
)
|
||||
Reference in New Issue
Block a user