Release 6.1.10
This commit is contained in:
1165
ports/cortex_a8/ghs/src/tx_el.c
Normal file
1165
ports/cortex_a8/ghs/src/tx_el.c
Normal file
File diff suppressed because it is too large
Load Diff
485
ports/cortex_a8/ghs/src/tx_ghs.c
Normal file
485
ports/cortex_a8/ghs/src/tx_ghs.c
Normal file
@@ -0,0 +1,485 @@
|
||||
/*
|
||||
* ThreadX C/C++ Library Support
|
||||
*
|
||||
* Copyright 1983-2019 Green Hills Software LLC.
|
||||
*
|
||||
* This program is the property of Green Hills Software LLC.,
|
||||
* its contents are proprietary information and no part of it
|
||||
* is to be disclosed to anyone except employees of Green Hills
|
||||
* Software LLC., or as agreed in writing signed by the President
|
||||
* of Green Hills Software LLC.
|
||||
*/
|
||||
|
||||
#include "tx_ghs.h"
|
||||
#ifndef TX_DISABLE_ERROR_CHECKING
|
||||
#define TX_DISABLE_ERROR_CHECKING
|
||||
#endif
|
||||
#include "tx_api.h"
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Allow these routines to access the following ThreadX global variables. */
|
||||
extern ULONG _tx_thread_created_count;
|
||||
extern TX_THREAD *_tx_thread_created_ptr;
|
||||
extern TX_THREAD *_tx_thread_current_ptr;
|
||||
|
||||
#if defined(__ghs) && (__GHS_VERSION_NUMBER >= 500)
|
||||
/* Thread-local storage routines for Green Hills releases 5.x and above. */
|
||||
/*
|
||||
Thread-Local (Per-Thread) Library Data Retrieval
|
||||
================================================
|
||||
|
||||
__ghs_ThreadLocalStorage_specifier defines all library data items
|
||||
that the Green Hills libraries allow to be allocated per-thread.
|
||||
|
||||
An implementation can choose which of these data items to allocate
|
||||
for each thread. For example, an implementation may choose to
|
||||
allocate an errno value for each thread, but not the strtok_saved_pos
|
||||
pointer. The application could then use strtok_r instead of strtok for
|
||||
correct operation.
|
||||
|
||||
To add per-thread library data, define one of the
|
||||
TX_THREAD_EXTENSION_* macros in tx_port.h to include the data item
|
||||
or items in each thread control block TX_THREAD.
|
||||
|
||||
If C++ with exceptions is being used, the __eh_globals entry must be
|
||||
allocated for each thread. This is typically done by default using
|
||||
TX_THREAD_EXTENSION_1 in tx_port.h.
|
||||
|
||||
If __ghs_GetThreadLocalStorageItem is customized to return a
|
||||
per-thread errno value, you should also:
|
||||
|
||||
* Customize the System Library for your project
|
||||
* Define the preprocessor symbol USE_THREAD_LOCAL_ERRNO in
|
||||
src/libsys/ind_errn.c
|
||||
|
||||
If you customize the System Library, you should remove ind_thrd.c
|
||||
from the libsys.gpj subproject.
|
||||
|
||||
*/
|
||||
|
||||
/* Provide global __eh_globals value to support C++ exception handling
|
||||
outside a thread context. This name also forces this module to be
|
||||
included in the linked program instead of the ind_thrd.o module from
|
||||
the System Library libsys.a.
|
||||
*/
|
||||
static void *__eh_globals;
|
||||
|
||||
#pragma ghs startnomisra
|
||||
void *__ghs_GetThreadLocalStorageItem(int specifier)
|
||||
{
|
||||
void *ptlsitem = (void *)0;
|
||||
switch (specifier) {
|
||||
case (int)__ghs_TLS_Errno:
|
||||
/* Set ptslsitem to the address of the per-thread errno value.
|
||||
The per-thread errno value should have the type int.
|
||||
|
||||
If returning a per-thread errno value, follow the steps
|
||||
above.
|
||||
|
||||
This item is used by numerous library functions.
|
||||
*/
|
||||
break;
|
||||
case (int)__ghs_TLS_SignalHandlers:
|
||||
/* Set ptslsitem to the address of the per-thread SignalHandlers
|
||||
array. The per-thread SignalHandlers array should have the
|
||||
array type as in the following declaration:
|
||||
SignalHandler SignalHandlers[_SIGMAX];
|
||||
The SignalHandler type and _SIGMAX constant are defined in
|
||||
ind_thrd.h.
|
||||
|
||||
This item is used by the library functions signal() and
|
||||
raise().
|
||||
*/
|
||||
break;
|
||||
case (int)__ghs_TLS_asctime_buff:
|
||||
/* Set ptslsitem to the address of the per-thread asctime_buff
|
||||
array. The per-thread asctime_buff array should have the
|
||||
array type as in the following declaration:
|
||||
char asctime_buff[30];
|
||||
|
||||
This item is used by the library functions asctime() and
|
||||
ctime(). The library provides asctime_r() and ctime_r(),
|
||||
inherently thread-safe versions of these functions.
|
||||
*/
|
||||
break;
|
||||
case (int)__ghs_TLS_tmpnam_space:
|
||||
/* Set ptslsitem to the address of the per-thread tmpnam_space
|
||||
array. The per-thread tmpnam_space array should have the
|
||||
array type as in the following declaration:
|
||||
char tmpnam_space[L_tmpnam];
|
||||
The constant is defined in <stdio.h>
|
||||
|
||||
This item is used by the library function tmpnam() when
|
||||
passed NULL. The library provides tmpnam_r(), an
|
||||
inherently thread-safe version of tmpnam().
|
||||
*/
|
||||
break;
|
||||
case (int)__ghs_TLS_strtok_saved_pos:
|
||||
/* Set ptslsitem to the address of the per-thread
|
||||
strtok_saved_pos pointer. The per-thread strtok_saved_pos
|
||||
pointer should have the type "char *".
|
||||
|
||||
This item is used by the library function strtok().
|
||||
The library provides strtok_r(), an inherently thread-safe
|
||||
version of strtok().
|
||||
*/
|
||||
break;
|
||||
case (int)__ghs_TLS_gmtime_temp:
|
||||
/* Set ptslsitem to the address of the per-thread gmtime_temp
|
||||
value. The per-thread gmtime_temp value should have the
|
||||
type "struct tm" defined in time.h, included by indos.h.
|
||||
|
||||
This item is used by the library functions gmtime() and
|
||||
localtime(). The library provides gmtime_r() and
|
||||
localtime_r(), inherently thread-safe versions of these
|
||||
functions.
|
||||
*/
|
||||
break;
|
||||
case (int)__ghs_TLS___eh_globals:
|
||||
/* Set ptslsitem to the address of the per-thread __eh_globals
|
||||
value. The per-thread __eh_globals value should have the
|
||||
type "void *".
|
||||
|
||||
This item is used by C++ exception handling.
|
||||
*/
|
||||
if (_tx_thread_current_ptr)
|
||||
ptlsitem = (void *)&(_tx_thread_current_ptr->tx_thread_eh_globals);
|
||||
else
|
||||
/* Use the global __eh_globals pointer. */
|
||||
ptlsitem = (void *)&__eh_globals;
|
||||
break;
|
||||
}
|
||||
return ptlsitem;
|
||||
}
|
||||
#pragma ghs endnomisra
|
||||
#else
|
||||
/* Thread-local storage routines for Green Hills releases 4.x and 3.x . */
|
||||
|
||||
/*
|
||||
* ThreadX C and C++ thread-safe library support routines.
|
||||
*
|
||||
* This implementation merely tries to guarantee thread safety within
|
||||
* individual C library calls such as malloc() and free(), but it does
|
||||
* not attempt to solve the problems associated with the following
|
||||
* multithreaded issues:
|
||||
*
|
||||
* 1. Use of errno. This can be made thread-safe by adding errno
|
||||
* to TX_THREAD_PORT_EXTENSION and using that within a modified
|
||||
* version of libsys/ind_errno.c.
|
||||
*
|
||||
* 2. Thread safety ACROSS library calls. Certain C library calls either
|
||||
* return pointers to statically-allocated data structures or maintain
|
||||
* state across calls. These include strtok(), asctime(), gmtime(),
|
||||
* tmpnam(NULL), signal(). To make such C library routines thread-safe
|
||||
* would require adding a ThreadLocalStorage struct to the thread control
|
||||
* block TX_THREAD. Since relatively few applications make use of these
|
||||
* library routines, the implementation provided here uses a single, global
|
||||
* ThreadLocalStorage data structure rather than greatly increasing the size
|
||||
* of the thread control block TX_THREAD.
|
||||
*
|
||||
* The ThreadX global variable _tx_thread_current_ptr points to the
|
||||
* current thread's control block TX_THREAD. If a ThreadLocalStorage struct
|
||||
* called tx_tls is placed in TX_THREAD, the function GetThreadLocalStorage
|
||||
* should be modified to return &(_tx_thread_current_ptr->tx_tls).
|
||||
*/
|
||||
|
||||
static ThreadLocalStorage GlobalTLS;
|
||||
|
||||
ThreadLocalStorage *GetThreadLocalStorage()
|
||||
{
|
||||
return &GlobalTLS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use a global ThreadX mutex to implement thread safety within C and C++
|
||||
* library routines.
|
||||
*
|
||||
*/
|
||||
TX_MUTEX __ghLockMutex;
|
||||
|
||||
/*
|
||||
* Acquire general lock. Blocks until the lock becomes available.
|
||||
* Use tx_mutex_get to implement __ghsLock
|
||||
*/
|
||||
void __ghsLock(void)
|
||||
{
|
||||
tx_mutex_get(&__ghLockMutex, TX_WAIT_FOREVER);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release general lock
|
||||
* Use tx_mutex_put to implement __ghsUnlock
|
||||
*/
|
||||
void __ghsUnlock(void)
|
||||
{
|
||||
tx_mutex_put(&__ghLockMutex);
|
||||
}
|
||||
|
||||
/* ThreadX Initialization function prototype. */
|
||||
void _tx_initialize_kernel_setup(void);
|
||||
|
||||
void __gh_lock_init(void)
|
||||
{
|
||||
/* Initialize the low-level portions of ThreadX. */
|
||||
_tx_initialize_kernel_setup();
|
||||
|
||||
/* Create the global thread lock mutex. */
|
||||
tx_mutex_create(&__ghLockMutex, "__ghLockMutex", TX_NO_INHERIT);
|
||||
}
|
||||
|
||||
/*
|
||||
Saving State Across setjmp() Calls
|
||||
==================================
|
||||
|
||||
These routines can be used to save and restore arbitrary state
|
||||
across calls to setjmp() and longjmp().
|
||||
*/
|
||||
int __ghs_SaveSignalContext(jmp_buf jmpbuf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Restore arbitrary state across a longjmp() */
|
||||
void __ghs_RestoreSignalContext(jmp_buf jmpbuf)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(__GHS_VERSION_NUMBER) && (__GHS_VERSION_NUMBER < 560)
|
||||
/*
|
||||
C++ Exception Handling
|
||||
======================
|
||||
|
||||
These routines allow C++ exceptions to be used in multiple threads.
|
||||
The default implementation uses __ghs_GetThreadLocalStorageItem
|
||||
to return a thread-specific __eh_globals pointer.
|
||||
|
||||
*/
|
||||
|
||||
/* Must be called after __cpp_exception_init() is called to allocate
|
||||
* and initialize the per-thread exception handling structure */
|
||||
void *__get_eh_globals(void)
|
||||
{
|
||||
#if defined(__ghs) && (__GHS_VERSION_NUMBER >= 500)
|
||||
return *(void **)__ghs_GetThreadLocalStorageItem(__ghs_TLS___eh_globals);
|
||||
#else
|
||||
if (_tx_thread_current_ptr)
|
||||
|
||||
/* Return thread-specific __eh_globals pointer. */
|
||||
return _tx_thread_current_ptr->tx_thread_eh_globals;
|
||||
else
|
||||
/* Return the global __eh_globals pointer. */
|
||||
return GlobalTLS.__eh_globals;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ghs) && (__GHS_VERSION_NUMBER >= 500)
|
||||
#pragma weak __cpp_exception_init
|
||||
extern void __cpp_exception_init(void **);
|
||||
#pragma weak __cpp_exception_cleanup
|
||||
extern void __cpp_exception_cleanup(void **);
|
||||
|
||||
/* __tx_cpp_exception_init retrieves the eh_globals field from
|
||||
thread-local storage and calls __cpp_exception_init.
|
||||
*/
|
||||
void __tx_cpp_exception_init(TX_THREAD *thread_ptr) {
|
||||
void **peh_globals;
|
||||
if(__cpp_exception_init) {
|
||||
if (thread_ptr)
|
||||
peh_globals = &(thread_ptr->tx_thread_eh_globals);
|
||||
else
|
||||
/* Use the global __eh_globals pointer. */
|
||||
peh_globals = &__eh_globals;
|
||||
__cpp_exception_init(peh_globals);
|
||||
}
|
||||
}
|
||||
|
||||
/* __tx_cpp_exception_cleanup retrieves the eh_globals field from
|
||||
thread-local storage and calls __cpp_exception_cleanup.
|
||||
*/
|
||||
void __tx_cpp_exception_cleanup(TX_THREAD *thread_ptr) {
|
||||
void **peh_globals;
|
||||
if(__cpp_exception_cleanup) {
|
||||
if (thread_ptr)
|
||||
peh_globals = &(thread_ptr->tx_thread_eh_globals);
|
||||
else
|
||||
/* Use the global __eh_globals pointer. */
|
||||
peh_globals = &__eh_globals;
|
||||
__cpp_exception_cleanup(peh_globals);
|
||||
}
|
||||
}
|
||||
|
||||
/* __ghs_cpp_exception_init is called from ind_crt1.o to initialize
|
||||
exceptions for the global context.
|
||||
*/
|
||||
void __ghs_cpp_exception_init() {
|
||||
__tx_cpp_exception_init((void *)0);
|
||||
}
|
||||
|
||||
/* __ghs_cpp_exception_cleanup is called from ind_exit.o to clean up
|
||||
exceptions for the global context.
|
||||
*/
|
||||
void __ghs_cpp_exception_cleanup(TX_THREAD *thread_ptr) {
|
||||
__tx_cpp_exception_cleanup((void *)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
File Locks
|
||||
======================
|
||||
|
||||
These routines can be customized to implement per-file locks to allow
|
||||
thread-safe I/O.
|
||||
|
||||
*/
|
||||
|
||||
/* Acquire lock for FILE *addr */
|
||||
void __ghs_flock_file(void *addr)
|
||||
{
|
||||
tx_mutex_get((TX_MUTEX *)addr, TX_WAIT_FOREVER);
|
||||
}
|
||||
|
||||
/* Release lock for FILE *addr */
|
||||
void __ghs_funlock_file(void *addr)
|
||||
{
|
||||
tx_mutex_put((TX_MUTEX *)addr);
|
||||
}
|
||||
|
||||
/* Non blocking acquire lock for FILE *addr. May return -1 if */
|
||||
/* not implemented. Returns 0 on success and nonzero otherwise. */
|
||||
int __ghs_ftrylock_file(void *addr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Calls to initialize local lock data structures before they */
|
||||
/* are used. */
|
||||
void __ghs_flock_create(void **addr)
|
||||
{
|
||||
*addr = (void *)(&__ghLockMutex);
|
||||
}
|
||||
void __ghs_flock_destroy(void *addr) {}
|
||||
|
||||
|
||||
/*
|
||||
* ThreadX Peak Stack Checking support routines.
|
||||
*
|
||||
* All of these routines are called by MULTI's ThreadX-aware debugging
|
||||
* package to determine the peak stack use for one thread or for all threads.
|
||||
*
|
||||
* These routines are included in this file in order to guarantee that they will
|
||||
* be available while debugging with MULTI. These routines are not referenced by
|
||||
* any other part of the ThreadX system.
|
||||
*
|
||||
* _txs_thread_stack_check: return the peak stack usage for a thread.
|
||||
*
|
||||
* _txs_thread_stack_check_2: store the peak stack usage for all threads
|
||||
* in the tx_thread_stack_size field of each thread
|
||||
* control block, TX_THREAD. This routine takes
|
||||
* advantage of the redundancy within the TX_THREAD
|
||||
* structure since tx_thread_stack_size can be computed
|
||||
* from the tx_thread_stack_start and tx_thread_stack_end
|
||||
* fields of TX_THREAD.
|
||||
*
|
||||
* _txs_thread_stack_check_2_fixup: clean up from the _txs_thread_stack_check_2
|
||||
* call by computing the stack size for each
|
||||
* thread and storing the result in the
|
||||
* tx_thread_stack_size field of each thread control
|
||||
* block TX_THREAD.
|
||||
*
|
||||
* These three routines do not support architectures such as i960 or StarCore
|
||||
* where the stack grows up instead of down.
|
||||
*
|
||||
*/
|
||||
#ifndef TX_DISABLE_STACK_CHECKING
|
||||
|
||||
ULONG _txs_thread_stack_check(TX_THREAD *thread_ptr)
|
||||
{
|
||||
CHAR *cp; /* Pointer inside thread's stack. */
|
||||
|
||||
/* Search through the thread's stack to find the highest address modified. */
|
||||
for ( cp = (CHAR *)thread_ptr->tx_thread_stack_start;
|
||||
cp <= (CHAR *)thread_ptr->tx_thread_stack_end; ++cp ) {
|
||||
|
||||
/* Check if this byte in the stack contains something other than TX_STACK_FILL. */
|
||||
if (*cp != (char)TX_STACK_FILL) {
|
||||
|
||||
/* Assume cp points to the locating marking the peak stack use.
|
||||
Return the number of bytes from cp up to and including the
|
||||
end of the stack. */
|
||||
return (((ULONG)thread_ptr->tx_thread_stack_end) - (ULONG)cp + 1);
|
||||
}
|
||||
}
|
||||
return thread_ptr->tx_thread_stack_size;
|
||||
}
|
||||
|
||||
|
||||
int _txs_thread_stack_check_2(void) {
|
||||
CHAR * cp; /* Pointer inside thread's stack. */
|
||||
TX_THREAD * tp; /* Pointer to each thread. */
|
||||
|
||||
/* If no threads are created, return immediately. */
|
||||
if (!_tx_thread_created_count)
|
||||
return 0;
|
||||
|
||||
/* Start iterating through the threads in the system. Assume that we always
|
||||
have at least one thread (the system timer thread) in the system. */
|
||||
tp = _tx_thread_created_ptr;
|
||||
|
||||
do {
|
||||
|
||||
/* Search through the thread's stack to find the highest address modified. */
|
||||
for ( cp = (CHAR *)tp->tx_thread_stack_start; cp <= (CHAR *)tp->tx_thread_stack_end;
|
||||
++cp ) {
|
||||
|
||||
/* Check if this byte in the stack contains something other than TX_STACK_FILL. */
|
||||
if (*cp != (char)TX_STACK_FILL) {
|
||||
|
||||
/* Assume cp points to the locating marking the peak stack use.
|
||||
Store the number of bytes from cp up to and including the
|
||||
end of the stack in the tx_thread_stack_size field. */
|
||||
tp->tx_thread_stack_size = ((ULONG)tp->tx_thread_stack_end) - (ULONG)cp + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Continue with the next thread. */
|
||||
tp = tp->tx_thread_created_next;
|
||||
|
||||
/* Loop until we point to the first thread again. */
|
||||
} while ( tp != _tx_thread_created_ptr );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _txs_thread_stack_check_2_fixup(void) {
|
||||
TX_THREAD * tp; /* Pointer to each thread. */
|
||||
|
||||
/* If no threads are created, return immediately. */
|
||||
if (!_tx_thread_created_count)
|
||||
return 0;
|
||||
|
||||
/* Start iterating through the threads in the system. Assume that we always
|
||||
have at least one thread (the system timer thread) in the system. */
|
||||
tp = _tx_thread_created_ptr;
|
||||
|
||||
do {
|
||||
|
||||
/* Compute the tx_thread_stack_size field by using the tx_thread_stack_end and
|
||||
tx_thread_stack_start fields. */
|
||||
tp->tx_thread_stack_size = (ULONG)tp->tx_thread_stack_end-(ULONG)tp->tx_thread_stack_start+1;
|
||||
|
||||
/* Continue with the next thread. */
|
||||
tp = tp->tx_thread_created_next;
|
||||
|
||||
/* Loop until we point to the first thread again. */
|
||||
} while ( tp != _tx_thread_created_ptr );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* TX_DISABLE_STACK_CHECKING */
|
||||
49
ports/cortex_a8/ghs/src/tx_ghse.c
Normal file
49
ports/cortex_a8/ghs/src/tx_ghse.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* ThreadX C++ Library Support
|
||||
*
|
||||
* Copyright 1983-2019 Green Hills Software LLC.
|
||||
*
|
||||
* This program is the property of Green Hills Software LLC.,
|
||||
* its contents are proprietary information and no part of it
|
||||
* is to be disclosed to anyone except employees of Green Hills
|
||||
* Software LLC., or as agreed in writing signed by the President
|
||||
* of Green Hills Software LLC.
|
||||
*/
|
||||
#include "tx_ghs.h"
|
||||
#ifndef TX_DISABLE_ERROR_CHECKING
|
||||
#define TX_DISABLE_ERROR_CHECKING
|
||||
#endif
|
||||
#include "tx_api.h"
|
||||
|
||||
/*
|
||||
C++ Exception Handling
|
||||
======================
|
||||
|
||||
These routines allow C++ exceptions to be used in multiple threads.
|
||||
The default implementation uses __ghs_GetThreadLocalStorageItem
|
||||
to return a thread-specific __eh_globals pointer.
|
||||
|
||||
*/
|
||||
|
||||
#if defined(__ghs) && (__GHS_VERSION_NUMBER >= 560)
|
||||
#ifdef _WIN32
|
||||
/* Windows uses a different linker, so include a stub routine, never called,
|
||||
to pull in __cpp_exception_init and __cpp_exception_cleanup */
|
||||
extern void __cpp_exception_init(void **);
|
||||
extern void __cpp_exception_cleanup(void **);
|
||||
void __tx_win32_pull_in_exceptions(void) {
|
||||
__cpp_exception_init(0);
|
||||
__cpp_exception_cleanup(0);
|
||||
}
|
||||
#else
|
||||
#pragma ghs reference __cpp_exception_init
|
||||
#pragma ghs reference __cpp_exception_cleanup
|
||||
#endif
|
||||
|
||||
/* Must be called after __cpp_exception_init() is called to allocate
|
||||
* and initialize the per-thread exception handling structure */
|
||||
void *__get_eh_globals(void)
|
||||
{
|
||||
return *(void **)__ghs_GetThreadLocalStorageItem(__ghs_TLS___eh_globals);
|
||||
}
|
||||
#endif
|
||||
259
ports/cortex_a8/ghs/src/tx_thread_context_restore.arm
Normal file
259
ports/cortex_a8/ghs/src/tx_thread_context_restore.arm
Normal file
@@ -0,0 +1,259 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
DISABLE_INTS = 0xC0 # Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
DISABLE_INTS = 0x80 # Disable IRQ interrupts
|
||||
#endif
|
||||
SVC_MODE = (0x13 | DISABLE_INTS) # SVC mode
|
||||
IRQ_MODE = (0x12 | DISABLE_INTS) # IRQ mode
|
||||
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_restore Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_context_restore(VOID)
|
||||
{ */
|
||||
.globl _tx_thread_context_restore
|
||||
_tx_thread_context_restore:
|
||||
|
||||
/* Lockout interrupts. */
|
||||
|
||||
#ifdef TX_BEFORE_ARMV6
|
||||
MRS r3, CPSR # Pickup current CPSR
|
||||
ORR r0, r3, DISABLE_INTS # Build interrupt disable value
|
||||
MSR CPSR_c, r0 # Lockout interrupts
|
||||
#else
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if # Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSID i # Disable IRQ interrupts
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR exit function to indicate an ISR is complete. */
|
||||
|
||||
BL _tx_execution_isr_exit # Call the ISR exit function
|
||||
#endif
|
||||
|
||||
/* Determine if interrupts are nested. */
|
||||
/* if (--_tx_thread_system_state)
|
||||
{ */
|
||||
|
||||
LDR r3, =_tx_thread_system_state # Pickup address of system state var
|
||||
LDR r2, [r3] # Pickup system state
|
||||
SUB r2, r2, 1 # Decrement the counter
|
||||
STR r2, [r3] # Store the counter
|
||||
CMP r2, 0 # Was this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_restore # If so, not a nested restore
|
||||
|
||||
/* Interrupts are nested. */
|
||||
|
||||
/* Just recover the saved registers and return to the point of
|
||||
interrupt. */
|
||||
|
||||
LDMIA sp!, {r0, r10, r12, lr} # Recover SPSR, POI, and scratch regs
|
||||
MSR SPSR_cxsf, r0 # Put SPSR back
|
||||
LDMIA sp!, {r0-r3} # Recover r0-r3
|
||||
MOVS pc, lr # Return to point of interrupt
|
||||
|
||||
/* } */
|
||||
__tx_thread_not_nested_restore:
|
||||
|
||||
/* Determine if a thread was interrupted and no preemption is required. */
|
||||
/* else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr)
|
||||
|| (_tx_thread_preempt_disable))
|
||||
{ */
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr # Pickup address of current thread ptr
|
||||
LDR r0, [r1] # Pickup actual current thread pointer
|
||||
CMP r0, 0 # Is it NULL?
|
||||
BEQ __tx_thread_idle_system_restore # Yes, idle system was interrupted
|
||||
|
||||
LDR r3, =_tx_thread_preempt_disable # Pickup preempt disable address
|
||||
LDR r2, [r3] # Pickup actual preempt disable flag
|
||||
CMP r2, 0 # Is it set?
|
||||
BNE __tx_thread_no_preempt_restore # Yes, don't preempt this thread
|
||||
LDR r3, =_tx_thread_execute_ptr # Pickup address of execute thread ptr
|
||||
LDR r2, [r3] # Pickup actual execute thread pointer
|
||||
CMP r0, r2 # Is the same thread highest priority?
|
||||
BNE __tx_thread_preempt_restore # No, preemption needs to happen
|
||||
|
||||
|
||||
__tx_thread_no_preempt_restore:
|
||||
|
||||
/* Restore interrupted thread or ISR. */
|
||||
|
||||
/* Pickup the saved stack pointer. */
|
||||
/* tmp_ptr = _tx_thread_current_ptr -> tx_thread_stack_ptr; */
|
||||
|
||||
/* Recover the saved context and return to the point of interrupt. */
|
||||
|
||||
LDMIA sp!, {r0, r10, r12, lr} # Recover SPSR, POI, and scratch regs
|
||||
MSR SPSR_cxsf, r0 # Put SPSR back
|
||||
LDMIA sp!, {r0-r3} # Recover r0-r3
|
||||
MOVS pc, lr # Return to point of interrupt
|
||||
|
||||
/* }
|
||||
else
|
||||
{ */
|
||||
__tx_thread_preempt_restore:
|
||||
|
||||
LDMIA sp!, {r3, r10, r12, lr} # Recover temporarily saved registers
|
||||
MOV r1, lr # Save lr (point of interrupt)
|
||||
MOV r2, SVC_MODE # Build SVC mode CPSR
|
||||
MSR CPSR_c, r2 # Enter SVC mode
|
||||
STR r1, [sp, -4]! # Save point of interrupt
|
||||
STMDB sp!, {r4-r12, lr} # Save upper half of registers
|
||||
MOV r4, r3 # Save SPSR in r4
|
||||
MOV r2, IRQ_MODE # Build IRQ mode CPSR
|
||||
MSR CPSR_c, r2 # Re-enter IRQ mode
|
||||
LDMIA sp!, {r0-r3} # Recover r0-r3
|
||||
MOV r5, SVC_MODE # Build SVC mode CPSR
|
||||
MSR CPSR_c, r5 # Enter SVC mode
|
||||
STMDB sp!, {r0-r3} # Save r0-r3 on thread's stack
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr # Pickup address of current thread ptr
|
||||
LDR r0, [r1] # Pickup current thread pointer
|
||||
|
||||
#ifdef __VFP__
|
||||
LDR r2, [r0, 144] # Pickup the VFP enabled flag
|
||||
CMP r2, 0 # Is the VFP enabled?
|
||||
BEQ _tx_skip_irq_vfp_save # No, skip VFP IRQ save
|
||||
VMRS r2, FPSCR # Pickup the FPSCR
|
||||
STR r2, [sp, -4]! # Save FPSCR
|
||||
VSTMDB sp!, {D16-D31} # Save D16-D31
|
||||
VSTMDB sp!, {D0-D15} # Save D0-D15
|
||||
_tx_skip_irq_vfp_save:
|
||||
#endif
|
||||
|
||||
MOV r3, 1 # Build interrupt stack type
|
||||
STMDB sp!, {r3, r4} # Save interrupt stack type and SPSR
|
||||
STR sp, [r0, 8] # Save stack pointer in thread control
|
||||
/* # block */
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_LOGGING
|
||||
MOV r4, r0 # Save r0
|
||||
MOV r5, r1 # Save r1
|
||||
BL _tx_el_thread_preempted # Call thread preempted routine
|
||||
MOV r0, r4 # Restore r0
|
||||
MOV r1, r5 # Restore r1
|
||||
#endif
|
||||
|
||||
/* Save the remaining time-slice and disable it. */
|
||||
/* if (_tx_timer_time_slice)
|
||||
{ */
|
||||
|
||||
LDR r3, =_tx_timer_time_slice # Pickup time-slice variable address
|
||||
LDR r2, [r3] # Pickup time-slice
|
||||
CMP r2, 0 # Is it active?
|
||||
BEQ __tx_thread_dont_save_ts # No, don't save it
|
||||
|
||||
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
_tx_timer_time_slice = 0; */
|
||||
|
||||
STR r2, [r0, 24] # Save thread's time-slice
|
||||
MOV r2, 0 # Clear value
|
||||
STR r2, [r3] # Disable global time-slice flag
|
||||
|
||||
/* } */
|
||||
__tx_thread_dont_save_ts:
|
||||
|
||||
|
||||
/* Clear the current task pointer. */
|
||||
/* _tx_thread_current_ptr = TX_NULL; */
|
||||
|
||||
MOV r0, 0 # NULL value
|
||||
STR r0, [r1] # Clear current thread pointer
|
||||
|
||||
/* Return to the scheduler. */
|
||||
/* _tx_thread_schedule(); */
|
||||
|
||||
B _tx_thread_schedule # Return to scheduler
|
||||
/* } */
|
||||
|
||||
__tx_thread_idle_system_restore:
|
||||
|
||||
/* Just return back to the scheduler! */
|
||||
|
||||
|
||||
MOV r3, SVC_MODE # Build SVC mode CPSR
|
||||
MSR CPSR_c, r3 # Lockout interrupts
|
||||
B _tx_thread_schedule # Return to scheduler
|
||||
|
||||
.type _tx_thread_context_restore,$function
|
||||
.size _tx_thread_context_restore,.-_tx_thread_context_restore
|
||||
|
||||
/* } */
|
||||
|
||||
207
ports/cortex_a8/ghs/src/tx_thread_context_save.arm
Normal file
207
ports/cortex_a8/ghs/src/tx_thread_context_save.arm
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" */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
DISABLE_INTS = 0xC0 # IRQ & FIQ interrupts disabled
|
||||
#else
|
||||
DISABLE_INTS = 0x80 # IRQ interrupts disabled
|
||||
#endif
|
||||
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_save Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_context_save(VOID)
|
||||
{ */
|
||||
.globl _tx_thread_context_save
|
||||
_tx_thread_context_save:
|
||||
|
||||
/* Upon entry to this routine, it is assumed that IRQ interrupts are locked
|
||||
out, we are in IRQ mode, and all registers are intact. */
|
||||
|
||||
/* Check for a nested interrupt condition. */
|
||||
/* if (_tx_thread_system_state++)
|
||||
{ */
|
||||
|
||||
STMDB sp!, {r0-r3} # Save some working registers
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
#ifdef TX_BEFORE_ARMV6
|
||||
MRS r0, CPSR # Pickup the CPSR
|
||||
ORR r0, r0, DISABLE_INTS # Build disable interrupt CPSR
|
||||
MSR CPSR_c, r0 # Disable interrupts
|
||||
#else
|
||||
CPSID if # Disable FIQ interrupts
|
||||
#endif
|
||||
#endif
|
||||
|
||||
LDR r3, =_tx_thread_system_state # Pickup address of system state var
|
||||
LDR r2, [r3] # Pickup system state
|
||||
CMP r2, 0 # Is this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_save # Yes, not a nested context save
|
||||
|
||||
/* Nested interrupt condition. */
|
||||
|
||||
ADD r2, r2, 1 # Increment the interrupt counter
|
||||
STR r2, [r3] # Store it back in the variable
|
||||
|
||||
/* Save the rest of the scratch registers on the stack and return to the
|
||||
calling ISR. */
|
||||
|
||||
MRS r0, SPSR # Pickup saved SPSR
|
||||
SUB lr, lr, 4 # Adjust point of interrupt
|
||||
STMDB sp!, {r0, r10, r12, lr} # Store other registers
|
||||
|
||||
/* Return to the ISR. */
|
||||
|
||||
MOV r10, 0 # Clear stack limit
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} # Save ISR lr
|
||||
BL _tx_execution_isr_enter # Call the ISR enter function
|
||||
POP {lr} # Recover ISR lr
|
||||
#endif
|
||||
|
||||
B __tx_irq_processing_return # Continue IRQ processing
|
||||
|
||||
__tx_thread_not_nested_save:
|
||||
/* } */
|
||||
|
||||
/* Otherwise, not nested, check to see if a thread was running. */
|
||||
/* else if (_tx_thread_current_ptr)
|
||||
{ */
|
||||
|
||||
ADD r2, r2, 1 # Increment the interrupt counter
|
||||
STR r2, [r3] # Store it back in the variable
|
||||
LDR r1, =_tx_thread_current_ptr # Pickup address of current thread ptr
|
||||
LDR r0, [r1] # Pickup current thread pointer
|
||||
CMP r0, 0 # Is it NULL?
|
||||
BEQ __tx_thread_idle_system_save # If so, interrupt occurred in
|
||||
/* # scheduling loop - nothing needs saving! */
|
||||
|
||||
/* Save minimal context of interrupted thread. */
|
||||
|
||||
MRS r2, SPSR # Pickup saved SPSR
|
||||
SUB lr, lr, 4 # Adjust point of interrupt
|
||||
STMDB sp!, {r2, r10, r12, lr} # Store other registers
|
||||
|
||||
/* Save the current stack pointer in the thread's control block. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */
|
||||
|
||||
/* Switch to the system stack. */
|
||||
/* sp = _tx_thread_system_stack_ptr; */
|
||||
|
||||
MOV r10, 0 # Clear stack limit
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} # Save ISR lr
|
||||
BL _tx_execution_isr_enter # Call the ISR enter function
|
||||
POP {lr} # Recover ISR lr
|
||||
#endif
|
||||
|
||||
B __tx_irq_processing_return # Continue IRQ processing
|
||||
|
||||
/* }
|
||||
else
|
||||
{ */
|
||||
|
||||
__tx_thread_idle_system_save:
|
||||
|
||||
/* Interrupt occurred in the scheduling loop. */
|
||||
|
||||
/* Not much to do here, just adjust the stack pointer, and return to IRQ
|
||||
processing. */
|
||||
|
||||
MOV r10, 0 # Clear stack limit
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} # Save ISR lr
|
||||
BL _tx_execution_isr_enter # Call the ISR enter function
|
||||
POP {lr} # Recover ISR lr
|
||||
#endif
|
||||
|
||||
ADD sp, sp, 16 # Recover saved registers
|
||||
B __tx_irq_processing_return # Continue IRQ processing
|
||||
|
||||
.type _tx_thread_context_save,$function
|
||||
.size _tx_thread_context_save,.-_tx_thread_context_save
|
||||
|
||||
/* }
|
||||
} */
|
||||
|
||||
264
ports/cortex_a8/ghs/src/tx_thread_fiq_context_restore.arm
Normal file
264
ports/cortex_a8/ghs/src/tx_thread_fiq_context_restore.arm
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" */
|
||||
|
||||
SVC_MODE = 0xD3 # SVC mode
|
||||
FIQ_MODE = 0xD1 # FIQ mode
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
DISABLE_INTS = 0xC0 # Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
DISABLE_INTS = 0x80 # Disable IRQ interrupts
|
||||
#endif
|
||||
MODE_MASK = 0x1F # Mode mask
|
||||
IRQ_MODE_BITS = 0x12 # IRQ mode bits
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_fiq_context_restore Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function restores the fiq interrupt context when 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 */
|
||||
/* */
|
||||
/* FIQ ISR Interrupt Service Routines */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_fiq_context_restore(VOID)
|
||||
{ */
|
||||
.globl _tx_thread_fiq_context_restore
|
||||
_tx_thread_fiq_context_restore:
|
||||
|
||||
/* Lockout interrupts. */
|
||||
|
||||
#ifdef TX_BEFORE_ARMV6
|
||||
MRS r3, CPSR # Pickup current CPSR
|
||||
ORR r0, r3, DISABLE_INTS # Build interrupt disable value
|
||||
MSR CPSR_c, r0 # Lockout interrupts
|
||||
#else
|
||||
CPSID if # Disable IRQ and FIQ interrupts
|
||||
#endif
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR exit function to indicate an ISR is complete. */
|
||||
|
||||
BL _tx_execution_isr_exit # Call the ISR exit function
|
||||
#endif
|
||||
|
||||
/* Determine if interrupts are nested. */
|
||||
/* if (--_tx_thread_system_state)
|
||||
{ */
|
||||
|
||||
LDR r3, =_tx_thread_system_state # Pickup address of system state var
|
||||
LDR r2, [r3] # Pickup system state
|
||||
SUB r2, r2, 1 # Decrement the counter
|
||||
STR r2, [r3] # Store the counter
|
||||
CMP r2, 0 # Was this the first interrupt?
|
||||
BEQ __tx_thread_fiq_not_nested_restore # If so, not a nested restore
|
||||
|
||||
/* Interrupts are nested. */
|
||||
|
||||
/* Just recover the saved registers and return to the point of
|
||||
interrupt. */
|
||||
|
||||
LDMIA sp!, {r0, r10, r12, lr} # Recover SPSR, POI, and scratch regs
|
||||
MSR SPSR_cxsf, r0 # Put SPSR back
|
||||
LDMIA sp!, {r0-r3} # Recover r0-r3
|
||||
MOVS pc, lr # Return to point of interrupt
|
||||
|
||||
/* } */
|
||||
__tx_thread_fiq_not_nested_restore:
|
||||
|
||||
/* Determine if a thread was interrupted and no preemption is required. */
|
||||
/* else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr)
|
||||
|| (_tx_thread_preempt_disable))
|
||||
{ */
|
||||
|
||||
LDR r1, [sp] # Pickup the saved SPSR
|
||||
MOV r2, MODE_MASK # Build mask to isolate the interrupted mode
|
||||
AND r1, r1, r2 # Isolate mode bits
|
||||
CMP r1, IRQ_MODE_BITS # Was an interrupt taken in IRQ mode before we
|
||||
/* # got to context save? */
|
||||
BEQ __tx_thread_fiq_no_preempt_restore # Yes, just go back to point of interrupt
|
||||
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr # Pickup address of current thread ptr
|
||||
LDR r0, [r1] # Pickup actual current thread pointer
|
||||
CMP r0, 0 # Is it NULL?
|
||||
BEQ __tx_thread_fiq_idle_system_restore # Yes, idle system was interrupted
|
||||
|
||||
LDR r3, =_tx_thread_preempt_disable # Pickup preempt disable address
|
||||
LDR r2, [r3] # Pickup actual preempt disable flag
|
||||
CMP r2, 0 # Is it set?
|
||||
BNE __tx_thread_fiq_no_preempt_restore # Yes, don't preempt this thread
|
||||
LDR r3, =_tx_thread_execute_ptr # Pickup address of execute thread ptr
|
||||
LDR r2, [r3] # Pickup actual execute thread pointer
|
||||
CMP r0, r2 # Is the same thread highest priority?
|
||||
BNE __tx_thread_fiq_preempt_restore # No, preemption needs to happen
|
||||
|
||||
|
||||
__tx_thread_fiq_no_preempt_restore:
|
||||
|
||||
/* Restore interrupted thread or ISR. */
|
||||
|
||||
/* Pickup the saved stack pointer. */
|
||||
/* tmp_ptr = _tx_thread_current_ptr -> tx_thread_stack_ptr; */
|
||||
|
||||
/* Recover the saved context and return to the point of interrupt. */
|
||||
|
||||
LDMIA sp!, {r0, lr} # Recover SPSR, POI, and scratch regs
|
||||
MSR SPSR_cxsf, r0 # Put SPSR back
|
||||
LDMIA sp!, {r0-r3} # Recover r0-r3
|
||||
MOVS pc, lr # Return to point of interrupt
|
||||
|
||||
/* }
|
||||
else
|
||||
{ */
|
||||
__tx_thread_fiq_preempt_restore:
|
||||
|
||||
LDMIA sp!, {r3, lr} # Recover temporarily saved registers
|
||||
MOV r1, lr # Save lr (point of interrupt)
|
||||
MOV r2, SVC_MODE # Build SVC mode CPSR
|
||||
MSR CPSR_c, r2 # Enter SVC mode
|
||||
STR r1, [sp, -4]! # Save point of interrupt
|
||||
STMDB sp!, {r4-r12, lr} # Save upper half of registers
|
||||
MOV r4, r3 # Save SPSR in r4
|
||||
MOV r2, FIQ_MODE # Build FIQ mode CPSR
|
||||
MSR CPSR_c, r2 # Re-enter FIQ mode
|
||||
LDMIA sp!, {r0-r3} # Recover r0-r3
|
||||
MOV r5, SVC_MODE # Build SVC mode CPSR
|
||||
MSR CPSR_c, r5 # Enter SVC mode
|
||||
STMDB sp!, {r0-r3} # Save r0-r3 on thread's stack
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr # Pickup address of current thread ptr
|
||||
LDR r0, [r1] # Pickup current thread pointer
|
||||
|
||||
#ifdef __VFP__
|
||||
LDR r2, [r0, 144] # Pickup the VFP enabled flag
|
||||
CMP r2, 0 # Is the VFP enabled?
|
||||
BEQ _tx_skip_fiq_vfp_save # No, skip VFP IRQ save
|
||||
VMRS r2, FPSCR # Pickup the FPSCR
|
||||
STR r2, [sp, -4]! # Save FPSCR
|
||||
VSTMDB sp!, {D16-D31} # Save D16-D31
|
||||
VSTMDB sp!, {D0-D15} # Save D0-D15
|
||||
_tx_skip_fiq_vfp_save:
|
||||
#endif
|
||||
|
||||
MOV r3, 1 # Build interrupt stack type
|
||||
STMDB sp!, {r3, r4} # Save interrupt stack type and SPSR
|
||||
STR sp, [r0, 8] # Save stack pointer in thread control
|
||||
/* # block */
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_LOGGING
|
||||
MOV r4, r0 # Save r0
|
||||
MOV r5, r1 # Save r1
|
||||
BL _tx_el_thread_preempted # Call thread preempted routine
|
||||
MOV r0, r4 # Restore r0
|
||||
MOV r1, r5 # Restore r1
|
||||
#endif
|
||||
|
||||
/* Save the remaining time-slice and disable it. */
|
||||
/* if (_tx_timer_time_slice)
|
||||
{ */
|
||||
|
||||
LDR r3, =_tx_timer_time_slice # Pickup time-slice variable address
|
||||
LDR r2, [r3] # Pickup time-slice
|
||||
CMP r2, 0 # Is it active?
|
||||
BEQ __tx_thread_fiq_dont_save_ts # No, don't save it
|
||||
|
||||
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
_tx_timer_time_slice = 0; */
|
||||
|
||||
STR r2, [r0, 24] # Save thread's time-slice
|
||||
MOV r2, 0 # Clear value
|
||||
STR r2, [r3] # Disable global time-slice flag
|
||||
|
||||
/* } */
|
||||
__tx_thread_fiq_dont_save_ts:
|
||||
|
||||
|
||||
/* Clear the current task pointer. */
|
||||
/* _tx_thread_current_ptr = TX_NULL; */
|
||||
|
||||
MOV r0, 0 # NULL value
|
||||
STR r0, [r1] # Clear current thread pointer
|
||||
|
||||
/* Return to the scheduler. */
|
||||
/* _tx_thread_schedule(); */
|
||||
|
||||
B _tx_thread_schedule # Return to scheduler
|
||||
/* } */
|
||||
|
||||
__tx_thread_fiq_idle_system_restore:
|
||||
|
||||
/* Just return back to the scheduler! */
|
||||
|
||||
ADD sp, sp, 24 # Recover FIQ stack space
|
||||
MOV r3, SVC_MODE # Build SVC mode CPSR
|
||||
MSR CPSR_c, r3 # Lockout interrupts
|
||||
B _tx_thread_schedule # Return to scheduler
|
||||
|
||||
.type _tx_thread_fiq_context_restore,$function
|
||||
.size _tx_thread_fiq_context_restore,.-_tx_thread_fiq_context_restore
|
||||
|
||||
/* } */
|
||||
|
||||
197
ports/cortex_a8/ghs/src/tx_thread_fiq_context_save.arm
Normal file
197
ports/cortex_a8/ghs/src/tx_thread_fiq_context_save.arm
Normal file
@@ -0,0 +1,197 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_fiq_context_save Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_fiq_context_save(VOID)
|
||||
{ */
|
||||
.globl _tx_thread_fiq_context_save
|
||||
_tx_thread_fiq_context_save:
|
||||
|
||||
/* Upon entry to this routine, it is assumed that IRQ interrupts are locked
|
||||
out, we are in IRQ mode, and all registers are intact. */
|
||||
|
||||
/* Check for a nested interrupt condition. */
|
||||
/* if (_tx_thread_system_state++)
|
||||
{ */
|
||||
|
||||
STMDB sp!, {r0-r3} # Save some working registers
|
||||
LDR r3, =_tx_thread_system_state # Pickup address of system state var
|
||||
LDR r2, [r3] # Pickup system state
|
||||
CMP r2, 0 # Is this the first interrupt?
|
||||
BEQ __tx_thread_fiq_not_nested_save # Yes, not a nested context save
|
||||
|
||||
/* Nested interrupt condition. */
|
||||
|
||||
ADD r2, r2, 1 # Increment the interrupt counter
|
||||
STR r2, [r3] # Store it back in the variable
|
||||
|
||||
/* Save the rest of the scratch registers on the stack and return to the
|
||||
calling ISR. */
|
||||
|
||||
MRS r0, SPSR # Pickup saved SPSR
|
||||
SUB lr, lr, 4 # Adjust point of interrupt
|
||||
STMDB sp!, {r0, r10, r12, lr} # Store other registers
|
||||
|
||||
/* Return to the ISR. */
|
||||
|
||||
MOV r10, 0 # Clear stack limit
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} # Save ISR lr
|
||||
BL _tx_execution_isr_enter # Call the ISR enter function
|
||||
POP {lr} # Recover ISR lr
|
||||
#endif
|
||||
|
||||
B __tx_fiq_processing_return # Continue FIQ processing
|
||||
|
||||
__tx_thread_fiq_not_nested_save:
|
||||
/* } */
|
||||
|
||||
/* Otherwise, not nested, check to see if a thread was running. */
|
||||
/* else if (_tx_thread_current_ptr)
|
||||
{ */
|
||||
|
||||
ADD r2, r2, 1 # Increment the interrupt counter
|
||||
STR r2, [r3] # Store it back in the variable
|
||||
LDR r1, =_tx_thread_current_ptr # Pickup address of current thread ptr
|
||||
LDR r0, [r1] # Pickup current thread pointer
|
||||
CMP r0, 0 # Is it NULL?
|
||||
BEQ __tx_thread_fiq_idle_system_save # If so, interrupt occurred in
|
||||
/* # scheduling loop - nothing needs saving! */
|
||||
|
||||
/* Save minimal context of interrupted thread. */
|
||||
|
||||
MRS r2, SPSR # Pickup saved SPSR
|
||||
SUB lr, lr, 4 # Adjust point of interrupt
|
||||
STMDB sp!, {r2, lr} # Store other registers, Note that we don't
|
||||
/* # need to save sl and ip since FIQ has
|
||||
# copies of these registers. Nested
|
||||
# interrupt processing does need to save
|
||||
# these registers. */
|
||||
|
||||
/* Save the current stack pointer in the thread's control block. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */
|
||||
|
||||
/* Switch to the system stack. */
|
||||
/* sp = _tx_thread_system_stack_ptr; */
|
||||
|
||||
MOV r10, 0 # Clear stack limit
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} # Save ISR lr
|
||||
BL _tx_execution_isr_enter # Call the ISR enter function
|
||||
POP {lr} # Recover ISR lr
|
||||
#endif
|
||||
|
||||
B __tx_fiq_processing_return # Continue FIQ processing
|
||||
|
||||
/* }
|
||||
else
|
||||
{ */
|
||||
|
||||
__tx_thread_fiq_idle_system_save:
|
||||
|
||||
/* Interrupt occurred in the scheduling loop. */
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} # Save ISR lr
|
||||
BL _tx_execution_isr_enter # Call the ISR enter function
|
||||
POP {lr} # Recover ISR lr
|
||||
#endif
|
||||
|
||||
/* Not much to do here, save the current SPSR and LR for possible
|
||||
use in IRQ interrupted in idle system conditions, and return to
|
||||
FIQ interrupt processing. */
|
||||
|
||||
MRS r0, SPSR # Pickup saved SPSR
|
||||
SUB lr, lr, 4 # Adjust point of interrupt
|
||||
STMDB sp!, {r0, lr} # Store other registers that will get used
|
||||
/* # or stripped off the stack in context
|
||||
# restore */
|
||||
B __tx_fiq_processing_return # Continue FIQ processing
|
||||
|
||||
.type _tx_thread_fiq_context_save,$function
|
||||
.size _tx_thread_fiq_context_save,.-_tx_thread_fiq_context_save
|
||||
|
||||
/* }
|
||||
} */
|
||||
|
||||
109
ports/cortex_a8/ghs/src/tx_thread_fiq_nesting_end.arm
Normal file
109
ports/cortex_a8/ghs/src/tx_thread_fiq_nesting_end.arm
Normal file
@@ -0,0 +1,109 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
DISABLE_INTS = 0xC0 # Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
DISABLE_INTS = 0x80 # Disable IRQ interrupts
|
||||
#endif
|
||||
MODE_MASK = 0x1F # Mode mask
|
||||
FIQ_MODE_BITS = 0x11 # FIQ mode bits
|
||||
SVC_MODE_BITS = 0x13 # SVC mode value */
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_fiq_nesting_end Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is called by the application from FIQ mode after */
|
||||
/* _tx_thread_fiq_nesting_start has been called and switches the FIQ */
|
||||
/* processing from system mode back to FIQ mode prior to the ISR */
|
||||
/* calling _tx_thread_fiq_context_restore. Note that this function */
|
||||
/* assumes the system stack pointer is in the same position after */
|
||||
/* nesting start function was called. */
|
||||
/* */
|
||||
/* This function assumes that the system mode stack pointer was setup */
|
||||
/* during low-level initialization (tx_initialize_low_level.arm). */
|
||||
/* */
|
||||
/* This function returns with FIQ interrupts disabled. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_fiq_nesting_end(VOID)
|
||||
{ */
|
||||
.globl _tx_thread_fiq_nesting_end
|
||||
_tx_thread_fiq_nesting_end:
|
||||
MOV r3,lr # Save ISR return address
|
||||
MRS r0, CPSR # Pickup the CPSR
|
||||
ORR r0, r0, DISABLE_INTS # Build disable interrupt value
|
||||
MSR CPSR_c, r0 # Disable interrupts
|
||||
LDR lr, [sp] # Pickup saved lr
|
||||
ADD sp, sp, 4 # Adjust stack pointer
|
||||
BIC r0, r0, MODE_MASK # Clear mode bits
|
||||
ORR r0, r0, FIQ_MODE_BITS # Build IRQ mode CPSR
|
||||
MSR CPSR_c, r0 # Re-enter IRQ mode
|
||||
MOV pc, r3 # Return to ISR
|
||||
|
||||
.type _tx_thread_fiq_nesting_end,$function
|
||||
.size _tx_thread_fiq_nesting_end,.-_tx_thread_fiq_nesting_end
|
||||
/* } */
|
||||
|
||||
103
ports/cortex_a8/ghs/src/tx_thread_fiq_nesting_start.arm
Normal file
103
ports/cortex_a8/ghs/src/tx_thread_fiq_nesting_start.arm
Normal file
@@ -0,0 +1,103 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
|
||||
FIQ_DISABLE = 0x40 # FIQ disable bit
|
||||
MODE_MASK = 0x1F # Mode mask
|
||||
SYS_MODE_BITS = 0x1F # System mode bits
|
||||
|
||||
|
||||
.text
|
||||
.align 4
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_fiq_nesting_start Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is called by the application from FIQ mode after */
|
||||
/* _tx_thread_fiq_context_save has been called and switches the FIQ */
|
||||
/* processing to the system mode so nested FIQ interrupt processing */
|
||||
/* is possible (system mode has its own "lr" register). Note that */
|
||||
/* this function assumes that the system mode stack pointer was setup */
|
||||
/* during low-level initialization (tx_initialize_low_level.arm). */
|
||||
/* */
|
||||
/* This function returns with FIQ interrupts enabled. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_fiq_nesting_start(VOID)
|
||||
{ */
|
||||
.globl _tx_thread_fiq_nesting_start
|
||||
_tx_thread_fiq_nesting_start:
|
||||
MOV r3,lr # Save ISR return address
|
||||
MRS r0, CPSR # Pickup the CPSR
|
||||
BIC r0, r0, MODE_MASK # Clear the mode bits
|
||||
ORR r0, r0, SYS_MODE_BITS # Build system mode CPSR
|
||||
MSR CPSR_c, r0 # Enter system mode
|
||||
STR lr, [sp, -4]! # Push the system mode lr on the system mode stack
|
||||
BIC r0, r0, FIQ_DISABLE # Build enable FIQ CPSR
|
||||
MSR CPSR_c, r0 # Enter system mode
|
||||
MOV pc, r3 # Return to ISR
|
||||
|
||||
.type _tx_thread_fiq_nesting_start,$function
|
||||
.size _tx_thread_fiq_nesting_start,.-_tx_thread_fiq_nesting_start
|
||||
/* } */
|
||||
|
||||
101
ports/cortex_a8/ghs/src/tx_thread_interrupt_control.arm
Normal file
101
ports/cortex_a8/ghs/src/tx_thread_interrupt_control.arm
Normal file
@@ -0,0 +1,101 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
INT_MASK = 0xC0 # Interrupt bit mask
|
||||
#else
|
||||
INT_MASK = 0x80 # Interrupt bit mask
|
||||
#endif
|
||||
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_control Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for changing the interrupt lockout */
|
||||
/* posture of the system. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* new_posture New interrupt lockout posture */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* old_posture Old interrupt lockout posture */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* UINT _tx_thread_interrupt_control(UINT new_posture)
|
||||
{ */
|
||||
.globl _tx_thread_interrupt_control
|
||||
_tx_thread_interrupt_control:
|
||||
|
||||
/* Pickup current interrupt lockout posture. */
|
||||
|
||||
MRS r3, CPSR # Pickup current CPSR
|
||||
BIC r1, r3, INT_MASK # Clear interrupt lockout bits
|
||||
ORR r1, r1, r0 # Or-in new interrupt lockout bits
|
||||
|
||||
/* Apply the new interrupt posture. */
|
||||
|
||||
MSR CPSR_c, r1 # Setup new CPSR
|
||||
AND r0, r3, INT_MASK # Return previous interrupt mask
|
||||
RET # Return to caller
|
||||
|
||||
.type _tx_thread_interrupt_control,$function
|
||||
.size _tx_thread_interrupt_control,.-_tx_thread_interrupt_control
|
||||
/* } */
|
||||
|
||||
|
||||
|
||||
105
ports/cortex_a8/ghs/src/tx_thread_interrupt_disable.arm
Normal file
105
ports/cortex_a8/ghs/src/tx_thread_interrupt_disable.arm
Normal file
@@ -0,0 +1,105 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
DISABLE_INTS = 0xC0 # IRQ & FIQ interrupts disabled
|
||||
#else
|
||||
DISABLE_INTS = 0x80 # IRQ interrupts disabled
|
||||
#endif
|
||||
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_disable Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* UINT _tx_thread_interrupt_disable(void)
|
||||
{ */
|
||||
.globl _tx_thread_interrupt_disable
|
||||
_tx_thread_interrupt_disable:
|
||||
|
||||
/* Pickup current interrupt lockout posture. */
|
||||
|
||||
MRS r0, CPSR # Pickup current CPSR
|
||||
|
||||
/* Mask interrupts. */
|
||||
|
||||
#ifdef TX_BEFORE_ARMV6
|
||||
ORR r1, r0, DISABLE_INTS # Mask interrupts
|
||||
MSR CPSR_c, r1 # Setup new CPSR
|
||||
#else
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if # Disable IRQ and FIQ
|
||||
#else
|
||||
CPSID i # Disable IRQ
|
||||
#endif
|
||||
#endif
|
||||
|
||||
RET # Return previous CPSR value
|
||||
|
||||
.type _tx_thread_interrupt_disable,$function
|
||||
.size _tx_thread_interrupt_disable,.-_tx_thread_interrupt_disable
|
||||
/* } */
|
||||
|
||||
85
ports/cortex_a8/ghs/src/tx_thread_interrupt_restore.arm
Normal file
85
ports/cortex_a8/ghs/src/tx_thread_interrupt_restore.arm
Normal file
@@ -0,0 +1,85 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
/* #define TX_SOURCE_CODE */
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
/* #include "tx_api.h"
|
||||
#include "tx_thread.h" */
|
||||
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_restore Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for restoring interrupts to the state */
|
||||
/* returned by a previous _tx_thread_interrupt_disable call. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* new_posture New interrupt lockout posture */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_interrupt_restore(UINT new_posture)
|
||||
{ */
|
||||
.globl _tx_thread_interrupt_restore
|
||||
_tx_thread_interrupt_restore:
|
||||
|
||||
/* Apply the new interrupt posture. */
|
||||
|
||||
MSR CPSR_c, r0 # Setup new CPSR
|
||||
RET
|
||||
|
||||
.type _tx_thread_interrupt_restore,$function
|
||||
.size _tx_thread_interrupt_restore,.-_tx_thread_interrupt_restore
|
||||
/* } */
|
||||
|
||||
109
ports/cortex_a8/ghs/src/tx_thread_irq_nesting_end.arm
Normal file
109
ports/cortex_a8/ghs/src/tx_thread_irq_nesting_end.arm
Normal file
@@ -0,0 +1,109 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
DISABLE_INTS = 0xC0 # Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
DISABLE_INTS = 0x80 # Disable IRQ interrupts
|
||||
#endif
|
||||
MODE_MASK = 0x1F # Mode mask
|
||||
IRQ_MODE_BITS = 0x12 # IRQ mode bits
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_irq_nesting_end Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is called by the application from IRQ mode after */
|
||||
/* _tx_thread_irq_nesting_start has been called and switches the IRQ */
|
||||
/* processing from system mode back to IRQ mode prior to the ISR */
|
||||
/* calling _tx_thread_context_restore. Note that this function */
|
||||
/* assumes the system stack pointer is in the same position after */
|
||||
/* nesting start function was called. */
|
||||
/* */
|
||||
/* This function assumes that the system mode stack pointer was setup */
|
||||
/* during low-level initialization (tx_initialize_low_level.arm). */
|
||||
/* */
|
||||
/* This function returns with IRQ interrupts disabled. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_irq_nesting_end(VOID)
|
||||
{ */
|
||||
.globl _tx_thread_irq_nesting_end
|
||||
_tx_thread_irq_nesting_end:
|
||||
MOV r3,lr # Save ISR return address
|
||||
MRS r0, CPSR # Pickup the CPSR
|
||||
ORR r0, r0, DISABLE_INTS # Build disable interrupt value
|
||||
MSR CPSR_c, r0 # Disable interrupts
|
||||
LDR lr, [sp] # Pickup saved lr
|
||||
ADD sp, sp, 4 # Adjust stack pointer
|
||||
BIC r0, r0, MODE_MASK # Clear mode bits
|
||||
ORR r0, r0, IRQ_MODE_BITS # Build IRQ mode CPSR
|
||||
MSR CPSR_c, r0 # Re-enter IRQ mode
|
||||
MOV pc, r3 # Return to ISR
|
||||
|
||||
.type _tx_thread_irq_nesting_end,$function
|
||||
.size _tx_thread_irq_nesting_end,.-_tx_thread_irq_nesting_end
|
||||
|
||||
/* } */
|
||||
|
||||
102
ports/cortex_a8/ghs/src/tx_thread_irq_nesting_start.arm
Normal file
102
ports/cortex_a8/ghs/src/tx_thread_irq_nesting_start.arm
Normal file
@@ -0,0 +1,102 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
|
||||
IRQ_DISABLE = 0x80 # IRQ disable bit
|
||||
MODE_MASK = 0x1F # Mode mask
|
||||
SYS_MODE_BITS = 0x1F # System mode bits
|
||||
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_irq_nesting_start Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is called by the application from IRQ mode after */
|
||||
/* _tx_thread_context_save has been called and switches the IRQ */
|
||||
/* processing to the system mode so nested IRQ interrupt processing */
|
||||
/* is possible (system mode has its own "lr" register). Note that */
|
||||
/* this function assumes that the system mode stack pointer was setup */
|
||||
/* during low-level initialization (tx_initialize_low_level.arm). */
|
||||
/* */
|
||||
/* This function returns with IRQ interrupts enabled. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ISRs */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_irq_nesting_start(VOID)
|
||||
{ */
|
||||
.globl _tx_thread_irq_nesting_start
|
||||
_tx_thread_irq_nesting_start:
|
||||
MOV r3,lr # Save ISR return address
|
||||
MRS r0, CPSR # Pickup the CPSR
|
||||
BIC r0, r0, MODE_MASK # Clear the mode bits
|
||||
ORR r0, r0, SYS_MODE_BITS # Build system mode CPSR
|
||||
MSR CPSR_c, r0 # Enter system mode
|
||||
STR lr, [sp, -4]! # Push the system mode lr on the system mode stack
|
||||
BIC r0, r0, IRQ_DISABLE # Build enable IRQ CPSR
|
||||
MSR CPSR_c, r0 # Enter system mode
|
||||
MOV pc, r3 # Return to ISR
|
||||
|
||||
.type _tx_thread_irq_nesting_start,$function
|
||||
.size _tx_thread_irq_nesting_start,.-_tx_thread_irq_nesting_start
|
||||
/* } */
|
||||
|
||||
251
ports/cortex_a8/ghs/src/tx_thread_schedule.arm
Normal file
251
ports/cortex_a8/ghs/src/tx_thread_schedule.arm
Normal file
@@ -0,0 +1,251 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
ENABLE_INTS = 0xC0 # IRQ & FIQ Interrupts enabled mask
|
||||
#else
|
||||
ENABLE_INTS = 0x80 # IRQ Interrupts enabled mask
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function waits for a thread control block pointer to appear in */
|
||||
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
|
||||
/* in the variable, the corresponding thread is resumed. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* _tx_thread_system_return Return to system from thread */
|
||||
/* _tx_thread_context_restore Restore thread's context */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_schedule(VOID)
|
||||
{ */
|
||||
.globl _tx_thread_schedule
|
||||
_tx_thread_schedule:
|
||||
|
||||
/* Enable interrupts. */
|
||||
|
||||
#ifdef TX_BEFORE_ARMV6
|
||||
MRS r2, CPSR # Pickup CPSR
|
||||
BIC r0, r2, ENABLE_INTS # Clear the disable bit(s)
|
||||
MSR CPSR_c, r0 # Enable interrupts
|
||||
#else
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSIE if # Enable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSIE i # Enable IRQ interrupts
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Wait for a thread to execute. */
|
||||
/* do
|
||||
{ */
|
||||
LDR r1, =_tx_thread_execute_ptr # Address of thread execute ptr
|
||||
|
||||
__tx_thread_schedule_loop:
|
||||
|
||||
LDR r0, [r1] # Pickup next thread to execute
|
||||
CMP r0, 0 # Is it NULL?
|
||||
BEQ __tx_thread_schedule_loop # If so, keep looking for a thread
|
||||
|
||||
/* }
|
||||
while(_tx_thread_execute_ptr == TX_NULL); */
|
||||
|
||||
/* Yes! We have a thread to execute. Lockout interrupts and
|
||||
transfer control to it. */
|
||||
|
||||
#ifdef TX_BEFORE_ARMV6
|
||||
MSR CPSR_c, r2 # Disable interrupts
|
||||
#else
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if # Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSID i # Disable IRQ interrupts
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Setup the current thread pointer. */
|
||||
/* _tx_thread_current_ptr = _tx_thread_execute_ptr; */
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_LOGGING
|
||||
MOV v1, r0 # Save temp register in non-volatile register
|
||||
BL _tx_el_thread_running # Call event logging routine
|
||||
MOV r0, v1 # Restore temp register
|
||||
#endif
|
||||
|
||||
LDR r1, =_tx_thread_current_ptr # Pickup address of current thread
|
||||
STR r0, [r1] # Setup current thread pointer
|
||||
|
||||
/* Increment the run count for this thread. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_run_count++; */
|
||||
|
||||
LDR r2, [r0, 4] # Pickup run counter
|
||||
LDR r3, [r0, 24] # Pickup time-slice for this thread
|
||||
ADD r2, r2, 1 # Increment thread run-counter
|
||||
STR r2, [r0, 4] # Store the new run counter
|
||||
|
||||
/* Setup time-slice, if present. */
|
||||
/* _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; */
|
||||
|
||||
LDR r2, =_tx_timer_time_slice # Pickup address of time slice
|
||||
/* # variable */
|
||||
LDR sp, [r0, 8] # Switch stack pointers
|
||||
STR r3, [r2] # Setup time-slice
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the thread entry function to indicate the thread is executing. */
|
||||
MOV r5, r0 # Save r0
|
||||
BL _tx_execution_thread_enter # Call the thread execution enter function
|
||||
MOV r0, r5 # Restore r0
|
||||
#endif
|
||||
|
||||
/* Switch to the thread's stack. */
|
||||
/* sp = _tx_thread_execute_ptr -> tx_thread_stack_ptr; */
|
||||
|
||||
/* Determine if an interrupt frame or a synchronous task suspension frame
|
||||
is present. */
|
||||
|
||||
LDMIA sp!, {r4, r5} # Pickup the stack type and saved CPSR
|
||||
CMP r4, 0 # Check for synchronous context switch
|
||||
BEQ _tx_solicited_return
|
||||
MSR SPSR_cxsf, r5 # Setup SPSR for return
|
||||
#ifdef __VFP__
|
||||
LDR r1, [r0, 144] # Pickup the VFP enabled flag
|
||||
CMP r1, 0 # Is the VFP enabled?
|
||||
BEQ _tx_skip_interrupt_vfp_restore # No, skip VFP interrupt restore
|
||||
VLDMIA sp!, {D0-D15} # Recover D0-D15
|
||||
VLDMIA sp!, {D16-D31} # Recover D16-D31
|
||||
LDR r4, [sp], 4 # Pickup FPSCR
|
||||
VMSR FPSCR, r4 # Restore FPSCR
|
||||
_tx_skip_interrupt_vfp_restore:
|
||||
#endif
|
||||
LDMIA sp!, {r0-r12, lr, pc}^ # Return to point of thread interrupt
|
||||
|
||||
_tx_solicited_return:
|
||||
#ifdef __VFP__
|
||||
LDR r1, [r0, 144] # Pickup the VFP enabled flag
|
||||
CMP r1, 0 # Is the VFP enabled?
|
||||
BEQ _tx_skip_solicited_vfp_restore # No, skip VFP solicited restore
|
||||
VLDMIA sp!, {D8-D15} # Recover D8-D15
|
||||
VLDMIA sp!, {D16-D31} # Recover D16-D31
|
||||
LDR r4, [sp], 4 # Pickup FPSCR
|
||||
VMSR FPSCR, r4 # Restore FPSCR
|
||||
_tx_skip_solicited_vfp_restore:
|
||||
#endif
|
||||
MSR CPSR_cxsf, r5 # Recover CPSR
|
||||
LDMIA sp!, {r4-r11, lr} # Return to thread synchronously
|
||||
RET # Return to caller (Thumb safe)
|
||||
|
||||
.type _tx_thread_schedule,$function
|
||||
.size _tx_thread_schedule,.-_tx_thread_schedule
|
||||
|
||||
#ifdef __VFP__
|
||||
.globl tx_thread_vfp_enable
|
||||
tx_thread_vfp_enable:
|
||||
MRS r2, CPSR # Pickup the CPSR
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSIE if # Enable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSIE i # Enable IRQ interrupts
|
||||
#endif
|
||||
LDR r0, =_tx_thread_current_ptr # Build current thread pointer address
|
||||
LDR r1, [r0] # Pickup current thread pointer
|
||||
CMP r1, 0 # Check for NULL thread pointer
|
||||
BEQ __tx_no_thread_to_enable # If NULL, skip VFP enable
|
||||
MOV r0, 1 # Build enable value
|
||||
STR r0, [r1, 144] # Set the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD)
|
||||
__tx_no_thread_to_enable:
|
||||
MSR CPSR_cxsf, r2 # Recover CPSR
|
||||
RET # Return to caller (Thumb safe)
|
||||
|
||||
.type tx_thread_vfp_enable,$function
|
||||
.size tx_thread_vfp_enable,.-tx_thread_vfp_enable
|
||||
|
||||
|
||||
.globl tx_thread_vfp_disable
|
||||
tx_thread_vfp_disable:
|
||||
MRS r2, CPSR # Pickup the CPSR
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSIE if # Enable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSIE i # Enable IRQ interrupts
|
||||
#endif
|
||||
LDR r0, =_tx_thread_current_ptr # Build current thread pointer address
|
||||
LDR r1, [r0] # Pickup current thread pointer
|
||||
CMP r1, 0 # Check for NULL thread pointer
|
||||
BEQ __tx_no_thread_to_disable # If NULL, skip VFP disable
|
||||
MOV r0, 0 # Build disable value
|
||||
STR r0, [r1, 144] # Clear the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD)
|
||||
__tx_no_thread_to_disable:
|
||||
MSR CPSR_cxsf, r2 # Recover CPSR
|
||||
RET # Return to caller (Thumb safe)
|
||||
|
||||
.type tx_thread_vfp_disable,$function
|
||||
.size tx_thread_vfp_disable,.-tx_thread_vfp_disable
|
||||
|
||||
#endif
|
||||
|
||||
/* } */
|
||||
|
||||
161
ports/cortex_a8/ghs/src/tx_thread_stack_build.arm
Normal file
161
ports/cortex_a8/ghs/src/tx_thread_stack_build.arm
Normal file
@@ -0,0 +1,161 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
SVC_MODE = 0x13 # SVC mode
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSR_MASK = 0xDF # Mask initial CPSR, IRQ & FIQ ints enabled
|
||||
#else
|
||||
CPSR_MASK = 0x9F # Mask initial CPSR, IRQ ints enabled
|
||||
#endif
|
||||
|
||||
THUMB_BIT = 0x20 # Thumb-bit
|
||||
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_stack_build Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function builds a stack frame on the supplied thread's stack. */
|
||||
/* The stack frame results in a fake interrupt return to the supplied */
|
||||
/* function pointer. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* thread_ptr Pointer to thread control blk */
|
||||
/* function_ptr Pointer to return function */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_create Create thread service */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
|
||||
{ */
|
||||
.globl _tx_thread_stack_build
|
||||
_tx_thread_stack_build:
|
||||
|
||||
|
||||
/* Build a fake interrupt frame. The form of the fake interrupt stack
|
||||
on the Cortex-A8 should look like the following after it is built:
|
||||
|
||||
Stack Top: 1 Interrupt stack frame type
|
||||
CPSR Initial value for CPSR
|
||||
r0 (a1) Initial value for r0
|
||||
r1 (a2) Initial value for r1
|
||||
r2 (a3) Initial value for r2
|
||||
r3 (a4) Initial value for r3
|
||||
r4 (v1) Initial value for r4
|
||||
r5 (v2) Initial value for r5
|
||||
r6 (v3) Initial value for r6
|
||||
r7 (v4) Initial value for r7
|
||||
r8 (v5) Initial value for r8
|
||||
r9 (sb) Initial value for r9
|
||||
r10 (sl) Initial value for r10
|
||||
r11 (fp) Initial value for r11
|
||||
r12 (ip) Initial value for r12
|
||||
lr Initial value for lr
|
||||
pc Initial value for pc
|
||||
0 For stack backtracing
|
||||
|
||||
Stack Bottom: (higher memory address) */
|
||||
|
||||
LDR r2, [r0, 16] # Pickup end of stack area
|
||||
BIC r2, r2, 7 # Ensure 8-byte alignment
|
||||
SUB r2, r2, 76 # Allocate space for the stack frame
|
||||
|
||||
/* Actually build the stack frame. */
|
||||
|
||||
MOV r3, 1 # Build interrupt stack type
|
||||
STR r3, [r2] # Store stack type
|
||||
MOV r3, 0 # Build initial register value
|
||||
STR r3, [r2, 8] # Store initial r0
|
||||
STR r3, [r2, 12] # Store initial r1
|
||||
STR r3, [r2, 16] # Store initial r2
|
||||
STR r3, [r2, 20] # Store initial r3
|
||||
STR r3, [r2, 24] # Store initial r4
|
||||
STR r3, [r2, 28] # Store initial r5
|
||||
STR r3, [r2, 32] # Store initial r6
|
||||
STR r3, [r2, 36] # Store initial r7
|
||||
STR r3, [r2, 40] # Store initial r8
|
||||
STR r3, [r2, 44] # Store initial r9
|
||||
LDR r3, [r0, 12] # Pickup stack starting address
|
||||
STR r3, [r2, 48] # Store initial r10
|
||||
MOV r3, 0 # Build initial register value
|
||||
STR r3, [r2, 52] # Store initial r11
|
||||
STR r3, [r2, 56] # Store initial r12
|
||||
STR r3, [r2, 60] # Store initial lr
|
||||
STR r1, [r2, 64] # Store initial pc
|
||||
STR r3, [r2, 68] # 0 for back-trace
|
||||
|
||||
MRS r3, CPSR # Pickup CPSR
|
||||
BIC r3, r3, CPSR_MASK # Mask mode bits of CPSR
|
||||
ORR r3, r3, SVC_MODE # Build CPSR, SVC mode, interrupts enabled
|
||||
BIC r3, r3, #THUMB_BIT # Clear Thumb-bit by default
|
||||
AND r1, r1, #1 # Determine if the entry function is in Thumb mode
|
||||
CMP r1, 1 # Is the Thumb-bit set?
|
||||
ORREQ r3, r3, #THUMB_BIT # Yes, set the Thumb-bit
|
||||
STR r3, [r2, 4] # Store initial CPSR
|
||||
|
||||
/* Setup stack pointer. */
|
||||
/* thread_ptr -> tx_thread_stack_ptr = r2; */
|
||||
|
||||
STR r2, [r0, 8] # Save stack pointer in thread's
|
||||
/* # control block */
|
||||
RET # Return to caller
|
||||
|
||||
.type _tx_thread_stack_build,$function
|
||||
.size _tx_thread_stack_build,.-_tx_thread_stack_build
|
||||
/* } */
|
||||
|
||||
167
ports/cortex_a8/ghs/src/tx_thread_system_return.arm
Normal file
167
ports/cortex_a8/ghs/src/tx_thread_system_return.arm
Normal file
@@ -0,0 +1,167 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
DISABLE_INTS = 0xC0 # IRQ & FIQ interrupts disabled
|
||||
#else
|
||||
DISABLE_INTS = 0x80 # IRQ interrupts disabled
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_system_return Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is target processor specific. It is used to transfer */
|
||||
/* control from a thread back to the ThreadX system. Only a */
|
||||
/* minimal context is saved since the compiler assumes temp registers */
|
||||
/* are going to get slicked by a function call anyway. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_schedule Thread scheduling loop */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ThreadX components */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_system_return(VOID)
|
||||
{ */
|
||||
.globl _tx_thread_system_return
|
||||
_tx_thread_system_return:
|
||||
|
||||
/* Save minimal context on the stack. */
|
||||
|
||||
MOV r0, 0 # Build a solicited stack type
|
||||
MRS r1, CPSR # Pickup the CPSR
|
||||
STMDB sp!, {r4-r11, lr} # Save minimal context
|
||||
|
||||
LDR r4, =_tx_thread_current_ptr # Pickup address of current ptr
|
||||
LDR r5, [r4] # Pickup current thread pointer
|
||||
|
||||
#ifdef __VFP__
|
||||
LDR r1, [r5, 144] # Pickup the VFP enabled flag
|
||||
CMP r1, 0 # Is the VFP enabled?
|
||||
BEQ _tx_skip_solicited_vfp_save # No, skip VFP solicited save
|
||||
VMRS r1, FPSCR # Pickup the FPSCR
|
||||
STR r1, [sp, -4]! # Save FPSCR
|
||||
VSTMDB sp!, {D16-D31} # Save D16-D31
|
||||
VSTMDB sp!, {D8-D15} # Save D8-D15
|
||||
_tx_skip_solicited_vfp_save:
|
||||
#endif
|
||||
|
||||
MOV r0, #0 # Build a solicited stack type
|
||||
MRS r1, CPSR # Pickup the CPSR
|
||||
STMDB sp!, {r0-r1} # Save type and CPSR
|
||||
|
||||
/* Lockout interrupts. */
|
||||
|
||||
#ifdef TX_BEFORE_ARMV6
|
||||
ORR r2, r1, DISABLE_INTS # Build disable interrupt CPSR
|
||||
MSR CPSR_c, r2 # Disable interrupts
|
||||
#else
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
CPSID if # Disable IRQ and FIQ interrupts
|
||||
#else
|
||||
CPSID i # Disable IRQ interrutps
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the thread exit function to indicate the thread is no longer executing. */
|
||||
|
||||
BL _tx_execution_thread_exit # Call the thread exit function
|
||||
#endif
|
||||
|
||||
MOV r3, r4 # Pickup address of current ptr
|
||||
MOV r0, r5 # Pickup current thread pointer
|
||||
LDR r2, =_tx_timer_time_slice # Pickup address of time slice
|
||||
LDR r1, [r2] # Pickup current time slice
|
||||
|
||||
/* Save current stack and switch to system stack. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp;
|
||||
sp = _tx_thread_system_stack_ptr; */
|
||||
|
||||
STR sp, [r0, 8] # Save thread stack pointer
|
||||
|
||||
/* Determine if the time-slice is active. */
|
||||
/* if (_tx_timer_time_slice)
|
||||
{ */
|
||||
|
||||
MOV r4, 0 # Build clear value
|
||||
CMP r1, 0 # Is a time-slice active?
|
||||
BEQ __tx_thread_dont_save_ts # No, don't save the current time-slice
|
||||
|
||||
/* Save time-slice for the thread and clear the current time-slice. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
_tx_timer_time_slice = 0; */
|
||||
|
||||
STR r4, [r2, 0] # Clear time-slice
|
||||
STR r1, [r0, 24] # Save current time-slice
|
||||
|
||||
/* } */
|
||||
__tx_thread_dont_save_ts:
|
||||
|
||||
/* Clear the current thread pointer. */
|
||||
/* _tx_thread_current_ptr = TX_NULL; */
|
||||
|
||||
STR r4, [r3] # Clear current thread pointer
|
||||
B _tx_thread_schedule # Jump to scheduler!
|
||||
|
||||
.type _tx_thread_system_return,$function
|
||||
.size _tx_thread_system_return,.-_tx_thread_system_return
|
||||
/* } */
|
||||
|
||||
196
ports/cortex_a8/ghs/src/tx_thread_vectored_context_save.arm
Normal file
196
ports/cortex_a8/ghs/src/tx_thread_vectored_context_save.arm
Normal file
@@ -0,0 +1,196 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
DISABLE_INTS = 0xC0 # IRQ & FIQ interrupts disabled
|
||||
#else
|
||||
DISABLE_INTS = 0x80 # IRQ interrupts disabled
|
||||
#endif
|
||||
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_vectored_context_save Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_thread_vectored_context_save(VOID)
|
||||
{ */
|
||||
.globl _tx_thread_vectored_context_save
|
||||
_tx_thread_vectored_context_save:
|
||||
|
||||
/* Upon entry to this routine, it is assumed that IRQ interrupts are locked
|
||||
out, we are in IRQ mode, the minimal context is already saved, and the
|
||||
lr register contains the return ISR address. */
|
||||
|
||||
/* Check for a nested interrupt condition. */
|
||||
/* if (_tx_thread_system_state++)
|
||||
{ */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
#ifdef TX_BEFORE_ARMV6
|
||||
MRS r0, CPSR # Pickup the CPSR
|
||||
ORR r0, r0, DISABLE_INTS # Build disable interrupt CPSR
|
||||
MSR CPSR_c, r0 # Disable interrupts
|
||||
#else
|
||||
CPSID if # Disable IRQ and FIQ interrupts
|
||||
#endif
|
||||
#endif
|
||||
LDR r3, =_tx_thread_system_state # Pickup address of system state var
|
||||
LDR r2, [r3] # Pickup system state
|
||||
CMP r2, 0 # Is this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_save # Yes, not a nested context save
|
||||
|
||||
/* Nested interrupt condition. */
|
||||
|
||||
ADD r2, r2, 1 # Increment the interrupt counter
|
||||
STR r2, [r3] # Store it back in the variable
|
||||
|
||||
/* Note: Minimal context of interrupted thread is already saved. */
|
||||
|
||||
/* Return to the ISR. */
|
||||
|
||||
MOV r10, 0 # Clear stack limit
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} # Save ISR lr
|
||||
BL _tx_execution_isr_enter # Call the ISR enter function
|
||||
POP {lr} # Recover ISR lr
|
||||
#endif
|
||||
|
||||
MOV pc, lr # Return to caller
|
||||
|
||||
__tx_thread_not_nested_save:
|
||||
/* } */
|
||||
|
||||
/* Otherwise, not nested, check to see if a thread was running. */
|
||||
/* else if (_tx_thread_current_ptr)
|
||||
{ */
|
||||
|
||||
ADD r2, r2, 1 # Increment the interrupt counter
|
||||
STR r2, [r3] # Store it back in the variable
|
||||
LDR r1, =_tx_thread_current_ptr # Pickup address of current thread ptr
|
||||
LDR r0, [r1] # Pickup current thread pointer
|
||||
CMP r0, 0 # Is it NULL?
|
||||
BEQ __tx_thread_idle_system_save # If so, interrupt occurred in
|
||||
/* # scheduling loop - nothing needs saving! */
|
||||
|
||||
/* Note: Minimal context of interrupted thread is already saved. */
|
||||
|
||||
/* Save the current stack pointer in the thread's control block. */
|
||||
/* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */
|
||||
|
||||
/* Switch to the system stack. */
|
||||
/* sp = _tx_thread_system_stack_ptr; */
|
||||
|
||||
MOV r10, 0 # Clear stack limit
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} # Save ISR lr
|
||||
BL _tx_execution_isr_enter # Call the ISR enter function
|
||||
POP {lr} # Recover ISR lr
|
||||
#endif
|
||||
|
||||
MOV pc, lr # Return to caller
|
||||
|
||||
/* }
|
||||
else
|
||||
{ */
|
||||
|
||||
__tx_thread_idle_system_save:
|
||||
|
||||
/* Interrupt occurred in the scheduling loop. */
|
||||
|
||||
/* Not much to do here, just adjust the stack pointer, and return to IRQ
|
||||
processing. */
|
||||
|
||||
MOV r10, 0 # Clear stack limit
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
PUSH {lr} # Save ISR lr
|
||||
BL _tx_execution_isr_enter # Call the ISR enter function
|
||||
POP {lr} # Recover ISR lr
|
||||
#endif
|
||||
|
||||
ADD sp, sp, 32 # Recover saved registers
|
||||
MOV pc, lr # Return to caller
|
||||
|
||||
.type _tx_thread_vectored_context_save,$function
|
||||
.size _tx_thread_vectored_context_save,.-_tx_thread_vectored_context_save
|
||||
|
||||
/* }
|
||||
} */
|
||||
|
||||
241
ports/cortex_a8/ghs/src/tx_timer_interrupt.arm
Normal file
241
ports/cortex_a8/ghs/src/tx_timer_interrupt.arm
Normal file
@@ -0,0 +1,241 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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" */
|
||||
|
||||
|
||||
.text
|
||||
.align 4
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_timer_interrupt Cortex-A8/Green Hills */
|
||||
/* 6.1 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes the hardware timer interrupt. This */
|
||||
/* processing includes incrementing the system clock and checking for */
|
||||
/* time slice and/or timer expiration. If either is found, the */
|
||||
/* interrupt context save/restore functions are called along with the */
|
||||
/* expiration functions. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_timer_expiration_process Process timer expiration */
|
||||
/* _tx_thread_time_slice Time slice interrupted thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* interrupt vector */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
/* VOID _tx_timer_interrupt(VOID)
|
||||
{ */
|
||||
.globl _tx_timer_interrupt
|
||||
_tx_timer_interrupt:
|
||||
|
||||
/* Upon entry to this routine, it is assumed that context save has already
|
||||
been called, and therefore the compiler scratch registers are available
|
||||
for use. */
|
||||
|
||||
/* Increment the system clock. */
|
||||
/* _tx_timer_system_clock++; */
|
||||
|
||||
LDR r1, =_tx_timer_system_clock # Pickup address of system clock
|
||||
LDR r0, [r1] # Pickup system clock
|
||||
ADD r0, r0, 1 # Increment system clock
|
||||
STR r0, [r1] # 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] # 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] # 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] # 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 addr
|
||||
LDR r0, [r1] # Pickup current timer
|
||||
LDR r2, [r0] # 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] # 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] # 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] # Set current pointer to list start
|
||||
|
||||
__tx_timer_skip_wrap:
|
||||
|
||||
STR r0, [r1] # 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] # 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] # 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] # Pickup timer expired flag
|
||||
CMP r0, 0 # Check for timer expiration
|
||||
BEQ __tx_timer_dont_activate # If not set, skip timer activation
|
||||
|
||||
/* Process the 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] # 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
|
||||
|
||||
/* } */
|
||||
__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:
|
||||
|
||||
RET # Return to caller
|
||||
|
||||
.type _tx_timer_interrupt,$function
|
||||
.size _tx_timer_interrupt,.-_tx_timer_interrupt
|
||||
/* } */
|
||||
|
||||
84
ports/cortex_a8/ghs/src/txr_ghs.c
Normal file
84
ports/cortex_a8/ghs/src/txr_ghs.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* ThreadX API Runtime Error Support
|
||||
*
|
||||
* Copyright 1983-2019 Green Hills Software LLC.
|
||||
*
|
||||
* This program is the property of Green Hills Software LLC.,
|
||||
* its contents are proprietary information and no part of it
|
||||
* is to be disclosed to anyone except employees of Green Hills
|
||||
* Software LLC., or as agreed in writing signed by the President
|
||||
* of Green Hills Software LLC.
|
||||
*/
|
||||
|
||||
/* #include "tx_ghs.h" */
|
||||
#ifndef TX_DISABLE_ERROR_CHECKING
|
||||
#define TX_DISABLE_ERROR_CHECKING
|
||||
#endif
|
||||
#include "tx_api.h"
|
||||
|
||||
/* Customized ThreadX API runtime error support routine. */
|
||||
|
||||
void _rnerr(int num, int linenum, const char*str, void*ptr, ...);
|
||||
|
||||
/* __ghs_rnerr()
|
||||
This is the custom runtime error checking routine.
|
||||
This implementation uses the existing __rnerr() routine.
|
||||
Another implementation could use the .syscall mechanism,
|
||||
provided MULTI was modified to understand that.
|
||||
*/
|
||||
void __ghs_rnerr(char *errMsg, int stackLevels, int stackTraceDisplay, void *hexVal) {
|
||||
TX_INTERRUPT_SAVE_AREA
|
||||
int num;
|
||||
/*
|
||||
Initialize the stack levels value.
|
||||
|
||||
Add 3 to account for the calls to _rnerr, __rnerr, and
|
||||
__ghs_rnerr.
|
||||
|
||||
If the implementation changes, calls to __ghs_rnerr
|
||||
will not need to be changed.
|
||||
|
||||
Zero is not permitted, so substitute 3 in that case.
|
||||
*/
|
||||
num = (stackLevels+3) & 0xf;
|
||||
if (!num) {
|
||||
num = 3;
|
||||
}
|
||||
/*
|
||||
Shift the stack levels value to bits 12..15 and
|
||||
insert the stack trace display value in bit 11.
|
||||
Bits 0..10 are unused.
|
||||
*/
|
||||
num = (num << 12) | (stackTraceDisplay ? 0x800 : 0);
|
||||
|
||||
/* This will mask all interrupts in the RTEC code, which is probably
|
||||
unacceptable for many targets. */
|
||||
TX_DISABLE
|
||||
_rnerr(num, -1, (const char *)hexVal, (void *)errMsg);
|
||||
TX_RESTORE
|
||||
}
|
||||
|
||||
|
||||
/* ThreadX thread stack checking runtime support routine. */
|
||||
|
||||
extern char __ghsbegin_stack[];
|
||||
extern TX_THREAD *_tx_thread_current_ptr;
|
||||
|
||||
void __stkchk(void) {
|
||||
int i;
|
||||
if(_tx_thread_current_ptr)
|
||||
{
|
||||
if((unsigned)(&i) <=
|
||||
(unsigned)(_tx_thread_current_ptr -> tx_thread_stack_start))
|
||||
{
|
||||
_rnerr(21, -1, 0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((unsigned)(&i) <= (unsigned)__ghsbegin_stack)
|
||||
{
|
||||
_rnerr(21, -1, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user