Release ARMv7-A architecture ports and add tx_user.h to GNU port assembly files (#250)
* Release ARMv7-A architecture ports * Add tx_user.h to GNU port assembly files * Update GitHub action to perform check for Cortex-A ports
This commit is contained in:
4
ports_arch/ARMv8-A/README.md
Normal file
4
ports_arch/ARMv8-A/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# ARMv8-A architecture ports
|
||||
|
||||
The ThreadX, ThreadX SMP, ThreadX Modules and ThreadX SMP Modules ports for ARMv8 share many files in common. To make work more efficient these files are internally tracked only once and copied over to specific ports for users.
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
/* This is a small demo of the high-performance ThreadX kernel. It includes examples of eight
|
||||
threads of different priorities, using a message queue, semaphore, mutex, event flags group,
|
||||
byte pool, and block pool. */
|
||||
|
||||
#include "tx_api.h"
|
||||
|
||||
|
||||
extern void init_timer(void); /* in timer_interrupts.c */
|
||||
|
||||
|
||||
#define DEMO_STACK_SIZE 1024
|
||||
#define DEMO_BYTE_POOL_SIZE 9120
|
||||
#define DEMO_BLOCK_POOL_SIZE 100
|
||||
#define DEMO_QUEUE_SIZE 100
|
||||
|
||||
|
||||
/* Define byte pool memory. */
|
||||
|
||||
UCHAR byte_pool_memory[DEMO_BYTE_POOL_SIZE];
|
||||
|
||||
|
||||
|
||||
|
||||
/* Define the ThreadX object control blocks... */
|
||||
|
||||
TX_THREAD thread_0;
|
||||
TX_THREAD thread_1;
|
||||
TX_THREAD thread_2;
|
||||
TX_THREAD thread_3;
|
||||
TX_THREAD thread_4;
|
||||
TX_THREAD thread_5;
|
||||
TX_THREAD thread_6;
|
||||
TX_THREAD thread_7;
|
||||
TX_TIMER timer_0;
|
||||
TX_QUEUE queue_0;
|
||||
TX_SEMAPHORE semaphore_0;
|
||||
TX_MUTEX mutex_0;
|
||||
TX_EVENT_FLAGS_GROUP event_flags_0;
|
||||
TX_BYTE_POOL byte_pool_0;
|
||||
TX_BLOCK_POOL block_pool_0;
|
||||
|
||||
|
||||
/* Define the counters used in the demo application... */
|
||||
|
||||
ULONG thread_0_counter;
|
||||
ULONG thread_1_counter;
|
||||
ULONG thread_1_messages_sent;
|
||||
ULONG thread_2_counter;
|
||||
ULONG thread_2_messages_received;
|
||||
ULONG thread_3_counter;
|
||||
ULONG thread_4_counter;
|
||||
ULONG thread_5_counter;
|
||||
ULONG thread_6_counter;
|
||||
ULONG thread_7_counter;
|
||||
|
||||
|
||||
/* Define thread prototypes. */
|
||||
|
||||
void thread_0_entry(ULONG thread_input);
|
||||
void thread_1_entry(ULONG thread_input);
|
||||
void thread_2_entry(ULONG thread_input);
|
||||
void thread_3_and_4_entry(ULONG thread_input);
|
||||
void thread_5_entry(ULONG thread_input);
|
||||
void thread_6_and_7_entry(ULONG thread_input);
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
UCHAR event_buffer[65536];
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define main entry point. */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
||||
/* Initialize timer. */
|
||||
init_timer();
|
||||
|
||||
/* Enter ThreadX. */
|
||||
tx_kernel_enter();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Define what the initial system looks like. */
|
||||
|
||||
void tx_application_define(void *first_unused_memory)
|
||||
{
|
||||
|
||||
CHAR *pointer = TX_NULL;
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
tx_trace_enable(event_buffer, sizeof(event_buffer), 32);
|
||||
#endif
|
||||
|
||||
/* Create a byte memory pool from which to allocate the thread stacks. */
|
||||
tx_byte_pool_create(&byte_pool_0, "byte pool 0", byte_pool_memory, DEMO_BYTE_POOL_SIZE);
|
||||
|
||||
/* Allocate the stack for thread 0. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create the main thread. */
|
||||
tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 1. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create threads 1 and 2. These threads pass information through a ThreadX
|
||||
message queue. It is also interesting to note that these threads have a time
|
||||
slice. */
|
||||
tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
16, 16, 4, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 2. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
16, 16, 4, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 3. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create threads 3 and 4. These threads compete for a ThreadX counting semaphore.
|
||||
An interesting thing here is that both threads share the same instruction area. */
|
||||
tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 4. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 5. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create thread 5. This thread simply pends on an event flag which will be set
|
||||
by thread_0. */
|
||||
tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 6. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create threads 6 and 7. These threads compete for a ThreadX mutex. */
|
||||
tx_thread_create(&thread_6, "thread 6", thread_6_and_7_entry, 6,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 7. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
tx_thread_create(&thread_7, "thread 7", thread_6_and_7_entry, 7,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the message queue. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_QUEUE_SIZE*sizeof(ULONG), TX_NO_WAIT);
|
||||
|
||||
/* Create the message queue shared by threads 1 and 2. */
|
||||
tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG));
|
||||
|
||||
/* Create the semaphore used by threads 3 and 4. */
|
||||
tx_semaphore_create(&semaphore_0, "semaphore 0", 1);
|
||||
|
||||
/* Create the event flags group used by threads 1 and 5. */
|
||||
tx_event_flags_create(&event_flags_0, "event flags 0");
|
||||
|
||||
/* Create the mutex used by thread 6 and 7 without priority inheritance. */
|
||||
tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT);
|
||||
|
||||
/* Allocate the memory for a small block pool. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_BLOCK_POOL_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create a block memory pool to allocate a message buffer from. */
|
||||
tx_block_pool_create(&block_pool_0, "block pool 0", sizeof(ULONG), pointer, DEMO_BLOCK_POOL_SIZE);
|
||||
|
||||
/* Allocate a block and release the block memory. */
|
||||
tx_block_allocate(&block_pool_0, (VOID **) &pointer, TX_NO_WAIT);
|
||||
|
||||
/* Release the block back to the pool. */
|
||||
tx_block_release(pointer);
|
||||
}
|
||||
|
||||
|
||||
/* Define the test threads. */
|
||||
|
||||
void thread_0_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* This thread simply sits in while-forever-sleep loop. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
thread_0_counter++;
|
||||
|
||||
/* Sleep for 10 ticks. */
|
||||
tx_thread_sleep(10);
|
||||
|
||||
/* Set event flag 0 to wakeup thread 5. */
|
||||
status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_1_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* This thread simply sends messages to a queue shared by thread 2. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
thread_1_counter++;
|
||||
|
||||
/* Send message to queue 0. */
|
||||
status = tx_queue_send(&queue_0, &thread_1_messages_sent, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check completion status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Increment the message sent. */
|
||||
thread_1_messages_sent++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_2_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
ULONG received_message;
|
||||
UINT status;
|
||||
|
||||
/* This thread retrieves messages placed on the queue by thread 1. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
thread_2_counter++;
|
||||
|
||||
/* Retrieve a message from the queue. */
|
||||
status = tx_queue_receive(&queue_0, &received_message, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check completion status and make sure the message is what we
|
||||
expected. */
|
||||
if ((status != TX_SUCCESS) || (received_message != thread_2_messages_received))
|
||||
break;
|
||||
|
||||
/* Otherwise, all is okay. Increment the received message count. */
|
||||
thread_2_messages_received++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_3_and_4_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* This function is executed from thread 3 and thread 4. As the loop
|
||||
below shows, these function compete for ownership of semaphore_0. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
if (thread_input == 3)
|
||||
thread_3_counter++;
|
||||
else
|
||||
thread_4_counter++;
|
||||
|
||||
/* Get the semaphore with suspension. */
|
||||
status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Sleep for 2 ticks to hold the semaphore. */
|
||||
tx_thread_sleep(2);
|
||||
|
||||
/* Release the semaphore. */
|
||||
status = tx_semaphore_put(&semaphore_0);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_5_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
ULONG actual_flags;
|
||||
|
||||
|
||||
/* This thread simply waits for an event in a forever loop. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
thread_5_counter++;
|
||||
|
||||
/* Wait for event flag 0. */
|
||||
status = tx_event_flags_get(&event_flags_0, 0x1, TX_OR_CLEAR,
|
||||
&actual_flags, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check status. */
|
||||
if ((status != TX_SUCCESS) || (actual_flags != 0x1))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_6_and_7_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* This function is executed from thread 6 and thread 7. As the loop
|
||||
below shows, these function compete for ownership of mutex_0. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
if (thread_input == 6)
|
||||
thread_6_counter++;
|
||||
else
|
||||
thread_7_counter++;
|
||||
|
||||
/* Get the mutex with suspension. */
|
||||
status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Get the mutex again with suspension. This shows
|
||||
that an owning thread may retrieve the mutex it
|
||||
owns multiple times. */
|
||||
status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Sleep for 2 ticks to hold the mutex. */
|
||||
tx_thread_sleep(2);
|
||||
|
||||
/* Release the mutex. */
|
||||
status = tx_mutex_put(&mutex_0);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Release the mutex again. This will actually
|
||||
release ownership since it was obtained twice. */
|
||||
status = tx_mutex_put(&mutex_0);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
379
ports_arch/ARMv8-A/threadx/common/inc/tx_port.h
Normal file
379
ports_arch/ARMv8-A/threadx/common/inc/tx_port.h
Normal file
@@ -0,0 +1,379 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Port Specific */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h ARMv8-A */
|
||||
/* 6.1.10 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains data type definitions that make the ThreadX */
|
||||
/* real-time kernel function identically on a variety of different */
|
||||
/* processor architectures. For example, the size or number of bits */
|
||||
/* in an "int" data type vary between microprocessor architectures and */
|
||||
/* even C compilers for the same microprocessor. ThreadX does not */
|
||||
/* directly use native C data types. Instead, ThreadX creates its */
|
||||
/* own special types that can be mapped to actual data types by this */
|
||||
/* file to guarantee consistency in the interface and functionality. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Bhupendra Naphade Modified comment(s),updated */
|
||||
/* macro definition, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_PORT_H
|
||||
#define TX_PORT_H
|
||||
|
||||
|
||||
/* Determine if the optional ThreadX user define file should be used. */
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
|
||||
|
||||
/* Yes, include the user defines in tx_user.h. The defines in this file may
|
||||
alternately be defined on the command line. */
|
||||
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* Define compiler library include files. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Define ThreadX basic types for this port. */
|
||||
|
||||
#define VOID void
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef int LONG;
|
||||
typedef unsigned int ULONG;
|
||||
typedef unsigned long long ULONG64;
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
#define ULONG64_DEFINED
|
||||
|
||||
/* Override the alignment type to use 64-bit alignment and storage for pointers. */
|
||||
|
||||
#define ALIGN_TYPE_DEFINED
|
||||
typedef unsigned long long ALIGN_TYPE;
|
||||
|
||||
|
||||
/* Override the free block marker for byte pools to be a 64-bit constant. */
|
||||
|
||||
#define TX_BYTE_BLOCK_FREE ((ALIGN_TYPE) 0xFFFFEEEEFFFFEEEE)
|
||||
|
||||
|
||||
/* Define the priority levels for ThreadX. Legal values range
|
||||
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||
|
||||
#ifndef TX_MAX_PRIORITIES
|
||||
#define TX_MAX_PRIORITIES 32
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||
thread creation is less than this value, the thread create call will return an error. */
|
||||
|
||||
#ifndef TX_MINIMUM_STACK
|
||||
#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||
|
||||
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||
#define TX_TIMER_THREAD_STACK_SIZE 4096 /* Default timer thread stack size */
|
||||
#endif
|
||||
|
||||
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define various constants for the ThreadX ARM port. */
|
||||
|
||||
#define TX_INT_DISABLE 0xC0 /* Disable IRQ & FIQ interrupts */
|
||||
#define TX_INT_ENABLE 0x00 /* Enable IRQ & FIQ interrupts */
|
||||
|
||||
|
||||
/* Define the clock source for trace event entry time stamp. The following two item are port specific.
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE _tx_thread_smp_time_get()
|
||||
#endif
|
||||
#else
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
ULONG _tx_misra_time_stamp_get(VOID);
|
||||
#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the port specific options for the _tx_build_options variable. This variable indicates
|
||||
how the ThreadX library was built. */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
#define TX_FIQ_ENABLED 1
|
||||
#else
|
||||
#define TX_FIQ_ENABLED 0
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_IRQ_NESTING
|
||||
#define TX_IRQ_NESTING_ENABLED 2
|
||||
#else
|
||||
#define TX_IRQ_NESTING_ENABLED 0
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_NESTING
|
||||
#define TX_FIQ_NESTING_ENABLED 4
|
||||
#else
|
||||
#define TX_FIQ_NESTING_ENABLED 0
|
||||
#endif
|
||||
|
||||
#define TX_PORT_SPECIFIC_BUILD_OPTIONS (TX_FIQ_ENABLED | TX_IRQ_NESTING_ENABLED | TX_FIQ_NESTING_ENABLED)
|
||||
|
||||
|
||||
/* Define the in-line initialization constant so that modules with in-line
|
||||
initialization capabilities can prevent their initialization from being
|
||||
a function call. */
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
#define TX_DISABLE_INLINE
|
||||
#else
|
||||
#define TX_INLINE_INITIALIZATION
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
|
||||
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
|
||||
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
|
||||
define is negated, thereby forcing the stack fill which is necessary for the stack checking
|
||||
logic. */
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
#undef TX_DISABLE_STACK_FILLING
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the TX_THREAD control block extensions for this port. The main reason
|
||||
for the multiple macros is so that backward compatibility can be maintained with
|
||||
existing ThreadX kernel awareness modules. */
|
||||
|
||||
#define TX_THREAD_EXTENSION_0
|
||||
#define TX_THREAD_EXTENSION_1
|
||||
#define TX_THREAD_EXTENSION_2 ULONG tx_thread_fp_enable;
|
||||
#define TX_THREAD_EXTENSION_3
|
||||
|
||||
|
||||
/* Define the port extensions of the remaining ThreadX objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_EXTENSION
|
||||
#define TX_BYTE_POOL_EXTENSION
|
||||
#define TX_EVENT_FLAGS_GROUP_EXTENSION
|
||||
#define TX_MUTEX_EXTENSION
|
||||
#define TX_QUEUE_EXTENSION
|
||||
#define TX_SEMAPHORE_EXTENSION
|
||||
#define TX_TIMER_EXTENSION
|
||||
|
||||
|
||||
/* Define the user extension field of the thread control block. Nothing
|
||||
additional is needed for this port so it is defined as white space. */
|
||||
|
||||
#ifndef TX_THREAD_USER_EXTENSION
|
||||
#define TX_THREAD_USER_EXTENSION
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
|
||||
tx_thread_shell_entry, and tx_thread_terminate. */
|
||||
|
||||
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
|
||||
|
||||
|
||||
/* Define the ThreadX object creation extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Define the ThreadX object deletion extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Determine if the ARM architecture has the CLZ instruction. This is available on
|
||||
architectures v5 and above. If available, redefine the macro for calculating the
|
||||
lowest bit set. */
|
||||
|
||||
#ifndef TX_DISABLE_INLINE
|
||||
|
||||
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) b = (UINT) __builtin_ctz((unsigned int) m);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the internal timer extension to also hold the thread pointer such that _tx_thread_timeout
|
||||
can figure out what thread timeout to process. */
|
||||
|
||||
#define TX_TIMER_INTERNAL_EXTENSION VOID *tx_timer_internal_thread_timeout_ptr;
|
||||
|
||||
|
||||
/* Define the thread timeout setup logic in _tx_thread_create. */
|
||||
|
||||
#define TX_THREAD_CREATE_TIMEOUT_SETUP(t) (t) -> tx_thread_timer.tx_timer_internal_timeout_function = &(_tx_thread_timeout); \
|
||||
(t) -> tx_thread_timer.tx_timer_internal_timeout_param = 0; \
|
||||
(t) -> tx_thread_timer.tx_timer_internal_thread_timeout_ptr = (VOID *) (t);
|
||||
|
||||
|
||||
/* Define the thread timeout pointer setup in _tx_thread_timeout. */
|
||||
|
||||
#define TX_THREAD_TIMEOUT_POINTER_SETUP(t) (t) = (TX_THREAD *) _tx_timer_expired_timer_ptr -> tx_timer_internal_thread_timeout_ptr;
|
||||
|
||||
|
||||
/* Define ThreadX interrupt lockout and restore macros for protection on
|
||||
access of critical kernel information. The restore interrupt macro must
|
||||
restore the interrupt posture of the running thread prior to the value
|
||||
present prior to the disable macro. In most cases, the save area macro
|
||||
is used to define a local function save area for the disable and restore
|
||||
macros. */
|
||||
|
||||
#ifndef TX_DISABLE_INLINE
|
||||
|
||||
/* Define macros, with in-line assembly for performance. */
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void)
|
||||
{
|
||||
|
||||
unsigned long long daif_value;
|
||||
|
||||
__asm__ volatile (" MRS %0, DAIF ": "=r" (daif_value) );
|
||||
__asm__ volatile (" MSR DAIFSet, 0x3" : : : "memory" );
|
||||
return((unsigned int) daif_value);
|
||||
}
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline void __restore_interrupts(unsigned int daif_value)
|
||||
{
|
||||
|
||||
unsigned long long temp;
|
||||
|
||||
temp = (unsigned long long) daif_value;
|
||||
__asm__ volatile (" MSR DAIF,%0": : "r" (temp): "memory" );
|
||||
}
|
||||
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
|
||||
#define TX_DISABLE interrupt_save = __disable_interrupts();
|
||||
#define TX_RESTORE __restore_interrupts(interrupt_save);
|
||||
|
||||
#else
|
||||
|
||||
unsigned int _tx_thread_interrupt_disable(void);
|
||||
unsigned int _tx_thread_interrupt_restore(UINT old_posture);
|
||||
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable();
|
||||
#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save);
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the interrupt lockout macros for each ThreadX object. */
|
||||
|
||||
#define TX_BLOCK_POOL_DISABLE TX_DISABLE
|
||||
#define TX_BYTE_POOL_DISABLE TX_DISABLE
|
||||
#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
|
||||
#define TX_MUTEX_DISABLE TX_DISABLE
|
||||
#define TX_QUEUE_DISABLE TX_DISABLE
|
||||
#define TX_SEMAPHORE_DISABLE TX_DISABLE
|
||||
|
||||
|
||||
/* Define FP extension for ARMv8. Each is assumed to be called in the context of the executing thread. */
|
||||
|
||||
#ifndef TX_SOURCE_CODE
|
||||
#define tx_thread_fp_enable _tx_thread_fp_enable
|
||||
#define tx_thread_fp_disable _tx_thread_fp_disable
|
||||
#endif
|
||||
|
||||
VOID tx_thread_fp_enable(VOID);
|
||||
VOID tx_thread_fp_disable(VOID);
|
||||
|
||||
|
||||
/* Define the version ID of ThreadX. This may be utilized by the application. */
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX ARMv8-A Version 6.2.1 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,291 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_restore ARMv8-A */
|
||||
/* 6.x */
|
||||
/* 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 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_context_restore(VOID)
|
||||
// {
|
||||
.global _tx_thread_context_restore
|
||||
.type _tx_thread_context_restore, @function
|
||||
_tx_thread_context_restore:
|
||||
|
||||
/* Lockout interrupts. */
|
||||
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
|
||||
#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 x3, =_tx_thread_system_state // Pickup address of system state var
|
||||
LDR w2, [x3, #0] // Pickup system state
|
||||
SUB w2, w2, #1 // Decrement the counter
|
||||
STR w2, [x3, #0] // Store the counter
|
||||
CMP w2, #0 // Was this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_restore // If so, not a nested restore
|
||||
|
||||
/* Interrupts are nested. */
|
||||
|
||||
/* Just recover the saved registers and return to the point of
|
||||
interrupt. */
|
||||
|
||||
LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL
|
||||
#ifdef EL1
|
||||
MSR SPSR_EL1, x4 // Setup SPSR for return
|
||||
MSR ELR_EL1, x5 // Setup point of interrupt
|
||||
#else
|
||||
#ifdef EL2
|
||||
MSR SPSR_EL2, x4 // Setup SPSR for return
|
||||
MSR ELR_EL2, x5 // Setup point of interrupt
|
||||
#else
|
||||
MSR SPSR_EL3, x4 // Setup SPSR for return
|
||||
MSR ELR_EL3, x5 // Setup point of interrupt
|
||||
#endif
|
||||
#endif
|
||||
LDP x18, x19, [sp], #16 // Recover x18, x19
|
||||
LDP x16, x17, [sp], #16 // Recover x16, x17
|
||||
LDP x14, x15, [sp], #16 // Recover x14, x15
|
||||
LDP x12, x13, [sp], #16 // Recover x12, x13
|
||||
LDP x10, x11, [sp], #16 // Recover x10, x11
|
||||
LDP x8, x9, [sp], #16 // Recover x8, x9
|
||||
LDP x6, x7, [sp], #16 // Recover x6, x7
|
||||
LDP x4, x5, [sp], #16 // Recover x4, x5
|
||||
LDP x2, x3, [sp], #16 // Recover x2, x3
|
||||
LDP x0, x1, [sp], #16 // Recover x0, x1
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
ERET // 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 x1, =_tx_thread_current_ptr // Pickup address of current thread ptr
|
||||
LDR x0, [x1, #0] // Pickup actual current thread pointer
|
||||
CMP x0, #0 // Is it NULL?
|
||||
BEQ __tx_thread_idle_system_restore // Yes, idle system was interrupted
|
||||
|
||||
LDR x3, =_tx_thread_preempt_disable // Pickup preempt disable address
|
||||
LDR w2, [x3, #0] // Pickup actual preempt disable flag
|
||||
CMP w2, #0 // Is it set?
|
||||
BNE __tx_thread_no_preempt_restore // Yes, don't preempt this thread
|
||||
LDR x3, =_tx_thread_execute_ptr // Pickup address of execute thread ptr
|
||||
LDR x2, [x3, #0] // Pickup actual execute thread pointer
|
||||
CMP x0, x2 // 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. */
|
||||
// sp = _tx_thread_current_ptr -> tx_thread_stack_ptr;
|
||||
|
||||
LDR x4, [x0, #8] // Switch to thread stack pointer
|
||||
MOV sp, x4 //
|
||||
|
||||
/* Recover the saved context and return to the point of interrupt. */
|
||||
|
||||
LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL1
|
||||
#ifdef EL1
|
||||
MSR SPSR_EL1, x4 // Setup SPSR for return
|
||||
MSR ELR_EL1, x5 // Setup point of interrupt
|
||||
#else
|
||||
#ifdef EL2
|
||||
MSR SPSR_EL2, x4 // Setup SPSR for return
|
||||
MSR ELR_EL2, x5 // Setup point of interrupt
|
||||
#else
|
||||
MSR SPSR_EL3, x4 // Setup SPSR for return
|
||||
MSR ELR_EL3, x5 // Setup point of interrupt
|
||||
#endif
|
||||
#endif
|
||||
LDP x18, x19, [sp], #16 // Recover x18, x19
|
||||
LDP x16, x17, [sp], #16 // Recover x16, x17
|
||||
LDP x14, x15, [sp], #16 // Recover x14, x15
|
||||
LDP x12, x13, [sp], #16 // Recover x12, x13
|
||||
LDP x10, x11, [sp], #16 // Recover x10, x11
|
||||
LDP x8, x9, [sp], #16 // Recover x8, x9
|
||||
LDP x6, x7, [sp], #16 // Recover x6, x7
|
||||
LDP x4, x5, [sp], #16 // Recover x4, x5
|
||||
LDP x2, x3, [sp], #16 // Recover x2, x3
|
||||
LDP x0, x1, [sp], #16 // Recover x0, x1
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
ERET // Return to point of interrupt
|
||||
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
__tx_thread_preempt_restore:
|
||||
|
||||
LDR x4, [x0, #8] // Switch to thread stack pointer
|
||||
MOV sp, x4 //
|
||||
|
||||
LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL1
|
||||
STP x20, x21, [sp, #-16]! // Save x20, x21
|
||||
STP x22, x23, [sp, #-16]! // Save x22, x23
|
||||
STP x24, x25, [sp, #-16]! // Save x24, x25
|
||||
STP x26, x27, [sp, #-16]! // Save x26, x27
|
||||
STP x28, x29, [sp, #-16]! // Save x28, x29
|
||||
#ifdef ENABLE_ARM_FP
|
||||
LDR w3, [x0, #248] // Pickup FP enable flag
|
||||
CMP w3, #0 // Is FP enabled?
|
||||
BEQ _skip_fp_save // No, skip FP save
|
||||
STP q0, q1, [sp, #-32]! // Save q0, q1
|
||||
STP q2, q3, [sp, #-32]! // Save q2, q3
|
||||
STP q4, q5, [sp, #-32]! // Save q4, q5
|
||||
STP q6, q7, [sp, #-32]! // Save q6, q7
|
||||
STP q8, q9, [sp, #-32]! // Save q8, q9
|
||||
STP q10, q11, [sp, #-32]! // Save q10, q11
|
||||
STP q12, q13, [sp, #-32]! // Save q12, q13
|
||||
STP q14, q15, [sp, #-32]! // Save q14, q15
|
||||
STP q16, q17, [sp, #-32]! // Save q16, q17
|
||||
STP q18, q19, [sp, #-32]! // Save q18, q19
|
||||
STP q20, q21, [sp, #-32]! // Save q20, q21
|
||||
STP q22, q23, [sp, #-32]! // Save q22, q23
|
||||
STP q24, q25, [sp, #-32]! // Save q24, q25
|
||||
STP q26, q27, [sp, #-32]! // Save q26, q27
|
||||
STP q28, q29, [sp, #-32]! // Save q28, q29
|
||||
STP q30, q31, [sp, #-32]! // Save q30, q31
|
||||
MRS x2, FPSR // Pickup FPSR
|
||||
MRS x3, FPCR // Pickup FPCR
|
||||
STP x2, x3, [sp, #-16]! // Save FPSR, FPCR
|
||||
_skip_fp_save:
|
||||
#endif
|
||||
STP x4, x5, [sp, #-16]! // Save x4 (SPSR_EL3), x5 (ELR_E3)
|
||||
|
||||
MOV x3, sp // Move sp into x3
|
||||
STR x3, [x0, #8] // Save stack pointer in thread control
|
||||
// block
|
||||
LDR x3, =_tx_thread_system_stack_ptr // Pickup address of system stack
|
||||
LDR x4, [x3, #0] // Pickup system stack pointer
|
||||
MOV sp, x4 // Setup system stack pointer
|
||||
|
||||
|
||||
/* Save the remaining time-slice and disable it. */
|
||||
// if (_tx_timer_time_slice)
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_timer_time_slice // Pickup time-slice variable address
|
||||
LDR w2, [x3, #0] // Pickup time-slice
|
||||
CMP w2, #0 // Is it active?
|
||||
BEQ __tx_thread_dont_save_ts // No, don't save it
|
||||
|
||||
// _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
// _tx_timer_time_slice = 0;
|
||||
|
||||
STR w2, [x0, #36] // Save thread's time-slice
|
||||
MOV w2, #0 // Clear value
|
||||
STR w2, [x3, #0] // Disable global time-slice flag
|
||||
|
||||
// }
|
||||
__tx_thread_dont_save_ts:
|
||||
|
||||
|
||||
/* Clear the current task pointer. */
|
||||
/* _tx_thread_current_ptr = TX_NULL; */
|
||||
|
||||
MOV x0, #0 // NULL value
|
||||
STR x0, [x1, #0] // Clear current thread pointer
|
||||
|
||||
/* Return to the scheduler. */
|
||||
// _tx_thread_schedule();
|
||||
|
||||
// }
|
||||
|
||||
__tx_thread_idle_system_restore:
|
||||
|
||||
/* Just return back to the scheduler! */
|
||||
|
||||
LDR x1, =_tx_thread_schedule // Build address for _tx_thread_schedule
|
||||
#ifdef EL1
|
||||
MSR ELR_EL1, x1 // Setup point of interrupt
|
||||
// MOV x1, #0x4 // Setup EL1 return
|
||||
// MSR spsr_el1, x1 // Move into SPSR
|
||||
#else
|
||||
#ifdef EL2
|
||||
MSR ELR_EL2, x1 // Setup point of interrupt
|
||||
// MOV x1, #0x8 // Setup EL2 return
|
||||
// MSR spsr_el2, x1 // Move into SPSR
|
||||
#else
|
||||
MSR ELR_EL3, x1 // Setup point of interrupt
|
||||
// MOV x1, #0xC // Setup EL3 return
|
||||
// MSR spsr_el3, x1 // Move into SPSR
|
||||
#endif
|
||||
#endif
|
||||
ERET // Return to scheduler
|
||||
// }
|
||||
221
ports_arch/ARMv8-A/threadx/common/src/tx_thread_context_save.S
Normal file
221
ports_arch/ARMv8-A/threadx/common/src/tx_thread_context_save.S
Normal file
@@ -0,0 +1,221 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_save ARMv8-A */
|
||||
/* 6.x */
|
||||
/* 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 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_context_save(VOID)
|
||||
// {
|
||||
.global _tx_thread_context_save
|
||||
.type _tx_thread_context_save, @function
|
||||
_tx_thread_context_save:
|
||||
|
||||
/* Upon entry to this routine, it is assumed that IRQ/FIQ interrupts are locked
|
||||
out, x29 (frame pointer), x30 (link register) are saved, we are in EL1,
|
||||
and all other registers are intact. */
|
||||
|
||||
/* Check for a nested interrupt condition. */
|
||||
// if (_tx_thread_system_state++)
|
||||
// {
|
||||
|
||||
STP x0, x1, [sp, #-16]! // Save x0, x1
|
||||
STP x2, x3, [sp, #-16]! // Save x2, x3
|
||||
LDR x3, =_tx_thread_system_state // Pickup address of system state var
|
||||
LDR w2, [x3, #0] // Pickup system state
|
||||
CMP w2, #0 // Is this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_save // Yes, not a nested context save
|
||||
|
||||
/* Nested interrupt condition. */
|
||||
|
||||
ADD w2, w2, #1 // Increment the nested interrupt counter
|
||||
STR w2, [x3, #0] // Store it back in the variable
|
||||
|
||||
/* Save the rest of the scratch registers on the stack and return to the
|
||||
calling ISR. */
|
||||
|
||||
STP x4, x5, [sp, #-16]! // Save x4, x5
|
||||
STP x6, x7, [sp, #-16]! // Save x6, x7
|
||||
STP x8, x9, [sp, #-16]! // Save x8, x9
|
||||
STP x10, x11, [sp, #-16]! // Save x10, x11
|
||||
STP x12, x13, [sp, #-16]! // Save x12, x13
|
||||
STP x14, x15, [sp, #-16]! // Save x14, x15
|
||||
STP x16, x17, [sp, #-16]! // Save x16, x17
|
||||
STP x18, x19, [sp, #-16]! // Save x18, x19
|
||||
#ifdef EL1
|
||||
MRS x0, SPSR_EL1 // Pickup SPSR
|
||||
MRS x1, ELR_EL1 // Pickup ELR (point of interrupt)
|
||||
#else
|
||||
#ifdef EL2
|
||||
MRS x0, SPSR_EL2 // Pickup SPSR
|
||||
MRS x1, ELR_EL2 // Pickup ELR (point of interrupt)
|
||||
#else
|
||||
MRS x0, SPSR_EL3 // Pickup SPSR
|
||||
MRS x1, ELR_EL3 // Pickup ELR (point of interrupt)
|
||||
#endif
|
||||
#endif
|
||||
STP x0, x1, [sp, #-16]! // Save SPSR, ELR
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
STP x29, x30, [sp, #-16]! // Save x29, x30
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
#endif
|
||||
|
||||
/* Return to the ISR. */
|
||||
|
||||
RET // Return to ISR
|
||||
|
||||
__tx_thread_not_nested_save:
|
||||
// }
|
||||
|
||||
/* Otherwise, not nested, check to see if a thread was running. */
|
||||
// else if (_tx_thread_current_ptr)
|
||||
// {
|
||||
|
||||
ADD w2, w2, #1 // Increment the interrupt counter
|
||||
STR w2, [x3, #0] // Store it back in the variable
|
||||
LDR x1, =_tx_thread_current_ptr // Pickup address of current thread ptr
|
||||
LDR x0, [x1, #0] // Pickup current thread pointer
|
||||
CMP x0, #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. */
|
||||
|
||||
STP x4, x5, [sp, #-16]! // Save x4, x5
|
||||
STP x6, x7, [sp, #-16]! // Save x6, x7
|
||||
STP x8, x9, [sp, #-16]! // Save x8, x9
|
||||
STP x10, x11, [sp, #-16]! // Save x10, x11
|
||||
STP x12, x13, [sp, #-16]! // Save x12, x13
|
||||
STP x14, x15, [sp, #-16]! // Save x14, x15
|
||||
STP x16, x17, [sp, #-16]! // Save x16, x17
|
||||
STP x18, x19, [sp, #-16]! // Save x18, x19
|
||||
#ifdef EL1
|
||||
MRS x4, SPSR_EL1 // Pickup SPSR
|
||||
MRS x5, ELR_EL1 // Pickup ELR (point of interrupt)
|
||||
#else
|
||||
#ifdef EL2
|
||||
MRS x4, SPSR_EL2 // Pickup SPSR
|
||||
MRS x5, ELR_EL2 // Pickup ELR (point of interrupt)
|
||||
#else
|
||||
MRS x4, SPSR_EL3 // Pickup SPSR
|
||||
MRS x5, ELR_EL3 // Pickup ELR (point of interrupt)
|
||||
#endif
|
||||
#endif
|
||||
STP x4, x5, [sp, #-16]! // Save SPSR, ELR
|
||||
|
||||
/* Save the current stack pointer in the thread's control block. */
|
||||
// _tx_thread_current_ptr -> tx_thread_stack_ptr = sp;
|
||||
|
||||
MOV x4, sp //
|
||||
STR x4, [x0, #8] // Save thread stack pointer
|
||||
|
||||
/* Switch to the system stack. */
|
||||
// sp = _tx_thread_system_stack_ptr;
|
||||
|
||||
LDR x3, =_tx_thread_system_stack_ptr // Pickup address of system stack
|
||||
LDR x4, [x3, #0] // Pickup system stack pointer
|
||||
MOV sp, x4 // Setup system stack pointer
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
STP x29, x30, [sp, #-16]! // Save x29, x30
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
#endif
|
||||
|
||||
RET // 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. */
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
STP x29, x30, [sp, #-16]! // Save x29, x30
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
#endif
|
||||
|
||||
ADD sp, sp, #48 // Recover saved registers
|
||||
RET // Continue IRQ processing
|
||||
|
||||
// }
|
||||
// }
|
||||
97
ports_arch/ARMv8-A/threadx/common/src/tx_thread_fp_disable.c
Normal file
97
ports_arch/ARMv8-A/threadx/common/src/tx_thread_fp_disable.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_fp_disable ARMv8-A */
|
||||
/* 6.1.10 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function disables the FP for the currently executing thread. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_fp_disable(VOID)
|
||||
{
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
ULONG system_state;
|
||||
|
||||
|
||||
/* Pickup the current thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(thread_ptr);
|
||||
|
||||
/* Get the system state. */
|
||||
system_state = TX_THREAD_GET_SYSTEM_STATE();
|
||||
|
||||
/* Make sure it is not NULL. */
|
||||
if (thread_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Thread is running... make sure the call is from the thread context. */
|
||||
if (system_state == 0)
|
||||
{
|
||||
|
||||
/* Yes, now set the FP enable flag to false in the TX_THREAD structure. */
|
||||
thread_ptr -> tx_thread_fp_enable = TX_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
96
ports_arch/ARMv8-A/threadx/common/src/tx_thread_fp_enable.c
Normal file
96
ports_arch/ARMv8-A/threadx/common/src/tx_thread_fp_enable.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_fp_enable ARMv8-A */
|
||||
/* 6.1.10 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function enabled the FP for the currently executing thread. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_fp_enable(VOID)
|
||||
{
|
||||
|
||||
TX_THREAD *thread_ptr;
|
||||
ULONG system_state;
|
||||
|
||||
|
||||
/* Pickup the current thread pointer. */
|
||||
TX_THREAD_GET_CURRENT(thread_ptr);
|
||||
|
||||
/* Get the system state. */
|
||||
system_state = TX_THREAD_GET_SYSTEM_STATE();
|
||||
|
||||
/* Make sure it is not NULL. */
|
||||
if (thread_ptr != TX_NULL)
|
||||
{
|
||||
|
||||
/* Thread is running... make sure the call is from the thread context. */
|
||||
if (system_state == 0)
|
||||
{
|
||||
|
||||
/* Yes, now setup the FP enable flag in the TX_THREAD structure. */
|
||||
thread_ptr -> tx_thread_fp_enable = TX_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_control ARMv8-A */
|
||||
/* 6.x */
|
||||
/* 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 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// UINT _tx_thread_interrupt_control(UINT new_posture)
|
||||
// {
|
||||
.global _tx_thread_interrupt_control
|
||||
.type _tx_thread_interrupt_control, @function
|
||||
_tx_thread_interrupt_control:
|
||||
|
||||
/* Pickup current interrupt lockout posture. */
|
||||
|
||||
MRS x1, DAIF // Pickup current interrupt posture
|
||||
|
||||
/* Apply the new interrupt posture. */
|
||||
|
||||
MSR DAIF, x0 // Set new interrupt posture
|
||||
MOV x0, x1 // Setup return value
|
||||
RET // Return to caller
|
||||
// }
|
||||
@@ -0,0 +1,84 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_disable ARMv8-A */
|
||||
/* 6.x */
|
||||
/* 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 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// UINT _tx_thread_interrupt_disable(void)
|
||||
// {
|
||||
.global _tx_thread_interrupt_disable
|
||||
.type _tx_thread_interrupt_disable, @function
|
||||
_tx_thread_interrupt_disable:
|
||||
|
||||
/* Pickup current interrupt lockout posture. */
|
||||
|
||||
MRS x0, DAIF // Pickup current interrupt lockout posture
|
||||
|
||||
/* Mask interrupts. */
|
||||
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
RET // Return to caller
|
||||
// }
|
||||
@@ -0,0 +1,82 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_interrupt_restore ARMv8-A */
|
||||
/* 6.x */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* old_posture Old interrupt lockout posture */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Application Code */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// UINT _tx_thread_interrupt_restore(UINT old_posture)
|
||||
// {
|
||||
.global _tx_thread_interrupt_restore
|
||||
.type _tx_thread_interrupt_restore, @function
|
||||
_tx_thread_interrupt_restore:
|
||||
|
||||
/* Restore the old interrupt posture. */
|
||||
|
||||
MSR DAIF, x0 // Setup the old posture
|
||||
RET // Return to caller
|
||||
|
||||
// }
|
||||
233
ports_arch/ARMv8-A/threadx/common/src/tx_thread_schedule.S
Normal file
233
ports_arch/ARMv8-A/threadx/common/src/tx_thread_schedule.S
Normal file
@@ -0,0 +1,233 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule ARMv8-A */
|
||||
/* 6.x */
|
||||
/* 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 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
// {
|
||||
.global _tx_thread_schedule
|
||||
.type _tx_thread_schedule, @function
|
||||
_tx_thread_schedule:
|
||||
|
||||
/* Enable interrupts. */
|
||||
|
||||
MSR DAIFClr, 0x3 // Enable interrupts
|
||||
|
||||
/* Wait for a thread to execute. */
|
||||
// do
|
||||
// {
|
||||
|
||||
LDR x1, =_tx_thread_execute_ptr // Address of thread execute ptr
|
||||
|
||||
#ifdef TX_ENABLE_WFI
|
||||
__tx_thread_schedule_loop:
|
||||
LDR x0, [x1, #0] // Pickup next thread to execute
|
||||
CMP x0, #0 // Is it NULL?
|
||||
BNE _tx_thread_schedule_thread //
|
||||
WFI //
|
||||
B __tx_thread_schedule_loop // Keep looking for a thread
|
||||
_tx_thread_schedule_thread:
|
||||
#else
|
||||
__tx_thread_schedule_loop:
|
||||
LDR x0, [x1, #0] // Pickup next thread to execute
|
||||
CMP x0, #0 // Is it NULL?
|
||||
BEQ __tx_thread_schedule_loop // If so, keep looking for a thread
|
||||
#endif
|
||||
|
||||
// }
|
||||
// while(_tx_thread_execute_ptr == TX_NULL);
|
||||
|
||||
/* Yes! We have a thread to execute. Lockout interrupts and
|
||||
transfer control to it. */
|
||||
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
|
||||
/* Setup the current thread pointer. */
|
||||
// _tx_thread_current_ptr = _tx_thread_execute_ptr;
|
||||
|
||||
LDR x1, =_tx_thread_current_ptr // Pickup address of current thread
|
||||
STR x0, [x1, #0] // Setup current thread pointer
|
||||
|
||||
/* Increment the run count for this thread. */
|
||||
// _tx_thread_current_ptr -> tx_thread_run_count++;
|
||||
|
||||
LDR w2, [x0, #4] // Pickup run counter
|
||||
LDR w3, [x0, #36] // Pickup time-slice for this thread
|
||||
ADD w2, w2, #1 // Increment thread run-counter
|
||||
STR w2, [x0, #4] // Store the new run counter
|
||||
|
||||
/* Setup time-slice, if present. */
|
||||
// _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice;
|
||||
|
||||
LDR x2, =_tx_timer_time_slice // Pickup address of time slice
|
||||
// variable
|
||||
LDR x4, [x0, #8] // Switch stack pointers
|
||||
MOV sp, x4 //
|
||||
STR w3, [x2, #0] // 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 x19, x0 // Save x0
|
||||
BL _tx_execution_thread_enter // Call the thread execution enter function
|
||||
MOV x0, x19 // Restore x0
|
||||
#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. */
|
||||
|
||||
LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL1
|
||||
CMP x5, #0 // Check for synchronous context switch (ELR_EL1 = NULL)
|
||||
BEQ _tx_solicited_return
|
||||
#ifdef EL1
|
||||
MSR SPSR_EL1, x4 // Setup SPSR for return
|
||||
MSR ELR_EL1, x5 // Setup point of interrupt
|
||||
#else
|
||||
#ifdef EL2
|
||||
MSR SPSR_EL2, x4 // Setup SPSR for return
|
||||
MSR ELR_EL2, x5 // Setup point of interrupt
|
||||
#else
|
||||
MSR SPSR_EL3, x4 // Setup SPSR for return
|
||||
MSR ELR_EL3, x5 // Setup point of interrupt
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ENABLE_ARM_FP
|
||||
LDR w1, [x0, #248] // Pickup FP enable flag
|
||||
CMP w1, #0 // Is FP enabled?
|
||||
BEQ _skip_interrupt_fp_restore // No, skip FP restore
|
||||
LDP x0, x1, [sp], #16 // Pickup FPSR, FPCR
|
||||
MSR FPSR, x0 // Recover FPSR
|
||||
MSR FPCR, x1 // Recover FPCR
|
||||
LDP q30, q31, [sp], #32 // Recover q30, q31
|
||||
LDP q28, q29, [sp], #32 // Recover q28, q29
|
||||
LDP q26, q27, [sp], #32 // Recover q26, q27
|
||||
LDP q24, q25, [sp], #32 // Recover q24, q25
|
||||
LDP q22, q23, [sp], #32 // Recover q22, q23
|
||||
LDP q20, q21, [sp], #32 // Recover q20, q21
|
||||
LDP q18, q19, [sp], #32 // Recover q18, q19
|
||||
LDP q16, q17, [sp], #32 // Recover q16, q17
|
||||
LDP q14, q15, [sp], #32 // Recover q14, q15
|
||||
LDP q12, q13, [sp], #32 // Recover q12, q13
|
||||
LDP q10, q11, [sp], #32 // Recover q10, q11
|
||||
LDP q8, q9, [sp], #32 // Recover q8, q9
|
||||
LDP q6, q7, [sp], #32 // Recover q6, q7
|
||||
LDP q4, q5, [sp], #32 // Recover q4, q5
|
||||
LDP q2, q3, [sp], #32 // Recover q2, q3
|
||||
LDP q0, q1, [sp], #32 // Recover q0, q1
|
||||
_skip_interrupt_fp_restore:
|
||||
#endif
|
||||
LDP x28, x29, [sp], #16 // Recover x28
|
||||
LDP x26, x27, [sp], #16 // Recover x26, x27
|
||||
LDP x24, x25, [sp], #16 // Recover x24, x25
|
||||
LDP x22, x23, [sp], #16 // Recover x22, x23
|
||||
LDP x20, x21, [sp], #16 // Recover x20, x21
|
||||
LDP x18, x19, [sp], #16 // Recover x18, x19
|
||||
LDP x16, x17, [sp], #16 // Recover x16, x17
|
||||
LDP x14, x15, [sp], #16 // Recover x14, x15
|
||||
LDP x12, x13, [sp], #16 // Recover x12, x13
|
||||
LDP x10, x11, [sp], #16 // Recover x10, x11
|
||||
LDP x8, x9, [sp], #16 // Recover x8, x9
|
||||
LDP x6, x7, [sp], #16 // Recover x6, x7
|
||||
LDP x4, x5, [sp], #16 // Recover x4, x5
|
||||
LDP x2, x3, [sp], #16 // Recover x2, x3
|
||||
LDP x0, x1, [sp], #16 // Recover x0, x1
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
ERET // Return to point of interrupt
|
||||
|
||||
_tx_solicited_return:
|
||||
|
||||
#ifdef ENABLE_ARM_FP
|
||||
LDR w1, [x0, #248] // Pickup FP enable flag
|
||||
CMP w1, #0 // Is FP enabled?
|
||||
BEQ _skip_solicited_fp_restore // No, skip FP restore
|
||||
LDP x0, x1, [sp], #16 // Pickup FPSR, FPCR
|
||||
MSR FPSR, x0 // Recover FPSR
|
||||
MSR FPCR, x1 // Recover FPCR
|
||||
LDP q14, q15, [sp], #32 // Recover q14, q15
|
||||
LDP q12, q13, [sp], #32 // Recover q12, q13
|
||||
LDP q10, q11, [sp], #32 // Recover q10, q11
|
||||
LDP q8, q9, [sp], #32 // Recover q8, q9
|
||||
_skip_solicited_fp_restore:
|
||||
#endif
|
||||
LDP x27, x28, [sp], #16 // Recover x27, x28
|
||||
LDP x25, x26, [sp], #16 // Recover x25, x26
|
||||
LDP x23, x24, [sp], #16 // Recover x23, x24
|
||||
LDP x21, x22, [sp], #16 // Recover x21, x22
|
||||
LDP x19, x20, [sp], #16 // Recover x19, x20
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
MSR DAIF, x4 // Recover DAIF
|
||||
RET // Return to caller
|
||||
// }
|
||||
163
ports_arch/ARMv8-A/threadx/common/src/tx_thread_stack_build.S
Normal file
163
ports_arch/ARMv8-A/threadx/common/src/tx_thread_stack_build.S
Normal file
@@ -0,0 +1,163 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_stack_build ARMv8-A */
|
||||
/* 6.x */
|
||||
/* 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 */
|
||||
/* function_ptr Pointer to entry 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 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
|
||||
// {
|
||||
.global _tx_thread_stack_build
|
||||
.type _tx_thread_stack_build, @function
|
||||
_tx_thread_stack_build:
|
||||
|
||||
|
||||
/* Build an interrupt frame. On Cortex-A35 it should look like this:
|
||||
|
||||
Stack Top: SSPR Initial SSPR
|
||||
ELR Point of interrupt
|
||||
x28 Initial value for x28
|
||||
not used Not used
|
||||
x26 Initial value for x26
|
||||
x27 Initial value for x27
|
||||
x24 Initial value for x24
|
||||
x25 Initial value for x25
|
||||
x22 Initial value for x22
|
||||
x23 Initial value for x23
|
||||
x20 Initial value for x20
|
||||
x21 Initial value for x21
|
||||
x18 Initial value for x18
|
||||
x19 Initial value for x19
|
||||
x16 Initial value for x16
|
||||
x17 Initial value for x17
|
||||
x14 Initial value for x14
|
||||
x15 Initial value for x15
|
||||
x12 Initial value for x12
|
||||
x13 Initial value for x13
|
||||
x10 Initial value for x10
|
||||
x11 Initial value for x11
|
||||
x8 Initial value for x8
|
||||
x9 Initial value for x9
|
||||
x6 Initial value for x6
|
||||
x7 Initial value for x7
|
||||
x4 Initial value for x4
|
||||
x5 Initial value for x5
|
||||
x2 Initial value for x2
|
||||
x3 Initial value for x3
|
||||
x0 Initial value for x0
|
||||
x1 Initial value for x1
|
||||
x29 Initial value for x29 (frame pointer)
|
||||
x30 Initial value for x30 (link register)
|
||||
0 For stack backtracing
|
||||
|
||||
Stack Bottom: (higher memory address) */
|
||||
|
||||
LDR x4, [x0, #24] // Pickup end of stack area
|
||||
BIC x4, x4, #0xF // Ensure 16-byte alignment
|
||||
|
||||
/* Actually build the stack frame. */
|
||||
|
||||
MOV x2, #0 // Build clear value
|
||||
MOV x3, #0 //
|
||||
|
||||
STP x2, x3, [x4, #-16]! // Set backtrace to 0
|
||||
STP x2, x3, [x4, #-16]! // Set initial x29, x30
|
||||
STP x2, x3, [x4, #-16]! // Set initial x0, x1
|
||||
STP x2, x3, [x4, #-16]! // Set initial x2, x3
|
||||
STP x2, x3, [x4, #-16]! // Set initial x4, x5
|
||||
STP x2, x3, [x4, #-16]! // Set initial x6, x7
|
||||
STP x2, x3, [x4, #-16]! // Set initial x8, x9
|
||||
STP x2, x3, [x4, #-16]! // Set initial x10, x11
|
||||
STP x2, x3, [x4, #-16]! // Set initial x12, x13
|
||||
STP x2, x3, [x4, #-16]! // Set initial x14, x15
|
||||
STP x2, x3, [x4, #-16]! // Set initial x16, x17
|
||||
STP x2, x3, [x4, #-16]! // Set initial x18, x19
|
||||
STP x2, x3, [x4, #-16]! // Set initial x20, x21
|
||||
STP x2, x3, [x4, #-16]! // Set initial x22, x23
|
||||
STP x2, x3, [x4, #-16]! // Set initial x24, x25
|
||||
STP x2, x3, [x4, #-16]! // Set initial x26, x27
|
||||
STP x2, x3, [x4, #-16]! // Set initial x28
|
||||
#ifdef EL1
|
||||
MOV x2, #0x4 // Build initial SPSR (EL1)
|
||||
#else
|
||||
#ifdef EL2
|
||||
MOV x2, #0x8 // Build initial SPSR (EL2)
|
||||
#else
|
||||
MOV x2, #0xC // Build initial SPSR (EL3)
|
||||
#endif
|
||||
#endif
|
||||
MOV x3, x1 // Build initial ELR
|
||||
STP x2, x3, [x4, #-16]! // Set initial SPSR & ELR
|
||||
|
||||
/* Setup stack pointer. */
|
||||
// thread_ptr -> tx_thread_stack_ptr = x2;
|
||||
|
||||
STR x4, [x0, #8] // Save stack pointer in thread's
|
||||
RET // Return to caller
|
||||
|
||||
// }
|
||||
156
ports_arch/ARMv8-A/threadx/common/src/tx_thread_system_return.S
Normal file
156
ports_arch/ARMv8-A/threadx/common/src/tx_thread_system_return.S
Normal file
@@ -0,0 +1,156 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_system_return ARMv8-A */
|
||||
/* 6.x */
|
||||
/* 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 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_system_return(VOID)
|
||||
// {
|
||||
.global _tx_thread_system_return
|
||||
.type _tx_thread_system_return, @function
|
||||
_tx_thread_system_return:
|
||||
|
||||
/* Save minimal context on the stack. */
|
||||
|
||||
MRS x0, DAIF // Pickup DAIF
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
STP x29, x30, [sp, #-16]! // Save x29 (frame pointer), x30 (link register)
|
||||
STP x19, x20, [sp, #-16]! // Save x19, x20
|
||||
STP x21, x22, [sp, #-16]! // Save x21, x22
|
||||
STP x23, x24, [sp, #-16]! // Save x23, x24
|
||||
STP x25, x26, [sp, #-16]! // Save x25, x26
|
||||
STP x27, x28, [sp, #-16]! // Save x27, x28
|
||||
LDR x5, =_tx_thread_current_ptr // Pickup address of current ptr
|
||||
LDR x6, [x5, #0] // Pickup current thread pointer
|
||||
|
||||
#ifdef ENABLE_ARM_FP
|
||||
LDR w7, [x6, #248] // Pickup FP enable flag
|
||||
CMP w7, #0 // Is FP enabled?
|
||||
BEQ _skip_fp_save // No, skip FP save
|
||||
STP q8, q9, [sp, #-32]! // Save q8, q9
|
||||
STP q10, q11, [sp, #-32]! // Save q10, q11
|
||||
STP q12, q13, [sp, #-32]! // Save q12, q13
|
||||
STP q14, q15, [sp, #-32]! // Save q14, q15
|
||||
MRS x2, FPSR // Pickup FPSR
|
||||
MRS x3, FPCR // Pickup FPCR
|
||||
STP x2, x3, [sp, #-16]! // Save FPSR, FPCR
|
||||
_skip_fp_save:
|
||||
#endif
|
||||
|
||||
MOV x1, #0 // Clear x1
|
||||
STP x0, x1, [sp, #-16]! // Save DAIF and clear value for ELR_EK1
|
||||
|
||||
#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. */
|
||||
|
||||
MOV x19, x5 // Save x5
|
||||
MOV x20, x6 // Save x6
|
||||
BL _tx_execution_thread_exit // Call the thread exit function
|
||||
MOV x5, x19 // Restore x5
|
||||
MOV x6, x20 // Restore x6
|
||||
#endif
|
||||
|
||||
LDR x2, =_tx_timer_time_slice // Pickup address of time slice
|
||||
LDR w1, [x2, #0] // 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;
|
||||
|
||||
MOV x4, sp //
|
||||
STR x4, [x6, #8] // Save thread stack pointer
|
||||
LDR x3, =_tx_thread_system_stack_ptr // Pickup address of system stack
|
||||
LDR x4, [x3, #0] // Pickup system stack pointer
|
||||
MOV sp, x4 // Setup system stack pointer
|
||||
|
||||
/* Determine if the time-slice is active. */
|
||||
// if (_tx_timer_time_slice)
|
||||
// {
|
||||
|
||||
MOV x4, #0 // Build clear value
|
||||
CMP w1, #0 // Is a time-slice active?
|
||||
BEQ __tx_thread_dont_save_ts // No, don't save the time-slice
|
||||
|
||||
/* Save the current remaining time-slice. */
|
||||
// _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
// _tx_timer_time_slice = 0;
|
||||
|
||||
STR w4, [x2, #0] // Clear time-slice
|
||||
STR w1, [x6, #36] // Store current time-slice
|
||||
|
||||
// }
|
||||
__tx_thread_dont_save_ts:
|
||||
|
||||
/* Clear the current thread pointer. */
|
||||
// _tx_thread_current_ptr = TX_NULL;
|
||||
|
||||
STR x4, [x5, #0] // Clear current thread pointer
|
||||
|
||||
B _tx_thread_schedule // Jump to scheduler!
|
||||
|
||||
// }
|
||||
233
ports_arch/ARMv8-A/threadx/common/src/tx_timer_interrupt.S
Normal file
233
ports_arch/ARMv8-A/threadx/common/src/tx_timer_interrupt.S
Normal file
@@ -0,0 +1,233 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_timer_interrupt ARMv8-A */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes the hardware timer interrupt. This */
|
||||
/* processing includes incrementing the system clock and checking for */
|
||||
/* time slice and/or timer expiration. If either is found, the */
|
||||
/* interrupt context save/restore functions are called along with the */
|
||||
/* expiration functions. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_timer_expiration_process Timer expiration processing */
|
||||
/* _tx_thread_time_slice Time slice interrupted thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* interrupt vector */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_timer_interrupt(VOID)
|
||||
// {
|
||||
.global _tx_timer_interrupt
|
||||
.type _tx_timer_interrupt, @function
|
||||
_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 x1, =_tx_timer_system_clock // Pickup address of system clock
|
||||
LDR w0, [x1, #0] // Pickup system clock
|
||||
ADD w0, w0, #1 // Increment system clock
|
||||
STR w0, [x1, #0] // Store new system clock
|
||||
|
||||
/* Test for time-slice expiration. */
|
||||
/* if (_tx_timer_time_slice)
|
||||
{ */
|
||||
|
||||
LDR x3, =_tx_timer_time_slice // Pickup address of time-slice
|
||||
LDR w2, [x3, #0] // Pickup time-slice
|
||||
CMP w2, #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 w2, w2, #1 // Decrement the time-slice
|
||||
STR w2, [x3, #0] // Store new time-slice value
|
||||
|
||||
/* Check for expiration. */
|
||||
/* if (__tx_timer_time_slice == 0) */
|
||||
|
||||
CMP w2, #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 x3, =_tx_timer_expired_time_slice // Pickup address of expired flag
|
||||
MOV w0, #1 // Build expired value
|
||||
STR w0, [x3, #0] // Set time-slice expiration flag
|
||||
|
||||
/* } */
|
||||
|
||||
__tx_timer_no_time_slice:
|
||||
|
||||
/* Test for timer expiration. */
|
||||
// if (*_tx_timer_current_ptr)
|
||||
// {
|
||||
|
||||
LDR x1, =_tx_timer_current_ptr // Pickup current timer pointer addr
|
||||
LDR x0, [x1, #0] // Pickup current timer
|
||||
LDR x2, [x0, #0] // Pickup timer list entry
|
||||
CMP x2, #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 x3, =_tx_timer_expired // Pickup expiration flag address
|
||||
MOV w2, #1 // Build expired value
|
||||
STR w2, [x3, #0] // Set expired flag
|
||||
B __tx_timer_done // Finished timer processing
|
||||
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
__tx_timer_no_timer:
|
||||
|
||||
/* No timer expired, increment the timer pointer. */
|
||||
// _tx_timer_current_ptr++;
|
||||
|
||||
ADD x0, x0, #8 // Move to next timer
|
||||
|
||||
/* Check for wrap-around. */
|
||||
// if (_tx_timer_current_ptr == _tx_timer_list_end)
|
||||
|
||||
LDR x3, =_tx_timer_list_end // Pickup addr of timer list end
|
||||
LDR x2, [x3, #0] // Pickup list end
|
||||
CMP x0, x2 // 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 x3, =_tx_timer_list_start // Pickup addr of timer list start
|
||||
LDR x0, [x3, #0] // Set current pointer to list start
|
||||
|
||||
__tx_timer_skip_wrap:
|
||||
|
||||
STR x0, [x1, #0] // Store new current timer pointer
|
||||
// }
|
||||
|
||||
__tx_timer_done:
|
||||
|
||||
|
||||
/* See if anything has expired. */
|
||||
// if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
|
||||
//{
|
||||
|
||||
LDR x3, =_tx_timer_expired_time_slice // Pickup addr of expired flag
|
||||
LDR w2, [x3, #0] // Pickup time-slice expired flag
|
||||
CMP w2, #0 // Did a time-slice expire?
|
||||
BNE __tx_something_expired // If non-zero, time-slice expired
|
||||
LDR x1, =_tx_timer_expired // Pickup addr of other expired flag
|
||||
LDR w0, [x1, #0] // Pickup timer expired flag
|
||||
CMP w0, #0 // Did a timer expire?
|
||||
BEQ __tx_timer_nothing_expired // No, nothing expired
|
||||
|
||||
__tx_something_expired:
|
||||
|
||||
|
||||
STP x29, x30, [sp, #-16]! // Save x29 (frame pointer), x30 (link register)
|
||||
|
||||
/* Did a timer expire? */
|
||||
// if (_tx_timer_expired)
|
||||
// {
|
||||
|
||||
LDR x1, =_tx_timer_expired // Pickup addr of expired flag
|
||||
LDR w0, [x1, #0] // Pickup timer expired flag
|
||||
CMP w0, #0 // Check for timer expiration
|
||||
BEQ __tx_timer_dont_activate // If not set, skip timer activation
|
||||
|
||||
/* Process timer expiration. */
|
||||
// _tx_timer_expiration_process();
|
||||
|
||||
BL _tx_timer_expiration_process // Call the timer expiration handling routine
|
||||
|
||||
// }
|
||||
__tx_timer_dont_activate:
|
||||
|
||||
/* Did time slice expire? */
|
||||
// if (_tx_timer_expired_time_slice)
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired
|
||||
LDR w2, [x3, #0] // Pickup the actual flag
|
||||
CMP w2, #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:
|
||||
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
// }
|
||||
|
||||
__tx_timer_nothing_expired:
|
||||
|
||||
RET // Return to caller
|
||||
|
||||
// }
|
||||
@@ -0,0 +1,158 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
|
||||
<cconfiguration id="com.arm.eclipse.build.config.v6.exe.debug.base.515451048">
|
||||
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.exe.debug.base.515451048" moduleId="org.eclipse.cdt.core.settings" name="Debug">
|
||||
|
||||
<externalSettings/>
|
||||
|
||||
<extensions>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="com.arm.eclipse.builder.armcc.error" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<configuration artifactExtension="axf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.exe.debug.base.515451048" name="Debug" parent="com.arm.eclipse.build.config.v6.exe.debug.base">
|
||||
|
||||
<folderInfo id="com.arm.eclipse.build.config.v6.exe.debug.base.515451048." name="/" resourcePath="">
|
||||
|
||||
<toolChain id="com.arm.toolchain.v6.exe.debug.base.var.arm_compiler_6-6.1388095870" name="Arm Compiler 6" superClass="com.arm.toolchain.v6.exe.debug.base.var.arm_compiler_6-6">
|
||||
|
||||
<option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.689426261" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-A35.AArch64.ARMv8.Neon.Crypto" valueType="string"/>
|
||||
|
||||
<targetPlatform id="com.arm.toolchain.v6.exe.debug.base.var.arm_compiler_6-6.1388095870.857809581" name=""/>
|
||||
|
||||
<builder autoBuildTarget="all" buildPath="${workspace_loc:/sample_threadx}/Debug" cleanBuildTarget="clean" enableAutoBuild="false" enableCleanBuild="true" enabledIncrementalBuild="true" id="com.arm.toolchain.v6.builder.1944684744" incrementalBuildTarget="all" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="8" superClass="com.arm.toolchain.v6.builder"/>
|
||||
|
||||
<tool id="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.259341383" name="Arm C Compiler 6" superClass="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6">
|
||||
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.cpu.96377009" name="CPU (-mcpu)" superClass="com.arm.tool.c.compiler.v6.base.option.cpu" useByScannerDiscovery="true" value="cortex-a35" valueType="string"/>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.tool.c.compiler.v6.base.option.defmac.1975445896" name="Define macro (-D)" superClass="com.arm.tool.c.compiler.v6.base.option.defmac" useByScannerDiscovery="false" valueType="definedSymbols">
|
||||
|
||||
<listOptionValue builtIn="false" value="STANDALONE"/>
|
||||
|
||||
</option>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.tool.c.compiler.v6.base.option.incpath.1271571516" name="Include path (-I)" superClass="com.arm.tool.c.compiler.v6.base.option.incpath" useByScannerDiscovery="false" valueType="includePath">
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/tx/inc_generic}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/tx/inc_port}""/>
|
||||
|
||||
</option>
|
||||
|
||||
<option id="com.arm.tool.c.compiler.v6.base.options.debug.level.1548640167" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.options.debug.level.std" valueType="enumerated"/>
|
||||
|
||||
<inputType id="com.arm.tool.c.compiler.v6.base.input.815952161" superClass="com.arm.tool.c.compiler.v6.base.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.tool.cpp.compiler.v6.base.var.arm_compiler_6-6.1091536604" name="Arm C++ Compiler 6" superClass="com.arm.tool.cpp.compiler.v6.base.var.arm_compiler_6-6">
|
||||
|
||||
<option id="com.arm.tool.c.compiler.v6.base.options.debug.level.1962633763" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.options.debug.level.std" valueType="enumerated"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.tool.assembler.v6.base.var.arm_compiler_6-6.1147447905" name="Arm Assembler 6" superClass="com.arm.tool.assembler.v6.base.var.arm_compiler_6-6">
|
||||
|
||||
<option id="com.arm.tool.assembler.v6.base.option.cpu.269795998" name="CPU (-mcpu)" superClass="com.arm.tool.assembler.v6.base.option.cpu" useByScannerDiscovery="false" value="cortex-a35" valueType="string"/>
|
||||
|
||||
<option id="com.arm.tool.assembler.v6.base.options.debug.level.1521551718" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" useByScannerDiscovery="false" value="com.arm.tool.assembler.v6.base.options.debug.level.std" valueType="enumerated"/>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="true" id="com.arm.tool.assembler.v6.base.option.defmac.281085002" name="Define macro (-D)" superClass="com.arm.tool.assembler.v6.base.option.defmac" useByScannerDiscovery="false" valueType="definedSymbols"/>
|
||||
|
||||
<inputType id="com.arm.tool.assembler.v6.base.input.1000911913" superClass="com.arm.tool.assembler.v6.base.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.tool.c.linker.v6.base.var.arm_compiler_6-6.1807144931" name="Arm Linker 6" superClass="com.arm.tool.c.linker.v6.base.var.arm_compiler_6-6">
|
||||
|
||||
<option id="com.arm.tool.c.linker.option.entry.249327747" name="Image entry point (--entry)" superClass="com.arm.tool.c.linker.option.entry" useByScannerDiscovery="false" value="start64" valueType="string"/>
|
||||
|
||||
<option id="com.arm.tool.c.linker.option.scatter.1246240408" name="Scatter file (--scatter)" superClass="com.arm.tool.c.linker.option.scatter" useByScannerDiscovery="false" value="..\sample_threadx.scat" valueType="string"/>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.tool.c.linker.libs.2105481551" name="User library files" superClass="com.arm.tool.c.linker.libs" useByScannerDiscovery="false" valueType="libs">
|
||||
|
||||
<listOptionValue builtIn="false" value="..\..\tx\Debug\tx.a"/>
|
||||
|
||||
</option>
|
||||
|
||||
<option id="com.arm.tool.c.linker.option.imagemap.359605740" name="Generate image map (--map)" superClass="com.arm.tool.c.linker.option.imagemap" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
|
||||
<option id="com.arm.tool.c.linker.option.verbose.509554865" name="Verbose output (--verbose)" superClass="com.arm.tool.c.linker.option.verbose" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
|
||||
<option id="com.arm.tool.c.linker.option.totals.428431324" name="List total code and data sizes of output image (--info=totals)" superClass="com.arm.tool.c.linker.option.totals" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
|
||||
<option id="com.arm.tool.c.linker.option.redirectoutput.259431691" name="Redirect diagnostics output to file (--list)" superClass="com.arm.tool.c.linker.option.redirectoutput" useByScannerDiscovery="false" value="sample_threadx.map" valueType="string"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.tool.librarian.v6.base.var.arm_compiler_6-6.1243987688" name="Arm Librarian 6" superClass="com.arm.tool.librarian.v6.base.var.arm_compiler_6-6"/>
|
||||
|
||||
</toolChain>
|
||||
|
||||
</folderInfo>
|
||||
|
||||
<sourceEntries>
|
||||
|
||||
<entry excluding="startup_el3.S|startup_el2.S|startup_el1.S|startup_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
|
||||
</sourceEntries>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
|
||||
</cconfiguration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<project id="sample_threadx.com.arm.eclipse.build.project.v6.exe.1027551600" name="Executable"/>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
|
||||
<storageModule moduleId="refreshScope" versionNumber="2">
|
||||
|
||||
<configuration configurationName="Debug">
|
||||
|
||||
<resource resourceType="PROJECT" workspacePath="/sample_threadx"/>
|
||||
|
||||
</configuration>
|
||||
|
||||
<configuration configurationName="Release">
|
||||
|
||||
<resource resourceType="PROJECT" workspacePath="/sample_threadx"/>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
|
||||
<storageModule moduleId="com.arm.projectSettings" version="6.0.0"/>
|
||||
|
||||
</cproject>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>sample_threadx</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,561 @@
|
||||
/*
|
||||
* GICv3.h - data types and function prototypes for GICv3 utility routines
|
||||
*
|
||||
* Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#ifndef GICV3_h
|
||||
#define GICV3_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* extra flags for GICD enable
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
gicdctlr_EnableGrp0 = (1 << 0),
|
||||
gicdctlr_EnableGrp1NS = (1 << 1),
|
||||
gicdctlr_EnableGrp1A = (1 << 1),
|
||||
gicdctlr_EnableGrp1S = (1 << 2),
|
||||
gicdctlr_EnableAll = (1 << 2) | (1 << 1) | (1 << 0),
|
||||
gicdctlr_ARE_S = (1 << 4), /* Enable Secure state affinity routing */
|
||||
gicdctlr_ARE_NS = (1 << 5), /* Enable Non-Secure state affinity routing */
|
||||
gicdctlr_DS = (1 << 6), /* Disable Security support */
|
||||
gicdctlr_E1NWF = (1 << 7) /* Enable "1-of-N" wakeup model */
|
||||
} GICDCTLRFlags_t;
|
||||
|
||||
/*
|
||||
* modes for SPI routing
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
gicdirouter_ModeSpecific = 0,
|
||||
gicdirouter_ModeAny = (1 << 31)
|
||||
} GICDIROUTERBits_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
gicdicfgr_Level = 0,
|
||||
gicdicfgr_Edge = (1 << 1)
|
||||
} GICDICFGRBits_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
gicigroupr_G0S = 0,
|
||||
gicigroupr_G1NS = (1 << 0),
|
||||
gicigroupr_G1S = (1 << 2)
|
||||
} GICIGROUPRBits_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
gicrwaker_ProcessorSleep = (1 << 1),
|
||||
gicrwaker_ChildrenAsleep = (1 << 2)
|
||||
} GICRWAKERBits_t;
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* Utility macros & functions
|
||||
*/
|
||||
#define RANGE_LIMIT(x) ((sizeof(x) / sizeof((x)[0])) - 1)
|
||||
|
||||
static inline uint64_t gicv3PackAffinity(uint32_t aff3, uint32_t aff2,
|
||||
uint32_t aff1, uint32_t aff0)
|
||||
{
|
||||
/*
|
||||
* only need to cast aff3 to get type promotion for all affinities
|
||||
*/
|
||||
return ((((uint64_t)aff3 & 0xff) << 32) |
|
||||
((aff2 & 0xff) << 16) |
|
||||
((aff1 & 0xff) << 8) | aff0);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* GIC Distributor Function Prototypes
|
||||
*/
|
||||
|
||||
/*
|
||||
* ConfigGICD - configure GIC Distributor prior to enabling it
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* control - control flags
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* ConfigGICD() will set an absolute flags value, whereas
|
||||
* {En,Dis}ableGICD() will only {set,clear} the flag bits
|
||||
* passed as a parameter
|
||||
*/
|
||||
void ConfigGICD(GICDCTLRFlags_t flags);
|
||||
|
||||
/*
|
||||
* EnableGICD - top-level enable for GIC Distributor
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* flags - new control flags to set
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* ConfigGICD() will set an absolute flags value, whereas
|
||||
* {En,Dis}ableGICD() will only {set,clear} the flag bits
|
||||
* passed as a parameter
|
||||
*/
|
||||
void EnableGICD(GICDCTLRFlags_t flags);
|
||||
|
||||
/*
|
||||
* DisableGICD - top-level disable for GIC Distributor
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* flags - control flags to clear
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* ConfigGICD() will set an absolute flags value, whereas
|
||||
* {En,Dis}ableGICD() will only {set,clear} the flag bits
|
||||
* passed as a parameter
|
||||
*/
|
||||
void DisableGICD(GICDCTLRFlags_t flags);
|
||||
|
||||
/*
|
||||
* SyncAREinGICD - synchronise GICD Address Routing Enable bits
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* flags - absolute flag bits to set in GIC Distributor
|
||||
*
|
||||
* dosync - flag whether to wait for ARE bits to match passed
|
||||
* flag field (dosync = true), or whether to set absolute
|
||||
* flag bits (dosync = false)
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* This function is used to resolve a race in an MP system whereby secondary
|
||||
* CPUs cannot reliably program all Redistributor registers until the
|
||||
* primary CPU has enabled Address Routing. The primary CPU will call this
|
||||
* function with dosync = false, while the secondaries will call it with
|
||||
* dosync = true.
|
||||
*/
|
||||
void SyncAREinGICD(GICDCTLRFlags_t flags, uint32_t dosync);
|
||||
|
||||
/*
|
||||
* EnableSPI - enable a specific shared peripheral interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - which interrupt to enable
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void EnableSPI(uint32_t id);
|
||||
|
||||
/*
|
||||
* DisableSPI - disable a specific shared peripheral interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - which interrupt to disable
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void DisableSPI(uint32_t id);
|
||||
|
||||
/*
|
||||
* SetSPIPriority - configure the priority for a shared peripheral interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* priority - 8-bit priority to program (see note below)
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* The GICv3 architecture makes this function sensitive to the Security
|
||||
* context in terms of what effect it has on the programmed priority: no
|
||||
* attempt is made to adjust for the reduced priority range available
|
||||
* when making Non-Secure accesses to the GIC
|
||||
*/
|
||||
void SetSPIPriority(uint32_t id, uint32_t priority);
|
||||
|
||||
/*
|
||||
* GetSPIPriority - determine the priority for a shared peripheral interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* interrupt priority in the range 0 - 0xff
|
||||
*/
|
||||
uint32_t GetSPIPriority(uint32_t id);
|
||||
|
||||
/*
|
||||
* SetSPIRoute - specify interrupt routing when gicdctlr_ARE is enabled
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* affinity - prepacked "dotted quad" affinity routing. NOTE: use the
|
||||
* gicv3PackAffinity() helper routine to generate this input
|
||||
*
|
||||
* mode - select routing mode (specific affinity, or any recipient)
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPIRoute(uint32_t id, uint64_t affinity, GICDIROUTERBits_t mode);
|
||||
|
||||
/*
|
||||
* GetSPIRoute - read ARE-enabled interrupt routing information
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* routing configuration
|
||||
*/
|
||||
uint64_t GetSPIRoute(uint32_t id);
|
||||
|
||||
/*
|
||||
* SetSPITarget - configure the set of processor targets for an interrupt
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* target - 8-bit target bitmap
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPITarget(uint32_t id, uint32_t target);
|
||||
|
||||
/*
|
||||
* GetSPITarget - read the set of processor targets for an interrupt
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* 8-bit target bitmap
|
||||
*/
|
||||
uint32_t GetSPITarget(uint32_t id);
|
||||
|
||||
/*
|
||||
* ConfigureSPI - setup an interrupt as edge- or level-triggered
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* config - desired configuration
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void ConfigureSPI(uint32_t id, GICDICFGRBits_t config);
|
||||
|
||||
/*
|
||||
* SetSPIPending - mark an interrupt as pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPIPending(uint32_t id);
|
||||
|
||||
/*
|
||||
* ClearSPIPending - mark an interrupt as not pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void ClearSPIPending(uint32_t id);
|
||||
|
||||
/*
|
||||
* GetSPIPending - query whether an interrupt is pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* pending status
|
||||
*/
|
||||
uint32_t GetSPIPending(uint32_t id);
|
||||
|
||||
/*
|
||||
* SetSPISecurity - mark a shared peripheral interrupt as
|
||||
* security <group>
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - which interrupt to mark
|
||||
*
|
||||
* group - the group for the interrupt
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPISecurity(uint32_t id, GICIGROUPRBits_t group);
|
||||
|
||||
/*
|
||||
* SetSPISecurityBlock - mark a block of 32 shared peripheral
|
||||
* interrupts as security <group>
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* block - which block to mark (e.g. 1 = Ints 32-63)
|
||||
*
|
||||
* group - the group for the interrupts
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPISecurityBlock(uint32_t block, GICIGROUPRBits_t group);
|
||||
|
||||
/*
|
||||
* SetSPISecurityAll - mark all shared peripheral interrupts
|
||||
* as security <group>
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* group - the group for the interrupts
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPISecurityAll(GICIGROUPRBits_t group);
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* GIC Re-Distributor Function Prototypes
|
||||
*
|
||||
* The model for calling Redistributor functions is that, rather than
|
||||
* identifying the target redistributor with every function call, the
|
||||
* SelectRedistributor() function is used to identify which redistributor
|
||||
* is to be used for all functions until a different redistributor is
|
||||
* explicitly selected
|
||||
*/
|
||||
|
||||
/*
|
||||
* WakeupGICR - wake up a Redistributor
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to wakeup
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void WakeupGICR(uint32_t gicr);
|
||||
|
||||
/*
|
||||
* EnablePrivateInt - enable a private (SGI/PPI) interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - which interrupt to enable
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void EnablePrivateInt(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* DisablePrivateInt - disable a private (SGI/PPI) interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - which interrupt to disable
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void DisablePrivateInt(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* SetPrivateIntPriority - configure the priority for a private
|
||||
* (SGI/PPI) interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* priority - 8-bit priority to program (see note below)
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* The GICv3 architecture makes this function sensitive to the Security
|
||||
* context in terms of what effect it has on the programmed priority: no
|
||||
* attempt is made to adjust for the reduced priority range available
|
||||
* when making Non-Secure accesses to the GIC
|
||||
*/
|
||||
void SetPrivateIntPriority(uint32_t gicr, uint32_t id, uint32_t priority);
|
||||
|
||||
/*
|
||||
* GetPrivateIntPriority - configure the priority for a private
|
||||
* (SGI/PPI) interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Int priority
|
||||
*/
|
||||
uint32_t GetPrivateIntPriority(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* SetPrivateIntPending - mark a private (SGI/PPI) interrupt as pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetPrivateIntPending(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* ClearPrivateIntPending - mark a private (SGI/PPI) interrupt as not pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void ClearPrivateIntPending(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* GetPrivateIntPending - query whether a private (SGI/PPI) interrupt is pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* pending status
|
||||
*/
|
||||
uint32_t GetPrivateIntPending(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* SetPrivateIntSecurity - mark a private (SGI/PPI) interrupt as
|
||||
* security <group>
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - which interrupt to mark
|
||||
*
|
||||
* group - the group for the interrupt
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetPrivateIntSecurity(uint32_t gicr, uint32_t id, GICIGROUPRBits_t group);
|
||||
|
||||
/*
|
||||
* SetPrivateIntSecurityBlock - mark all 32 private (SGI/PPI)
|
||||
* interrupts as security <group>
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* group - the group for the interrupt
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetPrivateIntSecurityBlock(uint32_t gicr, GICIGROUPRBits_t group);
|
||||
|
||||
#endif /* ndef GICV3_h */
|
||||
|
||||
/* EOF GICv3.h */
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Aliases for GICv3 registers
|
||||
//
|
||||
// Copyright (c) 2016-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
#ifndef GICV3_ALIASES_H
|
||||
#define GICV3_ALIASES_H
|
||||
|
||||
#ifndef __clang__
|
||||
|
||||
/*
|
||||
* Mapping of MSR and MRS to physical and virtual CPU interface registers
|
||||
*
|
||||
* Arm Generic Interrupt Controller Architecture Specification
|
||||
* GIC architecture version 3.0 and version 4.0
|
||||
* Table 8-5
|
||||
*/
|
||||
#define ICC_AP0R0_EL1 S3_0_C12_C8_4
|
||||
#define ICC_AP0R1_EL1 S3_0_C12_C8_5
|
||||
#define ICC_AP0R2_EL1 S3_0_C12_C8_6
|
||||
#define ICC_AP0R3_EL1 S3_0_C12_C8_7
|
||||
|
||||
#define ICC_AP1R0_EL1 S3_0_C12_C9_0
|
||||
#define ICC_AP1R1_EL1 S3_0_C12_C9_1
|
||||
#define ICC_AP1R2_EL1 S3_0_C12_C9_2
|
||||
#define ICC_AP1R3_EL1 S3_0_C12_C9_3
|
||||
|
||||
#define ICC_ASGI1R_EL1 S3_0_C12_C11_6
|
||||
|
||||
#define ICC_BPR0_EL1 S3_0_C12_C8_3
|
||||
#define ICC_BPR1_EL1 S3_0_C12_C12_3
|
||||
|
||||
#define ICC_CTLR_EL1 S3_0_C12_C12_4
|
||||
#define ICC_CTLR_EL3 S3_6_C12_C12_4
|
||||
|
||||
#define ICC_DIR_EL1 S3_0_C12_C11_1
|
||||
|
||||
#define ICC_EOIR0_EL1 S3_0_C12_C8_1
|
||||
#define ICC_EOIR1_EL1 S3_0_C12_C12_1
|
||||
|
||||
#define ICC_HPPIR0_EL1 S3_0_C12_C8_2
|
||||
#define ICC_HPPIR1_EL1 S3_0_C12_C12_2
|
||||
|
||||
#define ICC_IAR0_EL1 S3_0_C12_C8_0
|
||||
#define ICC_IAR1_EL1 S3_0_C12_C12_0
|
||||
|
||||
#define ICC_IGRPEN0_EL1 S3_0_C12_C12_6
|
||||
#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7
|
||||
#define ICC_IGRPEN1_EL3 S3_6_C12_C12_7
|
||||
|
||||
#define ICC_PMR_EL1 S3_0_C4_C6_0
|
||||
#define ICC_RPR_EL1 S3_0_C12_C11_3
|
||||
|
||||
#define ICC_SGI0R_EL1 S3_0_C12_C11_7
|
||||
#define ICC_SGI1R_EL1 S3_0_C12_C11_5
|
||||
|
||||
#define ICC_SRE_EL1 S3_0_C12_C12_5
|
||||
#define ICC_SRE_EL2 S3_4_C12_C9_5
|
||||
#define ICC_SRE_EL3 S3_6_C12_C12_5
|
||||
|
||||
/*
|
||||
* Mapping of MSR and MRS to virtual interface control registers
|
||||
*
|
||||
* Arm Generic Interrupt Controller Architecture Specification
|
||||
* GIC architecture version 3.0 and version 4.0
|
||||
* Table 8-6
|
||||
*/
|
||||
#define ICH_AP0R0_EL2 S3_4_C12_C8_0
|
||||
#define ICH_AP0R1_EL2 S3_4_C12_C8_1
|
||||
#define ICH_AP0R2_EL2 S3_4_C12_C8_2
|
||||
#define ICH_AP0R3_EL2 S3_4_C12_C8_3
|
||||
|
||||
#define ICH_AP1R0_EL2 S3_4_C12_C9_0
|
||||
#define ICH_AP1R1_EL2 S3_4_C12_C9_1
|
||||
#define ICH_AP1R2_EL2 S3_4_C12_C9_2
|
||||
#define ICH_AP1R3_EL2 S3_4_C12_C9_3
|
||||
|
||||
#define ICH_HCR_EL2 S3_4_C12_C11_0
|
||||
|
||||
#define ICH_VTR_EL2 S3_4_C12_C11_1
|
||||
|
||||
#define ICH_MISR_EL2 S3_4_C12_C11_2
|
||||
|
||||
#define ICH_EISR_EL2 S3_4_C12_C11_3
|
||||
|
||||
#define ICH_ELRSR_EL2 S3_4_C12_C11_5
|
||||
|
||||
#define ICH_VMCR_EL2 S3_4_C12_C11_7
|
||||
|
||||
#define ICH_LR0_EL2 S3_4_C12_C12_0
|
||||
#define ICH_LR1_EL2 S3_4_C12_C12_1
|
||||
#define ICH_LR2_EL2 S3_4_C12_C12_2
|
||||
#define ICH_LR3_EL2 S3_4_C12_C12_3
|
||||
#define ICH_LR4_EL2 S3_4_C12_C12_4
|
||||
#define ICH_LR5_EL2 S3_4_C12_C12_5
|
||||
#define ICH_LR6_EL2 S3_4_C12_C12_6
|
||||
#define ICH_LR7_EL2 S3_4_C12_C12_7
|
||||
#define ICH_LR8_EL2 S3_4_C12_C13_0
|
||||
#define ICH_LR9_EL2 S3_4_C12_C13_1
|
||||
#define ICH_LR10_EL2 S3_4_C12_C13_2
|
||||
#define ICH_LR11_EL2 S3_4_C12_C13_3
|
||||
#define ICH_LR12_EL2 S3_4_C12_C13_4
|
||||
#define ICH_LR13_EL2 S3_4_C12_C13_5
|
||||
#define ICH_LR14_EL2 S3_4_C12_C13_6
|
||||
#define ICH_LR15_EL2 S3_4_C12_C13_7
|
||||
|
||||
#endif /* not __clang__ */
|
||||
|
||||
#endif /* GICV3_ALIASES */
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* GICv3_gicc.h - prototypes and inline functions for GICC system register operations
|
||||
*
|
||||
* Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#ifndef GICV3_gicc_h
|
||||
#define GICV3_gicc_h
|
||||
|
||||
#include "GICv3_aliases.h"
|
||||
|
||||
#define stringify_no_expansion(x) #x
|
||||
#define stringify(x) stringify_no_expansion(x)
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sreSRE = (1 << 0),
|
||||
sreDFB = (1 << 1),
|
||||
sreDIB = (1 << 2),
|
||||
sreEnable = (1 << 3)
|
||||
} ICC_SREBits_t;
|
||||
|
||||
static inline void setICC_SRE_EL1(ICC_SREBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_SRE_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_SRE_EL1(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_SRE_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline void setICC_SRE_EL2(ICC_SREBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_SRE_EL2)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_SRE_EL2(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_SRE_EL2)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline void setICC_SRE_EL3(ICC_SREBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_SRE_EL3)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_SRE_EL3(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_SRE_EL3)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
igrpEnable = (1 << 0),
|
||||
igrpEnableGrp1NS = (1 << 0),
|
||||
igrpEnableGrp1S = (1 << 2)
|
||||
} ICC_IGRPBits_t;
|
||||
|
||||
static inline void setICC_IGRPEN0_EL1(ICC_IGRPBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_IGRPEN0_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline void setICC_IGRPEN1_EL1(ICC_IGRPBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_IGRPEN1_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline void setICC_IGRPEN1_EL3(ICC_IGRPBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_IGRPEN1_EL3)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ctlrCBPR = (1 << 0),
|
||||
ctlrCBPR_EL1S = (1 << 0),
|
||||
ctlrEOImode = (1 << 1),
|
||||
ctlrCBPR_EL1NS = (1 << 1),
|
||||
ctlrEOImode_EL3 = (1 << 2),
|
||||
ctlrEOImode_EL1S = (1 << 3),
|
||||
ctlrEOImode_EL1NS = (1 << 4),
|
||||
ctlrRM = (1 << 5),
|
||||
ctlrPMHE = (1 << 6)
|
||||
} ICC_CTLRBits_t;
|
||||
|
||||
static inline void setICC_CTLR_EL1(ICC_CTLRBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_CTLR_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_CTLR_EL1(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_CTLR_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline void setICC_CTLR_EL3(ICC_CTLRBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_CTLR_EL3)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_CTLR_EL3(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_CTLR_EL3)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static inline uint64_t getICC_IAR0(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_IAR0_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_IAR1(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_IAR1_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline void setICC_EOIR0(uint32_t interrupt)
|
||||
{
|
||||
asm("msr "stringify(ICC_EOIR0_EL1)", %0\n; isb" :: "r" ((uint64_t)interrupt));
|
||||
}
|
||||
|
||||
static inline void setICC_EOIR1(uint32_t interrupt)
|
||||
{
|
||||
asm("msr "stringify(ICC_EOIR1_EL1)", %0\n; isb" :: "r" ((uint64_t)interrupt));
|
||||
}
|
||||
|
||||
static inline void setICC_DIR(uint32_t interrupt)
|
||||
{
|
||||
asm("msr "stringify(ICC_DIR_EL1)", %0\n; isb" :: "r" ((uint64_t)interrupt));
|
||||
}
|
||||
|
||||
static inline void setICC_PMR(uint32_t priority)
|
||||
{
|
||||
asm("msr "stringify(ICC_PMR_EL1)", %0\n; isb" :: "r" ((uint64_t)priority));
|
||||
}
|
||||
|
||||
static inline void setICC_BPR0(uint32_t binarypoint)
|
||||
{
|
||||
asm("msr "stringify(ICC_BPR0_EL1)", %0\n; isb" :: "r" ((uint64_t)binarypoint));
|
||||
}
|
||||
|
||||
static inline void setICC_BPR1(uint32_t binarypoint)
|
||||
{
|
||||
asm("msr "stringify(ICC_BPR1_EL1)", %0\n; isb" :: "r" ((uint64_t)binarypoint));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_BPR0(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_BPR0_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_BPR1(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_BPR1_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_RPR(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_RPR_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sgirIRMTarget = 0,
|
||||
sgirIRMAll = (1ull << 40)
|
||||
} ICC_SGIRBits_t;
|
||||
|
||||
static inline void setICC_SGI0R(uint8_t aff3, uint8_t aff2,
|
||||
uint8_t aff1, ICC_SGIRBits_t irm,
|
||||
uint16_t targetlist, uint8_t intid)
|
||||
{
|
||||
uint64_t packedbits = (((uint64_t)aff3 << 48) | ((uint64_t)aff2 << 32) | \
|
||||
((uint64_t)aff1 << 16) | irm | targetlist | \
|
||||
((uint64_t)(intid & 0x0f) << 24));
|
||||
|
||||
asm("msr "stringify(ICC_SGI0R_EL1)", %0\n; isb" :: "r" (packedbits));
|
||||
}
|
||||
|
||||
static inline void setICC_SGI1R(uint8_t aff3, uint8_t aff2,
|
||||
uint8_t aff1, ICC_SGIRBits_t irm,
|
||||
uint16_t targetlist, uint8_t intid)
|
||||
{
|
||||
uint64_t packedbits = (((uint64_t)aff3 << 48) | ((uint64_t)aff2 << 32) | \
|
||||
((uint64_t)aff1 << 16) | irm | targetlist | \
|
||||
((uint64_t)(intid & 0x0f) << 24));
|
||||
|
||||
asm("msr "stringify(ICC_SGI1R_EL1)", %0\n; isb" :: "r" (packedbits));
|
||||
}
|
||||
|
||||
static inline void setICC_ASGI1R(uint8_t aff3, uint8_t aff2,
|
||||
uint8_t aff1, ICC_SGIRBits_t irm,
|
||||
uint16_t targetlist, uint8_t intid)
|
||||
{
|
||||
uint64_t packedbits = (((uint64_t)aff3 << 48) | ((uint64_t)aff2 << 32) | \
|
||||
((uint64_t)aff1 << 16) | irm | targetlist | \
|
||||
((uint64_t)(intid & 0x0f) << 24));
|
||||
|
||||
asm("msr "stringify(ICC_ASGI1R_EL1)", %0\n; isb" :: "r" (packedbits));
|
||||
}
|
||||
|
||||
#endif /* ndef GICV3_gicc_h */
|
||||
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* GICv3_gicd.c - generic driver code for GICv3 distributor
|
||||
*
|
||||
* Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#include "GICv3.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t GICD_CTLR; // +0x0000
|
||||
const volatile uint32_t GICD_TYPER; // +0x0004
|
||||
const volatile uint32_t GICD_IIDR; // +0x0008
|
||||
|
||||
const volatile uint32_t padding0; // +0x000c
|
||||
|
||||
volatile uint32_t GICD_STATUSR; // +0x0010
|
||||
|
||||
const volatile uint32_t padding1[3]; // +0x0014
|
||||
|
||||
volatile uint32_t IMP_DEF[8]; // +0x0020
|
||||
|
||||
volatile uint32_t GICD_SETSPI_NSR; // +0x0040
|
||||
const volatile uint32_t padding2; // +0x0044
|
||||
volatile uint32_t GICD_CLRSPI_NSR; // +0x0048
|
||||
const volatile uint32_t padding3; // +0x004c
|
||||
volatile uint32_t GICD_SETSPI_SR; // +0x0050
|
||||
const volatile uint32_t padding4; // +0x0054
|
||||
volatile uint32_t GICD_CLRSPI_SR; // +0x0058
|
||||
|
||||
const volatile uint32_t padding5[3]; // +0x005c
|
||||
|
||||
volatile uint32_t GICD_SEIR; // +0x0068
|
||||
|
||||
const volatile uint32_t padding6[5]; // +0x006c
|
||||
|
||||
volatile uint32_t GICD_IGROUPR[32]; // +0x0080
|
||||
|
||||
volatile uint32_t GICD_ISENABLER[32]; // +0x0100
|
||||
volatile uint32_t GICD_ICENABLER[32]; // +0x0180
|
||||
volatile uint32_t GICD_ISPENDR[32]; // +0x0200
|
||||
volatile uint32_t GICD_ICPENDR[32]; // +0x0280
|
||||
volatile uint32_t GICD_ISACTIVER[32]; // +0x0300
|
||||
volatile uint32_t GICD_ICACTIVER[32]; // +0x0380
|
||||
|
||||
volatile uint8_t GICD_IPRIORITYR[1024]; // +0x0400
|
||||
volatile uint8_t GICD_ITARGETSR[1024]; // +0x0800
|
||||
volatile uint32_t GICD_ICFGR[64]; // +0x0c00
|
||||
volatile uint32_t GICD_IGRPMODR[32]; // +0x0d00
|
||||
const volatile uint32_t padding7[32]; // +0x0d80
|
||||
volatile uint32_t GICD_NSACR[64]; // +0x0e00
|
||||
|
||||
volatile uint32_t GICD_SGIR; // +0x0f00
|
||||
|
||||
const volatile uint32_t padding8[3]; // +0x0f04
|
||||
|
||||
volatile uint32_t GICD_CPENDSGIR[4]; // +0x0f10
|
||||
volatile uint32_t GICD_SPENDSGIR[4]; // +0x0f20
|
||||
|
||||
const volatile uint32_t padding9[52]; // +0x0f30
|
||||
const volatile uint32_t padding10[5120]; // +0x1000
|
||||
|
||||
volatile uint64_t GICD_IROUTER[1024]; // +0x6000
|
||||
} GICv3_distributor;
|
||||
|
||||
/*
|
||||
* use the scatter file to place GICD
|
||||
*/
|
||||
static GICv3_distributor __attribute__((section(".bss.distributor"))) gicd;
|
||||
|
||||
void ConfigGICD(GICDCTLRFlags_t flags)
|
||||
{
|
||||
gicd.GICD_CTLR = flags;
|
||||
}
|
||||
|
||||
void EnableGICD(GICDCTLRFlags_t flags)
|
||||
{
|
||||
gicd.GICD_CTLR |= flags;
|
||||
}
|
||||
|
||||
void DisableGICD(GICDCTLRFlags_t flags)
|
||||
{
|
||||
gicd.GICD_CTLR &= ~flags;
|
||||
}
|
||||
|
||||
void SyncAREinGICD(GICDCTLRFlags_t flags, uint32_t dosync)
|
||||
{
|
||||
if (dosync)
|
||||
{
|
||||
const uint32_t tmask = gicdctlr_ARE_S | gicdctlr_ARE_NS;
|
||||
const uint32_t tval = flags & tmask;
|
||||
|
||||
while ((gicd.GICD_CTLR & tmask) != tval)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
gicd.GICD_CTLR = flags;
|
||||
}
|
||||
|
||||
void EnableSPI(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ISENABLER has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ISENABLER);
|
||||
id &= 32 - 1;
|
||||
|
||||
gicd.GICD_ISENABLER[bank] = 1 << id;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DisableSPI(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ISENABLER has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ICENABLER);
|
||||
id &= 32 - 1;
|
||||
|
||||
gicd.GICD_ICENABLER[bank] = 1 << id;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void SetSPIPriority(uint32_t id, uint32_t priority)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_IPRIORITYR has one byte-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_IPRIORITYR);
|
||||
|
||||
gicd.GICD_IPRIORITYR[bank] = priority;
|
||||
}
|
||||
|
||||
uint32_t GetSPIPriority(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_IPRIORITYR has one byte-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_IPRIORITYR);
|
||||
|
||||
return (uint32_t)(gicd.GICD_IPRIORITYR[bank]);
|
||||
}
|
||||
|
||||
void SetSPIRoute(uint32_t id, uint64_t affinity, GICDIROUTERBits_t mode)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_IROUTER has one doubleword-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_IROUTER);
|
||||
|
||||
gicd.GICD_IROUTER[bank] = affinity | (uint64_t)mode;
|
||||
}
|
||||
|
||||
uint64_t GetSPIRoute(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_IROUTER has one doubleword-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_IROUTER);
|
||||
|
||||
return gicd.GICD_IROUTER[bank];
|
||||
}
|
||||
|
||||
void SetSPITarget(uint32_t id, uint32_t target)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ITARGETSR has one byte-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_ITARGETSR);
|
||||
|
||||
gicd.GICD_ITARGETSR[bank] = target;
|
||||
}
|
||||
|
||||
uint32_t GetSPITarget(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ITARGETSR has one byte-wide entry per interrupt
|
||||
*/
|
||||
/*
|
||||
* GICD_ITARGETSR has 4 interrupts per register, i.e. 8-bits of
|
||||
* target bitmap per register
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_ITARGETSR);
|
||||
|
||||
return (uint32_t)(gicd.GICD_ITARGETSR[bank]);
|
||||
}
|
||||
|
||||
void ConfigureSPI(uint32_t id, GICDICFGRBits_t config)
|
||||
{
|
||||
uint32_t bank, tmp;
|
||||
|
||||
/*
|
||||
* GICD_ICFGR has 16 interrupts per register, i.e. 2-bits of
|
||||
* configuration per register
|
||||
*/
|
||||
bank = (id >> 4) & RANGE_LIMIT(gicd.GICD_ICFGR);
|
||||
config &= 3;
|
||||
|
||||
id = (id & 0xf) << 1;
|
||||
|
||||
tmp = gicd.GICD_ICFGR[bank];
|
||||
tmp &= ~(3 << id);
|
||||
tmp |= config << id;
|
||||
gicd.GICD_ICFGR[bank] = tmp;
|
||||
}
|
||||
|
||||
void SetSPIPending(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ISPENDR has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ISPENDR);
|
||||
id &= 0x1f;
|
||||
|
||||
gicd.GICD_ISPENDR[bank] = 1 << id;
|
||||
}
|
||||
|
||||
void ClearSPIPending(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ICPENDR has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ICPENDR);
|
||||
id &= 0x1f;
|
||||
|
||||
gicd.GICD_ICPENDR[bank] = 1 << id;
|
||||
}
|
||||
|
||||
uint32_t GetSPIPending(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ICPENDR has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ICPENDR);
|
||||
id &= 0x1f;
|
||||
|
||||
return (gicd.GICD_ICPENDR[bank] >> id) & 1;
|
||||
}
|
||||
|
||||
void SetSPISecurity(uint32_t id, GICIGROUPRBits_t group)
|
||||
{
|
||||
uint32_t bank, groupmod;
|
||||
|
||||
/*
|
||||
* GICD_IGROUPR has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_IGROUPR);
|
||||
id &= 0x1f;
|
||||
|
||||
/*
|
||||
* the single group argument is split into two separate
|
||||
* registers, so filter out and remove the (new to gicv3)
|
||||
* group modifier bit
|
||||
*/
|
||||
groupmod = (group >> 1) & 1;
|
||||
group &= 1;
|
||||
|
||||
/*
|
||||
* either set or clear the Group bit for the interrupt as appropriate
|
||||
*/
|
||||
if (group)
|
||||
gicd.GICD_IGROUPR[bank] |= 1 << id;
|
||||
else
|
||||
gicd.GICD_IGROUPR[bank] &= ~(1 << id);
|
||||
|
||||
/*
|
||||
* now deal with groupmod
|
||||
*/
|
||||
if (groupmod)
|
||||
gicd.GICD_IGRPMODR[bank] |= 1 << id;
|
||||
else
|
||||
gicd.GICD_IGRPMODR[bank] &= ~(1 << id);
|
||||
}
|
||||
|
||||
void SetSPISecurityBlock(uint32_t block, GICIGROUPRBits_t group)
|
||||
{
|
||||
uint32_t groupmod;
|
||||
const uint32_t nbits = (sizeof group * 8) - 1;
|
||||
|
||||
/*
|
||||
* GICD_IGROUPR has 32 interrupts per register
|
||||
*/
|
||||
block &= RANGE_LIMIT(gicd.GICD_IGROUPR);
|
||||
|
||||
/*
|
||||
* get each bit of group config duplicated over all 32-bits in a word
|
||||
*/
|
||||
groupmod = (uint32_t)(((int32_t)group << (nbits - 1)) >> 31);
|
||||
group = (uint32_t)(((int32_t)group << nbits) >> 31);
|
||||
|
||||
/*
|
||||
* set the security state for this block of SPIs
|
||||
*/
|
||||
gicd.GICD_IGROUPR[block] = group;
|
||||
gicd.GICD_IGRPMODR[block] = groupmod;
|
||||
}
|
||||
|
||||
void SetSPISecurityAll(GICIGROUPRBits_t group)
|
||||
{
|
||||
uint32_t block;
|
||||
|
||||
/*
|
||||
* GICD_TYPER.ITLinesNumber gives (No. SPIS / 32) - 1, and we
|
||||
* want to iterate over all blocks excluding 0 (which are the
|
||||
* SGI/PPI interrupts, and not relevant here)
|
||||
*/
|
||||
for (block = (gicd.GICD_TYPER & ((1 << 5) - 1)); block > 0; --block)
|
||||
SetSPISecurityBlock(block, group);
|
||||
}
|
||||
|
||||
/* EOF GICv3_gicd.c */
|
||||
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* GICv3_gicr.c - generic driver code for GICv3 redistributor
|
||||
*
|
||||
* Copyright (c) 2014-2019 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#include "GICv3.h"
|
||||
|
||||
/*
|
||||
* physical LPI Redistributor register map
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t GICR_CTLR; // +0x0000 - RW - Redistributor Control Register
|
||||
const volatile uint32_t GICR_IIDR; // +0x0004 - RO - Implementer Identification Register
|
||||
const volatile uint32_t GICR_TYPER[2]; // +0x0008 - RO - Redistributor Type Register
|
||||
volatile uint32_t GICR_STATUSR; // +0x0010 - RW - Error Reporting Status Register, optional
|
||||
volatile uint32_t GICR_WAKER; // +0x0014 - RW - Redistributor Wake Register
|
||||
const volatile uint32_t padding1[2]; // +0x0018 - RESERVED
|
||||
#ifndef USE_GIC600
|
||||
volatile uint32_t IMPDEF1[8]; // +0x0020 - ?? - IMPLEMENTATION DEFINED
|
||||
#else
|
||||
volatile uint32_t GICR_FCTLR; // +0x0020 - RW - Function Control Register
|
||||
volatile uint32_t GICR_PWRR; // +0x0024 - RW - Power Management Control Register
|
||||
volatile uint32_t GICR_CLASS; // +0x0028 - RW - Class Register
|
||||
const volatile uint32_t padding2[5]; // +0x002C - RESERVED
|
||||
#endif
|
||||
volatile uint64_t GICR_SETLPIR; // +0x0040 - WO - Set LPI Pending Register
|
||||
volatile uint64_t GICR_CLRLPIR; // +0x0048 - WO - Clear LPI Pending Register
|
||||
const volatile uint32_t padding3[8]; // +0x0050 - RESERVED
|
||||
volatile uint64_t GICR_PROPBASER; // +0x0070 - RW - Redistributor Properties Base Address Register
|
||||
volatile uint64_t GICR_PENDBASER; // +0x0078 - RW - Redistributor LPI Pending Table Base Address Register
|
||||
const volatile uint32_t padding4[8]; // +0x0080 - RESERVED
|
||||
volatile uint64_t GICR_INVLPIR; // +0x00A0 - WO - Redistributor Invalidate LPI Register
|
||||
const volatile uint32_t padding5[2]; // +0x00A8 - RESERVED
|
||||
volatile uint64_t GICR_INVALLR; // +0x00B0 - WO - Redistributor Invalidate All Register
|
||||
const volatile uint32_t padding6[2]; // +0x00B8 - RESERVED
|
||||
volatile uint64_t GICR_SYNCR; // +0x00C0 - RO - Redistributor Synchronize Register
|
||||
const volatile uint32_t padding7[2]; // +0x00C8 - RESERVED
|
||||
const volatile uint32_t padding8[12]; // +0x00D0 - RESERVED
|
||||
volatile uint64_t IMPDEF2; // +0x0100 - WO - IMPLEMENTATION DEFINED
|
||||
const volatile uint32_t padding9[2]; // +0x0108 - RESERVED
|
||||
volatile uint64_t IMPDEF3; // +0x0110 - WO - IMPLEMENTATION DEFINED
|
||||
const volatile uint32_t padding10[2]; // +0x0118 - RESERVED
|
||||
} GICv3_redistributor_RD;
|
||||
|
||||
/*
|
||||
* SGI and PPI Redistributor register map
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const volatile uint32_t padding1[32]; // +0x0000 - RESERVED
|
||||
volatile uint32_t GICR_IGROUPR0; // +0x0080 - RW - Interrupt Group Registers (Security Registers in GICv1)
|
||||
const volatile uint32_t padding2[31]; // +0x0084 - RESERVED
|
||||
volatile uint32_t GICR_ISENABLER; // +0x0100 - RW - Interrupt Set-Enable Registers
|
||||
const volatile uint32_t padding3[31]; // +0x0104 - RESERVED
|
||||
volatile uint32_t GICR_ICENABLER; // +0x0180 - RW - Interrupt Clear-Enable Registers
|
||||
const volatile uint32_t padding4[31]; // +0x0184 - RESERVED
|
||||
volatile uint32_t GICR_ISPENDR; // +0x0200 - RW - Interrupt Set-Pending Registers
|
||||
const volatile uint32_t padding5[31]; // +0x0204 - RESERVED
|
||||
volatile uint32_t GICR_ICPENDR; // +0x0280 - RW - Interrupt Clear-Pending Registers
|
||||
const volatile uint32_t padding6[31]; // +0x0284 - RESERVED
|
||||
volatile uint32_t GICR_ISACTIVER; // +0x0300 - RW - Interrupt Set-Active Register
|
||||
const volatile uint32_t padding7[31]; // +0x0304 - RESERVED
|
||||
volatile uint32_t GICR_ICACTIVER; // +0x0380 - RW - Interrupt Clear-Active Register
|
||||
const volatile uint32_t padding8[31]; // +0x0184 - RESERVED
|
||||
volatile uint8_t GICR_IPRIORITYR[32]; // +0x0400 - RW - Interrupt Priority Registers
|
||||
const volatile uint32_t padding9[504]; // +0x0420 - RESERVED
|
||||
volatile uint32_t GICR_ICnoFGR[2]; // +0x0C00 - RW - Interrupt Configuration Registers
|
||||
const volatile uint32_t padding10[62]; // +0x0C08 - RESERVED
|
||||
volatile uint32_t GICR_IGRPMODR0; // +0x0D00 - RW - ????
|
||||
const volatile uint32_t padding11[63]; // +0x0D04 - RESERVED
|
||||
volatile uint32_t GICR_NSACR; // +0x0E00 - RW - Non-Secure Access Control Register
|
||||
} GICv3_redistributor_SGI;
|
||||
|
||||
/*
|
||||
* We have a multiplicity of GIC Redistributors; on the GIC-AEM and
|
||||
* GIC-500 they are arranged as one 128KB region per redistributor: one
|
||||
* 64KB page of GICR LPI registers, and one 64KB page of GICR Private
|
||||
* Int registers
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
GICv3_redistributor_RD RD_base;
|
||||
uint8_t padding[64 * 1024];
|
||||
} RDblock;
|
||||
|
||||
union
|
||||
{
|
||||
GICv3_redistributor_SGI SGI_base;
|
||||
uint8_t padding[64 * 1024];
|
||||
} SGIblock;
|
||||
} GICv3_GICR;
|
||||
|
||||
/*
|
||||
* use the scatter file to place GIC Redistributor base address
|
||||
*
|
||||
* although this code doesn't know how many Redistributor banks
|
||||
* a particular system will have, we declare gicrbase as an array
|
||||
* to avoid unwanted compiler optimisations when calculating the
|
||||
* base of a particular Redistributor bank
|
||||
*/
|
||||
static const GICv3_GICR gicrbase[2] __attribute__((section (".bss.redistributor")));
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* utility functions to calculate base of a particular
|
||||
* Redistributor bank
|
||||
*/
|
||||
|
||||
static inline GICv3_redistributor_RD *const getgicrRD(uint32_t gicr)
|
||||
{
|
||||
GICv3_GICR *const arraybase = (GICv3_GICR *const)&gicrbase;
|
||||
|
||||
return &((arraybase + gicr)->RDblock.RD_base);
|
||||
}
|
||||
|
||||
static inline GICv3_redistributor_SGI *const getgicrSGI(uint32_t gicr)
|
||||
{
|
||||
GICv3_GICR *arraybase = (GICv3_GICR *)(&gicrbase);
|
||||
|
||||
return &(arraybase[gicr].SGIblock.SGI_base);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
// This function walks a block of RDs to find one with the matching affinity
|
||||
uint32_t GetGICR(uint32_t affinity)
|
||||
{
|
||||
GICv3_redistributor_RD* gicr;
|
||||
uint32_t index = 0;
|
||||
|
||||
do
|
||||
{
|
||||
gicr = getgicrRD(index);
|
||||
if (gicr->GICR_TYPER[1] == affinity)
|
||||
return index;
|
||||
|
||||
index++;
|
||||
}
|
||||
while((gicr->GICR_TYPER[0] & (1<<4)) == 0); // Keep looking until GICR_TYPER.Last reports no more RDs in block
|
||||
|
||||
return 0xFFFFFFFF; // return -1 to signal not RD found
|
||||
}
|
||||
|
||||
void WakeupGICR(uint32_t gicr)
|
||||
{
|
||||
GICv3_redistributor_RD *const gicrRD = getgicrRD(gicr);
|
||||
#ifdef USE_GIC600
|
||||
//Power up Re-distributor for GIC-600
|
||||
gicrRD->GICR_PWRR = 0x2;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* step 1 - ensure GICR_WAKER.ProcessorSleep is off
|
||||
*/
|
||||
gicrRD->GICR_WAKER &= ~gicrwaker_ProcessorSleep;
|
||||
|
||||
/*
|
||||
* step 2 - wait for children asleep to be cleared
|
||||
*/
|
||||
while ((gicrRD->GICR_WAKER & gicrwaker_ChildrenAsleep) != 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* OK, GICR is go
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
void EnablePrivateInt(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
id &= 0x1f;
|
||||
|
||||
gicrSGI->GICR_ISENABLER = 1 << id;
|
||||
}
|
||||
|
||||
void DisablePrivateInt(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
id &= 0x1f;
|
||||
|
||||
gicrSGI->GICR_ICENABLER = 1 << id;
|
||||
}
|
||||
|
||||
void SetPrivateIntPriority(uint32_t gicr, uint32_t id, uint32_t priority)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICD_IPRIORITYR has one byte-wide entry per interrupt
|
||||
*/
|
||||
id &= RANGE_LIMIT(gicrSGI->GICR_IPRIORITYR);
|
||||
|
||||
gicrSGI->GICR_IPRIORITYR[id] = priority;
|
||||
}
|
||||
|
||||
uint32_t GetPrivateIntPriority(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICD_IPRIORITYR has one byte-wide entry per interrupt
|
||||
*/
|
||||
id &= RANGE_LIMIT(gicrSGI->GICR_IPRIORITYR);
|
||||
|
||||
return (uint32_t)(gicrSGI->GICR_IPRIORITYR[id]);
|
||||
}
|
||||
|
||||
void SetPrivateIntPending(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICR_ISPENDR is one 32-bit register
|
||||
*/
|
||||
id &= 0x1f;
|
||||
|
||||
gicrSGI->GICR_ISPENDR = 1 << id;
|
||||
}
|
||||
|
||||
void ClearPrivateIntPending(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICR_ICPENDR is one 32-bit register
|
||||
*/
|
||||
id &= 0x1f;
|
||||
|
||||
gicrSGI->GICR_ICPENDR = 1 << id;
|
||||
}
|
||||
|
||||
uint32_t GetPrivateIntPending(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICR_ISPENDR is one 32-bit register
|
||||
*/
|
||||
id &= 0x1f;
|
||||
|
||||
return (gicrSGI->GICR_ISPENDR >> id) & 0x01;
|
||||
}
|
||||
|
||||
void SetPrivateIntSecurity(uint32_t gicr, uint32_t id, GICIGROUPRBits_t group)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
uint32_t groupmod;
|
||||
|
||||
/*
|
||||
* GICR_IGROUPR0 is one 32-bit register
|
||||
*/
|
||||
id &= 0x1f;
|
||||
|
||||
/*
|
||||
* the single group argument is split into two separate
|
||||
* registers, so filter out and remove the (new to gicv3)
|
||||
* group modifier bit
|
||||
*/
|
||||
groupmod = (group >> 1) & 1;
|
||||
group &= 1;
|
||||
|
||||
/*
|
||||
* either set or clear the Group bit for the interrupt as appropriate
|
||||
*/
|
||||
if (group)
|
||||
gicrSGI->GICR_IGROUPR0 |= 1 << id;
|
||||
else
|
||||
gicrSGI->GICR_IGROUPR0 &= ~(1 << id);
|
||||
|
||||
/*
|
||||
* now deal with groupmod
|
||||
*/
|
||||
if (groupmod)
|
||||
gicrSGI->GICR_IGRPMODR0 |= 1 << id;
|
||||
else
|
||||
gicrSGI->GICR_IGRPMODR0 &= ~(1 << id);
|
||||
}
|
||||
|
||||
void SetPrivateIntSecurityBlock(uint32_t gicr, GICIGROUPRBits_t group)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
const uint32_t nbits = (sizeof group * 8) - 1;
|
||||
uint32_t groupmod;
|
||||
|
||||
/*
|
||||
* get each bit of group config duplicated over all 32-bits
|
||||
*/
|
||||
groupmod = (uint32_t)(((int32_t)group << (nbits - 1)) >> 31);
|
||||
group = (uint32_t)(((int32_t)group << nbits) >> 31);
|
||||
|
||||
/*
|
||||
* set the security state for this block of SPIs
|
||||
*/
|
||||
gicrSGI->GICR_IGROUPR0 = group;
|
||||
gicrSGI->GICR_IGRPMODR0 = groupmod;
|
||||
}
|
||||
|
||||
/* EOF GICv3_gicr.c */
|
||||
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// Armv8-A AArch64 - Basic Mutex Example
|
||||
// Includes the option (USE_LSE_ATOMIC) to use Large System Extension (LSE) atomics introduced in Armv8.1-A
|
||||
//
|
||||
// Copyright (c) 2012-2019 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
|
||||
.text
|
||||
.cfi_sections .debug_frame // put stack frame info into .debug_frame instead of .eh_frame
|
||||
|
||||
|
||||
.global _mutex_initialize
|
||||
.global _mutex_acquire
|
||||
.global _mutex_release
|
||||
|
||||
//
|
||||
// These routines implement the mutex management functions required for running
|
||||
// the Arm C library in a multi-threaded environment.
|
||||
//
|
||||
// They use a value of 0 to represent an unlocked mutex, and 1 for a locked mutex
|
||||
//
|
||||
// **********************************************************************
|
||||
//
|
||||
|
||||
.type _mutex_initialize, "function"
|
||||
.cfi_startproc
|
||||
_mutex_initialize:
|
||||
|
||||
//
|
||||
// mark the mutex as unlocked
|
||||
//
|
||||
mov w1, #0
|
||||
str w1, [x0]
|
||||
|
||||
//
|
||||
// we are running multi-threaded, so set a non-zero return
|
||||
// value (function prototype says use 1)
|
||||
//
|
||||
mov w0, #1
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
#if !defined(USE_LSE_ATOMIC)
|
||||
|
||||
.type _mutex_acquire, "function"
|
||||
.cfi_startproc
|
||||
_mutex_acquire:
|
||||
|
||||
//
|
||||
// send ourselves an event, so we don't stick on the wfe at the
|
||||
// top of the loop
|
||||
//
|
||||
sevl
|
||||
|
||||
//
|
||||
// wait until the mutex is available
|
||||
//
|
||||
loop:
|
||||
wfe
|
||||
ldaxr w1, [x0]
|
||||
cbnz w1, loop
|
||||
|
||||
//
|
||||
// mutex is (at least, it was) available - try to claim it
|
||||
//
|
||||
mov w1, #1
|
||||
stxr w2, w1, [x0]
|
||||
cbnz w2, loop
|
||||
|
||||
//
|
||||
// OK, we have the mutex, our work is done here
|
||||
//
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
.type _mutex_release, "function"
|
||||
.cfi_startproc
|
||||
_mutex_release:
|
||||
|
||||
mov w1, #0
|
||||
stlr w1, [x0]
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
#else // LSE version
|
||||
|
||||
.type _mutex_acquire, "function"
|
||||
.cfi_startproc
|
||||
_mutex_acquire:
|
||||
// This uses a "ticket lock". The lock is stored as a 32-bit value:
|
||||
// - the upper 16-bits record the thread's ticket number ("take a ticket")
|
||||
// - the lower 16-bits record the ticket being served ("now serving")
|
||||
|
||||
// atomically load then increment the thread's ticket number ("take a ticket")
|
||||
mov w3, #(1 << 16)
|
||||
ldadda w3, w1, [x0]
|
||||
|
||||
// is the ticket now being served?
|
||||
eor w2, w1, w1, ror #16
|
||||
cbz w2, loop_exit
|
||||
|
||||
// no, so wait for the ticket to be served
|
||||
|
||||
// send a local event to avoid missing an unlock before the exclusive load
|
||||
sevl
|
||||
|
||||
loop:
|
||||
wfe
|
||||
ldaxrh w3, [x0]
|
||||
eor w2, w3, w1, lsr #16
|
||||
cbnz w2, loop
|
||||
|
||||
//
|
||||
// OK, we have the mutex, our work is done here
|
||||
//
|
||||
loop_exit:
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
.type _mutex_release, "function"
|
||||
.cfi_startproc
|
||||
_mutex_release:
|
||||
mov w1, #1
|
||||
staddlh w1, [x0]
|
||||
ret
|
||||
.cfi_endproc
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Armv8-A AArch64 - Basic Mutex Example
|
||||
*
|
||||
* Copyright (c) 2012-2014 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#ifndef MP_MUTEX_H
|
||||
#define MP_MUTEX_H
|
||||
|
||||
/*
|
||||
* The Arm C library calls-out to these functions to manage multithreading.
|
||||
* They can also be called by user application code.
|
||||
*
|
||||
* Mutex type is specified by the Arm C library
|
||||
*
|
||||
* Declare function prototypes for libc mutex routines
|
||||
*/
|
||||
typedef signed int *mutex;
|
||||
|
||||
/*
|
||||
* int _mutex_initialize(mutex *m)
|
||||
*
|
||||
* Inputs
|
||||
* mutex *m - pointer to the 32-bit word associated with the mutex
|
||||
*
|
||||
* Returns
|
||||
* 0 - application is non-threaded
|
||||
* 1 - application is threaded
|
||||
* The C library uses the return result to indicate whether it is being used in a multithreaded environment.
|
||||
*/
|
||||
int _mutex_initialize(mutex *m);
|
||||
|
||||
/*
|
||||
* void _mutex_acquire(mutex *m)
|
||||
*
|
||||
* Inputs
|
||||
* mutex *m - pointer to the 32-bit word associated with the mutex
|
||||
*
|
||||
* Returns
|
||||
* <nothing>
|
||||
*
|
||||
* Side Effects
|
||||
* Routine does not return until the mutex has been claimed. A load-acquire
|
||||
* is used to guarantee that the mutex claim is properly ordered with
|
||||
* respect to any accesses to the resource protected by the mutex
|
||||
*/
|
||||
void _mutex_acquire(mutex *m);
|
||||
|
||||
/*
|
||||
* void _mutex_release(mutex *m)
|
||||
*
|
||||
* Inputs
|
||||
* mutex *m - pointer to the 32-bit word associated with the mutex
|
||||
*
|
||||
* Returns
|
||||
* <nothing>
|
||||
*
|
||||
* Side Effects
|
||||
* A store-release is used to guarantee that the mutex release is properly
|
||||
* ordered with respect any accesses to the resource protected by the mutex
|
||||
*/
|
||||
void _mutex_release(mutex *m);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// Private Peripheral Map for the v8 Architecture Envelope Model
|
||||
//
|
||||
// Copyright (c) 2012-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
#ifndef PPM_AEM_H
|
||||
#define PPM_AEM_H
|
||||
|
||||
//
|
||||
// Distributor layout
|
||||
//
|
||||
#define GICD_CTLR 0x0000
|
||||
#define GICD_TYPER 0x0004
|
||||
#define GICD_IIDR 0x0008
|
||||
#define GICD_IGROUP 0x0080
|
||||
#define GICD_ISENABLE 0x0100
|
||||
#define GICD_ICENABLE 0x0180
|
||||
#define GICD_ISPEND 0x0200
|
||||
#define GICD_ICPEND 0x0280
|
||||
#define GICD_ISACTIVE 0x0300
|
||||
#define GICD_ICACTIVE 0x0380
|
||||
#define GICD_IPRIORITY 0x0400
|
||||
#define GICD_ITARGETS 0x0800
|
||||
#define GICD_ICFG 0x0c00
|
||||
#define GICD_PPISR 0x0d00
|
||||
#define GICD_SPISR 0x0d04
|
||||
#define GICD_SGIR 0x0f00
|
||||
#define GICD_CPENDSGI 0x0f10
|
||||
#define GICD_SPENDSGI 0x0f20
|
||||
#define GICD_PIDR4 0x0fd0
|
||||
#define GICD_PIDR5 0x0fd4
|
||||
#define GICD_PIDR6 0x0fd8
|
||||
#define GICD_PIDR7 0x0fdc
|
||||
#define GICD_PIDR0 0x0fe0
|
||||
#define GICD_PIDR1 0x0fe4
|
||||
#define GICD_PIDR2 0x0fe8
|
||||
#define GICD_PIDR3 0x0fec
|
||||
#define GICD_CIDR0 0x0ff0
|
||||
#define GICD_CIDR1 0x0ff4
|
||||
#define GICD_CIDR2 0x0ff8
|
||||
#define GICD_CIDR3 0x0ffc
|
||||
|
||||
//
|
||||
// CPU Interface layout
|
||||
//
|
||||
#define GICC_CTLR 0x0000
|
||||
#define GICC_PMR 0x0004
|
||||
#define GICC_BPR 0x0008
|
||||
#define GICC_IAR 0x000c
|
||||
#define GICC_EOIR 0x0010
|
||||
#define GICC_RPR 0x0014
|
||||
#define GICC_HPPIR 0x0018
|
||||
#define GICC_ABPR 0x001c
|
||||
#define GICC_AIAR 0x0020
|
||||
#define GICC_AEOIR 0x0024
|
||||
#define GICC_AHPPIR 0x0028
|
||||
#define GICC_APR0 0x00d0
|
||||
#define GICC_NSAPR0 0x00e0
|
||||
#define GICC_IIDR 0x00fc
|
||||
#define GICC_DIR 0x1000
|
||||
|
||||
#endif // PPM_AEM_H
|
||||
@@ -0,0 +1,325 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="com.arm.debugger.launcher2">
|
||||
<stringAttribute key="ANDROID_ACTIVITY_NAME" value=""/>
|
||||
<stringAttribute key="ANDROID_APPLICATION" value=""/>
|
||||
<stringAttribute key="ANDROID_APP_DIR" value=""/>
|
||||
<stringAttribute key="ANDROID_PROCESS_NAME" value=""/>
|
||||
<mapAttribute key="AverageDurationTracker">
|
||||
<mapEntry key="*Fetching Data Model" value="2164664"/>
|
||||
<mapEntry key="*list global low level symbols" value="1257028"/>
|
||||
<mapEntry key="*loading memory from target" value="820184"/>
|
||||
<mapEntry key="*loading values from target" value="17587201"/>
|
||||
<mapEntry key="*trace" value="71991640"/>
|
||||
<mapEntry key="*updating expressions" value="65540292"/>
|
||||
<mapEntry key="*updating registers" value="44165495"/>
|
||||
<mapEntry key="*updating variables" value="8591428"/>
|
||||
<mapEntry key="Add Watchpoint" value="24597988"/>
|
||||
<mapEntry key="AddEventObserver" value="3303997"/>
|
||||
<mapEntry key="Evaluate" value="9741530"/>
|
||||
<mapEntry key="GlobalsLoaderCommand" value="154351059"/>
|
||||
<mapEntry key="areCachesAvailable" value="1362117"/>
|
||||
<mapEntry key="backtrace" value="5112231"/>
|
||||
<mapEntry key="break" value="2857608"/>
|
||||
<mapEntry key="checking tracepoints" value="181653"/>
|
||||
<mapEntry key="compute execution mode" value="2388424"/>
|
||||
<mapEntry key="continue" value="17295461"/>
|
||||
<mapEntry key="core" value="3940900"/>
|
||||
<mapEntry key="directory" value="3642355"/>
|
||||
<mapEntry key="disable" value="1478680"/>
|
||||
<mapEntry key="disassemble" value="73653580"/>
|
||||
<mapEntry key="enable" value="1860234"/>
|
||||
<mapEntry key="evaluate" value="2783965"/>
|
||||
<mapEntry key="evaluate address" value="17239727"/>
|
||||
<mapEntry key="get byte order" value="472733"/>
|
||||
<mapEntry key="get capabilities" value="277384"/>
|
||||
<mapEntry key="get execution addresss" value="803429"/>
|
||||
<mapEntry key="get source lines" value="8797728"/>
|
||||
<mapEntry key="get substitute paths" value="366134"/>
|
||||
<mapEntry key="get value" value="402104"/>
|
||||
<mapEntry key="getValidEncodings" value="1410473"/>
|
||||
<mapEntry key="initialize command help" value="91066852"/>
|
||||
<mapEntry key="interrupt" value="44963461"/>
|
||||
<mapEntry key="list breakpoint options" value="1324766"/>
|
||||
<mapEntry key="list breakpoints" value="1847541"/>
|
||||
<mapEntry key="list instruction sets" value="1763403"/>
|
||||
<mapEntry key="list signals" value="2185731"/>
|
||||
<mapEntry key="list source files" value="864344"/>
|
||||
<mapEntry key="list watchpoint options" value="4792947"/>
|
||||
<mapEntry key="list watchpoints" value="1009370"/>
|
||||
<mapEntry key="loadfile" value="374708990"/>
|
||||
<mapEntry key="next" value="25423704"/>
|
||||
<mapEntry key="nexti" value="29780513"/>
|
||||
<mapEntry key="remove" value="1521133"/>
|
||||
<mapEntry key="run script" value="43050208"/>
|
||||
<mapEntry key="set CWD" value="7281705"/>
|
||||
<mapEntry key="set breakpoint properties" value="4075180"/>
|
||||
<mapEntry key="set debug-from" value="1229495"/>
|
||||
<mapEntry key="set substitute-path" value="35280088"/>
|
||||
<mapEntry key="set watchpoint properties" value="1458988"/>
|
||||
<mapEntry key="source use_model_semihosting.ds" value="11060320"/>
|
||||
<mapEntry key="start" value="50342824"/>
|
||||
<mapEntry key="step" value="30959584"/>
|
||||
<mapEntry key="stepi" value="30815174"/>
|
||||
<mapEntry key="synchronizing trace ranges" value="74184"/>
|
||||
<mapEntry key="toggleBreakpoint" value="11765863"/>
|
||||
<mapEntry key="waitForTargetToStop" value="63934815"/>
|
||||
<mapEntry key="write expression" value="5812240"/>
|
||||
</mapAttribute>
|
||||
<stringAttribute key="CLOCK_SPEED" value="Auto"/>
|
||||
<listAttribute key="DEBUG_TAB."/>
|
||||
<stringAttribute key="DEBUG_TAB..RESOURCES.0.TYPE" value="SOURCE_DIR"/>
|
||||
<stringAttribute key="DEBUG_TAB..RESOURCES.0.VALUE" value="${workspace_loc:/tx}"/>
|
||||
<intAttribute key="DEBUG_TAB..RESOURCES.COUNT" value="1"/>
|
||||
<intAttribute key="FILES.CONNECT_TO_GDB_SERVER.RESOURCES.COUNT" value="0"/>
|
||||
<intAttribute key="FILES.DEBUG_EXISTING_ANDROID.RESOURCES.COUNT" value="0"/>
|
||||
<listAttribute key="FILES.DEBUG_RESIDENT_ANDROID"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.0.VALUE" value=""/>
|
||||
<intAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.COUNT" value="1"/>
|
||||
<listAttribute key="FILES.DEBUG_RESIDENT_APP"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.0.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.1.TYPE" value="APPLICATION_ON_TARGET"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.1.VALUE" value=""/>
|
||||
<intAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.COUNT" value="2"/>
|
||||
<listAttribute key="FILES.DOWNLOAD_AND_DEBUG"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.TYPE" value="TARGET_WORKING_DIR"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.TYPE" value="TARGET_DOWNLOAD_DIR"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.VALUE" value=""/>
|
||||
<intAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.COUNT" value="3"/>
|
||||
<listAttribute key="FILES.DOWNLOAD_DEBUG"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.TYPE" value="TARGET_WORKING_DIR"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.TYPE" value="TARGET_DOWNLOAD_DIR"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.VALUE" value=""/>
|
||||
<intAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.COUNT" value="3"/>
|
||||
<intAttribute key="FILES.DOWNLOAD_DEBUG_ANDROID.RESOURCES.COUNT" value="0"/>
|
||||
<listAttribute key="FILES.ICE_DEBUG">
|
||||
<listEntry value="ON_DEMAND_LOAD"/>
|
||||
<listEntry value="ALSO_LOAD_SYMBOLS"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.VALUE" value="${workspace_loc:/sample_threadx/Debug/sample_threadx.axf}"/>
|
||||
<intAttribute key="FILES.ICE_DEBUG.RESOURCES.COUNT" value="1"/>
|
||||
<listAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE">
|
||||
<listEntry value="ON_DEMAND_LOAD"/>
|
||||
<listEntry value="ALSO_LOAD_SYMBOLS"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.VALUE" value=""/>
|
||||
<intAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.COUNT" value="1"/>
|
||||
<listAttribute key="FILES.ICE_DEBUG_WITH_TRACE">
|
||||
<listEntry value="ON_DEMAND_LOAD"/>
|
||||
<listEntry value="ALSO_LOAD_SYMBOLS"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.VALUE" value=""/>
|
||||
<intAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.COUNT" value="1"/>
|
||||
<stringAttribute key="FILES.SELECTED_DEBUG_OPEATION" value="ICE_DEBUG"/>
|
||||
<stringAttribute key="HOST_WORKING_DIR" value="${workspace_loc}"/>
|
||||
<booleanAttribute key="HOST_WORKING_DIR_USE_DEFAULT" value="true"/>
|
||||
<booleanAttribute key="InstructionStepping" value="false"/>
|
||||
<booleanAttribute key="KEY_COMMANDS_AFTER_CONNECT" value="true"/>
|
||||
<stringAttribute key="KEY_COMMANDS_AFTER_CONNECT_TEXT" value="add-symbol-file "${workspace_loc:/sample_threadx/Debug/sample_threadx.axf}" EL1N:0"/>
|
||||
<booleanAttribute key="KEY_COMMANDS_AS_CONNECT" value="false"/>
|
||||
<intAttribute key="Messages.POST_TRIGGER_CAPTURE_SIZE.getLocalisedValue().FMTrace" value="50"/>
|
||||
<booleanAttribute key="Messages.STOP_ON_TRIGGER.getLocalisedValue().FMTrace" value="false"/>
|
||||
<booleanAttribute key="RSE_USE_HOSTNAME" value="true"/>
|
||||
<booleanAttribute key="SWD" value="false"/>
|
||||
<booleanAttribute key="SWJ" value="true"/>
|
||||
<stringAttribute key="TCP_DISABLE_EXTENDED_MODE" value="true"/>
|
||||
<booleanAttribute key="TCP_KILL_ON_EXIT" value="false"/>
|
||||
<listAttribute key="TREE_NODE_PROPERTIES:debugger.view.ExpressionsView">
|
||||
<listEntry value="NODE CACHE VERSION 1"/>
|
||||
<listEntry value="EXPRESSION_GROUP:Expressions:VALUE:gic_dist:VALUE:(gic_dist)->padding0"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="element formatter"/>
|
||||
<listEntry value="Unsigned Decimal"/>
|
||||
<listEntry value="EXPRESSION_GROUP:Expressions:VALUE:_tx_thread_current_ptr->tx_thread_name"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="element formatter"/>
|
||||
<listEntry value="Character"/>
|
||||
<listEntry value="EXPRESSION_GROUP:Expressions:VALUE:$AARCH64::$Core::$SP"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="TREE_NODE_PROPERTIES:debugger.view.NewRegisterView">
|
||||
<listEntry value="NODE CACHE VERSION 1"/>
|
||||
<listEntry value="REGISTER_SET:$AARCH64"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="expanded"/>
|
||||
<listEntry value="true"/>
|
||||
<listEntry value="REGISTER_GROUP:$AARCH64::$Core"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="expanded"/>
|
||||
<listEntry value="true"/>
|
||||
</listAttribute>
|
||||
<booleanAttribute key="VFS_ENABLED" value="true"/>
|
||||
<stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/>
|
||||
<stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/>
|
||||
<stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x00000000800088D0" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports/cortex_a35/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports\cortex_a35\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x00000000800088D0" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports/cortex_a35/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports\cortex_a35\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x00000000800088D0" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports/cortex_a35/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports\cortex_a35\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/>
|
||||
<listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses">
|
||||
<listEntry value="<Next Instruction>"/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value="0x0000000080009140"/>
|
||||
<listEntry value="0x000000008000E660"/>
|
||||
<listEntry value="EL1N:0x000000008000E660"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.ranges">
|
||||
<listEntry value="100"/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.MemoryView.addresses">
|
||||
<listEntry value=""/>
|
||||
<listEntry value="0x000000008000E600"/>
|
||||
<listEntry value="0x000000008000EE00"/>
|
||||
<listEntry value="thread_2.tx_thread_stack_start"/>
|
||||
<listEntry value="0x000000008000E500"/>
|
||||
<listEntry value="0x000000008000E670"/>
|
||||
<listEntry value="0x8000de30"/>
|
||||
<listEntry value="0x8000de00"/>
|
||||
<listEntry value="0x8000de48"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.MemoryView.ranges">
|
||||
<listEntry value=""/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.addresses">
|
||||
<listEntry value="_tx_thread_schedule"/>
|
||||
<listEntry value="<Next Instruction>"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges">
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="config_db_activity_name" value="Cortex-A35"/>
|
||||
<stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/>
|
||||
<stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/>
|
||||
<stringAttribute key="config_db_platform_name" value="Arm FVP (Installed with Arm DS) - Base_A35x1"/>
|
||||
<stringAttribute key="config_db_project_type" value="Bare Metal Debug"/>
|
||||
<stringAttribute key="config_db_project_type_id" value="BARE_METAL"/>
|
||||
<stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp_installedwitharmds_/base_a35x1"/>
|
||||
<stringAttribute key="config_file" value="CDB://../../Arm FVP/Base_A35x1/iris_config.xml"/>
|
||||
<booleanAttribute key="connectOnly" value="false"/>
|
||||
<stringAttribute key="connect_existing_model" value="false"/>
|
||||
<listAttribute key="debugger.view.DisassemblyView:current">
|
||||
<listEntry value="<Next Instruction>"/>
|
||||
<listEntry value="100"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="debugger.view.DisassemblyView:current:133102083840333696.viewid=2">
|
||||
<listEntry value="<Next Instruction>"/>
|
||||
<listEntry value="100"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="debugger.view.DisassemblyView:current:3239034212381883008.viewid=2">
|
||||
<listEntry value="_tx_thread_schedule"/>
|
||||
<listEntry value="100"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="debugger.view.DisassemblyView:current:4564877728016551851.viewid=3">
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
</listAttribute>
|
||||
<listAttribute key="debugger.view.ExpressionsView">
|
||||
<listEntry value="thread_0_counter"/>
|
||||
<listEntry value="thread_1_counter"/>
|
||||
<listEntry value="thread_2_counter"/>
|
||||
<listEntry value="thread_3_counter"/>
|
||||
<listEntry value="thread_4_counter"/>
|
||||
<listEntry value="thread_5_counter"/>
|
||||
<listEntry value="thread_6_counter"/>
|
||||
<listEntry value="thread_7_counter"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="debugger.view.ExpressionsView.ExpressionTypes">
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
</listAttribute>
|
||||
<mapAttribute key="debugger.view.ExpressionsView.ExpressionsData">
|
||||
<mapEntry key="0" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="1" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="2" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="3" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="4" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="5" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="6" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="7" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
</mapAttribute>
|
||||
<stringAttribute key="debugger.view.ExpressionsView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	255	-1	true	1	false	true	127	-1	true	2	true	true	159	-1	true	3	true	true	75	-1	true	4	true	true	65	-1	true	5	true	true	48	-1	true	6	true	true	240	-1	true	7	true	true	69	-1	true"/>
|
||||
<stringAttribute key="debugger.view.MemoryView" value="<?xml version="1.0" encoding="UTF-8"?> <page> 	<memoryView/> </page> "/>
|
||||
<listAttribute key="debugger.view.MemoryView:current">
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="debugger.view.NewRegisterView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	49	-1	true	1	false	true	90	-1	true	2	true	false	420	-1	true	3	false	true	41	-1	true	4	false	true	50	-1	true	5	true	false	37	-1	true	6	false	true	62	-1	true	7	true	false	53	-1	true"/>
|
||||
<stringAttribute key="debugger.view.NewRegisterView:_selectedRegisterSet" value="All registers"/>
|
||||
<mapAttribute key="debugger.view.NewRegisterView_registerSets"/>
|
||||
<stringAttribute key="debugger.view.StackView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	49	-1	true	1	false	true	90	-1	true	2	true	true	45	-1	true	3	true	true	41	-1	true	4	true	true	50	-1	true	5	true	true	37	-1	true	6	true	true	62	-1	true	7	true	true	53	-1	true"/>
|
||||
<listAttribute key="debugger.view.TraceView:TRACE_EXPORT_FILTERS"/>
|
||||
<stringAttribute key="debugger.view.VariableTreeView:DebugOutlineColumnState" value="OutlineConfig1	0"/>
|
||||
<listAttribute key="debugger.view.VariableTreeView:USER_ADDED_FILE_STATICS"/>
|
||||
<listAttribute key="debugger.view.VariableTreeView:USER_ADDED_GLOBALS"/>
|
||||
<listAttribute key="debugger.view.VariableTreeView:USER_ADDED_UNRESOLVED"/>
|
||||
<booleanAttribute key="debugger.view.expression.DrawAsHex" value="false"/>
|
||||
<booleanAttribute key="debugger.view.register.DrawAsHex" value="false"/>
|
||||
<stringAttribute key="dtsl_config" value="DtslScript"/>
|
||||
<stringAttribute key="dtsl_config_script" value="CDB://../../Arm FVP/Base_A35x1/dtsl_config_script.py"/>
|
||||
<stringAttribute key="dtsl_options_file" value="default"/>
|
||||
<stringAttribute key="dtsl_tracecapture_option" value="options.trace.traceCapture"/>
|
||||
<stringAttribute key="launch_configuration_version" value="5.21.1"/>
|
||||
<booleanAttribute key="linuxOS" value="false"/>
|
||||
<stringAttribute key="model_connection_address" value="127.0.0.1:7100"/>
|
||||
<stringAttribute key="model_iris" value="1"/>
|
||||
<stringAttribute key="model_params" value="-C bp.secure_memory=false -C cache_state_modelled=0"/>
|
||||
<stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/>
|
||||
<booleanAttribute key="runAfterConnect" value="false"/>
|
||||
<stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/>
|
||||
<mapAttribute key="scripts_view_script_links">
|
||||
<mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports\cortex_a35\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/>
|
||||
<mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports\cortex_a35\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/>
|
||||
</mapAttribute>
|
||||
<listAttribute key="setup">
|
||||
<listEntry value="CDB://Scripts/rtsm_launcher.py"/>
|
||||
<listEntry value=""FVP_Base_Cortex-A35x1""/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/>
|
||||
<stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:\temp1702\tx\</ta> 		<tb>C:\temp1702\tx\</tb> 	</tuple> </tuplelist> "/>
|
||||
<stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/>
|
||||
</launchConfiguration>
|
||||
@@ -0,0 +1,103 @@
|
||||
;********************************************************
|
||||
; Scatter file for Armv8-A Startup code on FVP Base model
|
||||
; Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
; Use, modification and redistribution of this file is subject to your possession of a
|
||||
; valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
; and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
;********************************************************
|
||||
|
||||
LOAD 0x80000000
|
||||
{
|
||||
EXEC +0
|
||||
{
|
||||
startup.o (StartUp, +FIRST)
|
||||
* (+RO, +RW, +ZI)
|
||||
}
|
||||
|
||||
;
|
||||
; App stacks for all CPUs
|
||||
; All stacks and heap are aligned to a cache-line boundary
|
||||
;
|
||||
ARM_LIB_STACK +0 ALIGN 64 EMPTY 8 * 0x4000 {}
|
||||
|
||||
;
|
||||
; Separate heap - import symbol __use_two_region_memory
|
||||
; in source code for this to work correctly
|
||||
;
|
||||
ARM_LIB_HEAP +0 ALIGN 64 EMPTY 0xA0000 {}
|
||||
|
||||
;
|
||||
; Handler stacks for all CPUs
|
||||
; All stacks and heap are aligned to a cache-line boundary
|
||||
;
|
||||
HANDLER_STACK +0 ALIGN 64 EMPTY 4 * 0x4000 {}
|
||||
|
||||
;
|
||||
; Stacks for EL3
|
||||
;
|
||||
EL3_STACKS +0 ALIGN 64 EMPTY 8 * 0x1000 {}
|
||||
;
|
||||
; Strictly speaking, the L1 tables do not need to
|
||||
; be so strongly aligned, but no matter
|
||||
;
|
||||
TTB0_L1 +0 ALIGN 4096 EMPTY 0x1000 {}
|
||||
|
||||
;
|
||||
; Various sets of L2 tables
|
||||
;
|
||||
; Alignment is 4KB, since the code uses a 4K page
|
||||
; granularity - larger granularities would require
|
||||
; correspondingly stricter alignment
|
||||
;
|
||||
TTB0_L2_RAM +0 ALIGN 4096 EMPTY 0x1000 {}
|
||||
|
||||
TTB0_L2_PRIVATE +0 ALIGN 4096 EMPTY 0x1000 {}
|
||||
|
||||
TTB0_L2_PERIPH +0 ALIGN 4096 EMPTY 0x1000 {}
|
||||
|
||||
;
|
||||
; The startup code uses the end of this region to calculate
|
||||
; the top of memory - do not place any RAM regions after it
|
||||
;
|
||||
TOP_OF_RAM +0 EMPTY 4 {}
|
||||
|
||||
;
|
||||
; CS3 Peripherals is a 64MB region from 0x1c000000
|
||||
; that includes the following:
|
||||
; System Registers at 0x1C010000
|
||||
; UART0 (PL011) at 0x1C090000
|
||||
; Color LCD Controller (PL111) at 0x1C1F0000
|
||||
; plus a number of others.
|
||||
; CS3_PERIPHERALS is used by the startup code for page-table generation
|
||||
; This region is not truly empty, but we have no
|
||||
; predefined objects that live within it
|
||||
;
|
||||
CS3_PERIPHERALS 0x1c000000 EMPTY 0x90000 {}
|
||||
|
||||
;
|
||||
; Place the UART peripheral registers data structure
|
||||
; This is only really needed if USE_SERIAL_PORT is defined, but
|
||||
; the linker will remove unused sections if not needed
|
||||
; PL011 0x1c090000 UNINIT 0x1000
|
||||
; {
|
||||
; uart.o (+ZI)
|
||||
; }
|
||||
; Note that some other CS3_PERIPHERALS follow this
|
||||
|
||||
;
|
||||
; GICv3 distributor
|
||||
;
|
||||
GICD 0x2f000000 UNINIT 0x8000
|
||||
{
|
||||
GICv3_gicd.o (.bss.distributor)
|
||||
}
|
||||
|
||||
;
|
||||
; GICv3 redistributors
|
||||
; 128KB for each redistributor in the system
|
||||
;
|
||||
GICR 0x2f100000 UNINIT 0x80000
|
||||
{
|
||||
GICv3_gicr.o (.bss.redistributor)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
// ------------------------------------------------------------
|
||||
// SP804 Dual Timer
|
||||
//
|
||||
// Copyright (c) 2009-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#include "sp804_timer.h"
|
||||
|
||||
#define TIMER_SP804_CTRL_TIMEREN (1 << 7)
|
||||
#define TIMER_SP804_CTRL_TIMERMODE (1 << 6) // Bit 6:
|
||||
#define TIMER_SP804_CTRL_INTENABLE (1 << 5)
|
||||
#define TIMER_SP804_CTRL_TIMERSIZE (1 << 1) // Bit 1: 0=16-bit, 1=32-bit
|
||||
#define TIMER_SP804_CTRL_ONESHOT (1 << 0) // Bit 0: 0=wrapping, 1=one-shot
|
||||
|
||||
#define TIMER_SP804_CTRL_PRESCALE_1 (0 << 2) // clk/1
|
||||
#define TIMER_SP804_CTRL_PRESCALE_4 (1 << 2) // clk/4
|
||||
#define TIMER_SP804_CTRL_PRESCALE_8 (2 << 2) // clk/8
|
||||
|
||||
struct sp804_timer
|
||||
{
|
||||
volatile uint32_t Time1Load; // +0x00
|
||||
const volatile uint32_t Time1Value; // +0x04 - RO
|
||||
volatile uint32_t Timer1Control; // +0x08
|
||||
volatile uint32_t Timer1IntClr; // +0x0C - WO
|
||||
const volatile uint32_t Timer1RIS; // +0x10 - RO
|
||||
const volatile uint32_t Timer1MIS; // +0x14 - RO
|
||||
volatile uint32_t Timer1BGLoad; // +0x18
|
||||
|
||||
volatile uint32_t Time2Load; // +0x20
|
||||
volatile uint32_t Time2Value; // +0x24
|
||||
volatile uint8_t Timer2Control; // +0x28
|
||||
volatile uint32_t Timer2IntClr; // +0x2C - WO
|
||||
const volatile uint32_t Timer2RIS; // +0x30 - RO
|
||||
const volatile uint32_t Timer2MIS; // +0x34 - RO
|
||||
volatile uint32_t Timer2BGLoad; // +0x38
|
||||
|
||||
// Not including ID registers
|
||||
|
||||
};
|
||||
|
||||
// Instance of the dual timer, will be placed using the scatter file
|
||||
struct sp804_timer* dual_timer;
|
||||
|
||||
|
||||
// Set base address of timer
|
||||
// address - virtual address of SP804 timer
|
||||
void setTimerBaseAddress(uint64_t address)
|
||||
{
|
||||
dual_timer = (struct sp804_timer*)address;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Sets up the private timer
|
||||
// load_value - Initial value of timer
|
||||
// auto_reload - Periodic (SP804_AUTORELOAD) or one shot (SP804_SINGLESHOT)
|
||||
// interrupt - Whether to generate an interrupt
|
||||
void initTimer(uint32_t load_value, uint32_t auto_reload, uint32_t interrupt)
|
||||
{
|
||||
uint32_t tmp = 0;
|
||||
|
||||
dual_timer->Time1Load = load_value;
|
||||
|
||||
// Fixed setting: 32-bit, no prescaling
|
||||
tmp = TIMER_SP804_CTRL_TIMERSIZE | TIMER_SP804_CTRL_PRESCALE_1 | TIMER_SP804_CTRL_TIMERMODE;
|
||||
|
||||
// Settings from parameters: interrupt generation & reload
|
||||
tmp = tmp | interrupt | auto_reload;
|
||||
|
||||
// Write control register
|
||||
dual_timer->Timer1Control = tmp;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Starts the timer
|
||||
void startTimer(void)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = dual_timer->Timer1Control;
|
||||
tmp = tmp | TIMER_SP804_CTRL_TIMEREN; // Set TimerEn (bit 7)
|
||||
dual_timer->Timer1Control = tmp;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Stops the timer
|
||||
void stopTimer(void)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = dual_timer->Timer1Control;
|
||||
tmp = tmp & ~TIMER_SP804_CTRL_TIMEREN; // Clear TimerEn (bit 7)
|
||||
dual_timer->Timer1Control = tmp;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Returns the current timer count
|
||||
uint32_t getTimerCount(void)
|
||||
{
|
||||
return dual_timer->Time1Value;
|
||||
}
|
||||
|
||||
|
||||
void clearTimerIrq(void)
|
||||
{
|
||||
// A write to this register, of any value, clears the interrupt
|
||||
dual_timer->Timer1IntClr = 1;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// End of sp804_timer.c
|
||||
// ------------------------------------------------------------
|
||||
@@ -0,0 +1,53 @@
|
||||
// ------------------------------------------------------------
|
||||
// SP804 Dual Timer
|
||||
// Header Filer
|
||||
//
|
||||
// Copyright (c) 2009-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#ifndef _SP804_TIMER_
|
||||
#define _SP804_TIMER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Set base address of timer
|
||||
// address - virtual address of SP804 timer
|
||||
void setTimerBaseAddress(uint64_t address);
|
||||
|
||||
|
||||
// Sets up the private timer
|
||||
// load_value - Initial value of timer
|
||||
// auto_reload - Periodic (SP804_AUTORELOAD) or one shot (SP804_SINGLESHOT)
|
||||
// interrupt - Whether to generate an interrupt
|
||||
|
||||
#define SP804_AUTORELOAD (0)
|
||||
#define SP804_SINGLESHOT (1)
|
||||
#define SP804_GENERATE_IRQ (1 << 5)
|
||||
#define SP804_NO_IRQ (0)
|
||||
|
||||
void initTimer(uint32_t load_value, uint32_t auto_reload, uint32_t interrupt);
|
||||
|
||||
|
||||
// Starts the timer
|
||||
void startTimer(void);
|
||||
|
||||
|
||||
// Stops the timer
|
||||
void stopTimer(void);
|
||||
|
||||
|
||||
// Returns the current timer count
|
||||
uint32_t getTimerCount(void);
|
||||
|
||||
|
||||
// Clears the timer interrupt
|
||||
void clearTimerIrq(void);
|
||||
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// End of sp804_timer.h
|
||||
// ------------------------------------------------------------
|
||||
@@ -0,0 +1,779 @@
|
||||
// ------------------------------------------------------------
|
||||
// Armv8-A MPCore EL3 AArch64 Startup Code
|
||||
//
|
||||
// Basic Vectors, MMU, caches and GICv3 initialization
|
||||
//
|
||||
// Exits in EL1 AArch64
|
||||
//
|
||||
// Copyright (c) 2014-2019 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#include "v8_mmu.h"
|
||||
#include "v8_system.h"
|
||||
#include "GICv3_aliases.h"
|
||||
|
||||
.section StartUp, "ax"
|
||||
.balign 4
|
||||
.cfi_sections .debug_frame // put stack frame info into .debug_frame instead of .eh_frame
|
||||
|
||||
.global el1_vectors
|
||||
.global el2_vectors
|
||||
.global el3_vectors
|
||||
|
||||
.global InvalidateUDCaches
|
||||
.global ZeroBlock
|
||||
|
||||
.global SetPrivateIntSecurityBlock
|
||||
.global SetSPISecurityAll
|
||||
.global SetPrivateIntPriority
|
||||
|
||||
.global GetGICR
|
||||
.global WakeupGICR
|
||||
.global SyncAREinGICD
|
||||
.global EnableGICD
|
||||
.global EnablePrivateInt
|
||||
.global GetPrivateIntPending
|
||||
.global ClearPrivateIntPending
|
||||
|
||||
.global __main
|
||||
//.global MainApp
|
||||
|
||||
.global Image$$EXEC$$RO$$Base
|
||||
.global Image$$TTB0_L1$$ZI$$Base
|
||||
.global Image$$TTB0_L2_RAM$$ZI$$Base
|
||||
.global Image$$TTB0_L2_PERIPH$$ZI$$Base
|
||||
.global Image$$TOP_OF_RAM$$ZI$$Base
|
||||
.global Image$$GICD$$ZI$$Base
|
||||
.global Image$$ARM_LIB_STACK$$ZI$$Limit
|
||||
.global Image$$EL3_STACKS$$ZI$$Limit
|
||||
.global Image$$CS3_PERIPHERALS$$ZI$$Base
|
||||
// use separate stack and heap, as anticipated by scatter.scat
|
||||
.global __use_two_region_memory
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
.global start64
|
||||
.type start64, "function"
|
||||
start64:
|
||||
|
||||
//
|
||||
// program the VBARs
|
||||
//
|
||||
ldr x1, =el1_vectors
|
||||
msr VBAR_EL1, x1
|
||||
|
||||
ldr x1, =el2_vectors
|
||||
msr VBAR_EL2, x1
|
||||
|
||||
ldr x1, =el3_vectors
|
||||
msr VBAR_EL3, x1
|
||||
|
||||
|
||||
// GIC-500 comes out of reset in GICv2 compatibility mode - first set
|
||||
// system register enables for all relevant exception levels, and
|
||||
// select GICv3 operating mode
|
||||
//
|
||||
msr SCR_EL3, xzr // Ensure NS bit is initially clear, so secure copy of ICC_SRE_EL1 can be configured
|
||||
isb
|
||||
|
||||
mov x0, #15
|
||||
msr ICC_SRE_EL3, x0
|
||||
isb
|
||||
msr ICC_SRE_EL1, x0 // Secure copy of ICC_SRE_EL1
|
||||
|
||||
//
|
||||
// set lower exception levels as non-secure, with no access
|
||||
// back to EL2 or EL3, and are AArch64 capable
|
||||
//
|
||||
mov x3, #(SCR_EL3_RW | \
|
||||
SCR_EL3_SMD | \
|
||||
SCR_EL3_NS) // Set NS bit, to access Non-secure registers
|
||||
msr SCR_EL3, x3
|
||||
isb
|
||||
|
||||
mov x0, #15
|
||||
msr ICC_SRE_EL2, x0
|
||||
isb
|
||||
msr ICC_SRE_EL1, x0 // Non-secure copy of ICC_SRE_EL1
|
||||
|
||||
|
||||
//
|
||||
// no traps or VM modifications from the Hypervisor, EL1 is AArch64
|
||||
//
|
||||
mov x2, #HCR_EL2_RW
|
||||
msr HCR_EL2, x2
|
||||
|
||||
//
|
||||
// VMID is still significant, even when virtualisation is not
|
||||
// being used, so ensure VTTBR_EL2 is properly initialised
|
||||
//
|
||||
msr VTTBR_EL2, xzr
|
||||
|
||||
//
|
||||
// VMPIDR_EL2 holds the value of the Virtualization Multiprocessor ID. This is the value returned by Non-secure EL1 reads of MPIDR_EL1.
|
||||
// VPIDR_EL2 holds the value of the Virtualization Processor ID. This is the value returned by Non-secure EL1 reads of MIDR_EL1.
|
||||
// Both of these registers are architecturally UNKNOWN at reset, and so they must be set to the correct value
|
||||
// (even if EL2/virtualization is not being used), otherwise non-secure EL1 reads of MPIDR_EL1/MIDR_EL1 will return garbage values.
|
||||
// This guarantees that any future reads of MPIDR_EL1 and MIDR_EL1 from Non-secure EL1 will return the correct value.
|
||||
//
|
||||
mrs x0, MPIDR_EL1
|
||||
msr VMPIDR_EL2, x0
|
||||
mrs x0, MIDR_EL1
|
||||
msr VPIDR_EL2, x0
|
||||
|
||||
// extract the core number from MPIDR_EL1 and store it in
|
||||
// x19 (defined by the AAPCS as callee-saved), so we can re-use
|
||||
// the number later
|
||||
//
|
||||
bl GetCPUID
|
||||
mov x19, x0
|
||||
|
||||
//
|
||||
// neither EL3 nor EL2 trap floating point or accesses to CPACR
|
||||
//
|
||||
msr CPTR_EL3, xzr
|
||||
msr CPTR_EL2, xzr
|
||||
|
||||
//
|
||||
// SCTLR_ELx may come out of reset with UNKNOWN values so we will
|
||||
// set the fields to 0 except, possibly, the endianess field(s).
|
||||
// Note that setting SCTLR_EL2 or the EL0 related fields of SCTLR_EL1
|
||||
// is not strictly needed, since we're never in EL2 or EL0
|
||||
//
|
||||
#ifdef __ARM_BIG_ENDIAN
|
||||
mov x0, #(SCTLR_ELx_EE | SCTLR_EL1_E0E)
|
||||
#else
|
||||
mov x0, #0
|
||||
#endif
|
||||
msr SCTLR_EL3, x0
|
||||
msr SCTLR_EL2, x0
|
||||
msr SCTLR_EL1, x0
|
||||
|
||||
#ifdef CORTEXA
|
||||
//
|
||||
// Configure ACTLR_EL[23]
|
||||
// ----------------------
|
||||
//
|
||||
// These bits are IMPLEMENTATION DEFINED, so are different for
|
||||
// different processors
|
||||
//
|
||||
// For Cortex-A57, the controls we set are:
|
||||
//
|
||||
// Enable lower level access to CPUACTLR_EL1
|
||||
// Enable lower level access to CPUECTLR_EL1
|
||||
// Enable lower level access to L2CTLR_EL1
|
||||
// Enable lower level access to L2ECTLR_EL1
|
||||
// Enable lower level access to L2ACTLR_EL1
|
||||
//
|
||||
mov x0, #((1 << 0) | \
|
||||
(1 << 1) | \
|
||||
(1 << 4) | \
|
||||
(1 << 5) | \
|
||||
(1 << 6))
|
||||
|
||||
msr ACTLR_EL3, x0
|
||||
msr ACTLR_EL2, x0
|
||||
|
||||
//
|
||||
// configure CPUECTLR_EL1
|
||||
//
|
||||
// These bits are IMP DEF, so need to different for different
|
||||
// processors
|
||||
//
|
||||
// SMPEN - bit 6 - Enables the processor to receive cache
|
||||
// and TLB maintenance operations
|
||||
//
|
||||
// Note: For Cortex-A57/53 SMPEN should be set before enabling
|
||||
// the caches and MMU, or performing any cache and TLB
|
||||
// maintenance operations.
|
||||
//
|
||||
// This register has a defined reset value, so we use a
|
||||
// read-modify-write sequence to set SMPEN
|
||||
//
|
||||
mrs x0, S3_1_c15_c2_1 // Read EL1 CPU Extended Control Register
|
||||
orr x0, x0, #(1 << 6) // Set the SMPEN bit
|
||||
msr S3_1_c15_c2_1, x0 // Write EL1 CPU Extended Control Register
|
||||
|
||||
isb
|
||||
#endif
|
||||
|
||||
//
|
||||
// That's the last of the control settings for now
|
||||
//
|
||||
// Note: no ISB after all these changes, as registers won't be
|
||||
// accessed until after an exception return, which is itself a
|
||||
// context synchronisation event
|
||||
//
|
||||
|
||||
//
|
||||
// Setup some EL3 stack space, ready for calling some subroutines, below.
|
||||
//
|
||||
// Stack space allocation is CPU-specific, so use CPU
|
||||
// number already held in x19
|
||||
//
|
||||
// 2^12 bytes per CPU for the EL3 stacks
|
||||
//
|
||||
ldr x0, =Image$$EL3_STACKS$$ZI$$Limit
|
||||
sub x0, x0, x19, lsl #12
|
||||
mov sp, x0
|
||||
|
||||
//
|
||||
// we need to configure the GIC while still in secure mode, specifically
|
||||
// all PPIs and SPIs have to be programmed as Group1 interrupts
|
||||
//
|
||||
|
||||
//
|
||||
// Before the GIC can be reliably programmed, we need to
|
||||
// enable Affinity Routing, as this affects where the configuration
|
||||
// registers are (with Affinity Routing enabled, some registers are
|
||||
// in the Redistributor, whereas those same registers are in the
|
||||
// Distributor with Affinity Routing disabled (i.e. when in GICv2
|
||||
// compatibility mode).
|
||||
//
|
||||
mov x0, #(1 << 4) | (1 << 5) // gicdctlr_ARE_S | gicdctlr_ARE_NS
|
||||
mov x1, x19
|
||||
bl SyncAREinGICD
|
||||
|
||||
//
|
||||
// The Redistributor comes out of reset assuming the processor is
|
||||
// asleep - correct that assumption
|
||||
//
|
||||
bl GetAffinity
|
||||
bl GetGICR
|
||||
mov w20, w0 // Keep a copy for later
|
||||
bl WakeupGICR
|
||||
|
||||
//
|
||||
// Now we're ready to set security and other initialisations
|
||||
//
|
||||
// This is a per-CPU configuration for these interrupts
|
||||
//
|
||||
// for the first cluster, CPU number is the redistributor index
|
||||
//
|
||||
mov w0, w20
|
||||
mov w1, #1 // gicigroupr_G1NS
|
||||
bl SetPrivateIntSecurityBlock
|
||||
|
||||
//
|
||||
// While we're in the Secure World, set the priority mask low enough
|
||||
// for it to be writable in the Non-Secure World
|
||||
//
|
||||
//mov x0, #16 << 3 // 5 bits of priority in the Secure world
|
||||
mov x0, #0xFF // for Non-Secure interrupts
|
||||
msr ICC_PMR_EL1, x0
|
||||
|
||||
//
|
||||
// there's more GIC setup to do, but only for the primary CPU
|
||||
//
|
||||
cbnz x19, drop_to_el1
|
||||
|
||||
//
|
||||
// There's more to do to the GIC - call the utility routine to set
|
||||
// all SPIs to Group1
|
||||
//
|
||||
mov w0, #1 // gicigroupr_G1NS
|
||||
bl SetSPISecurityAll
|
||||
|
||||
//
|
||||
// Set up EL1 entry point and "dummy" exception return information,
|
||||
// then perform exception return to enter EL1
|
||||
//
|
||||
.global drop_to_el1
|
||||
drop_to_el1:
|
||||
adr x1, el1_entry_aarch64
|
||||
msr ELR_EL3, x1
|
||||
mov x1, #(AARCH64_SPSR_EL1h | \
|
||||
AARCH64_SPSR_F | \
|
||||
AARCH64_SPSR_I | \
|
||||
AARCH64_SPSR_A)
|
||||
msr SPSR_EL3, x1
|
||||
eret
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// EL1 - Common start-up code
|
||||
// ------------------------------------------------------------
|
||||
|
||||
.global el1_entry_aarch64
|
||||
.type el1_entry_aarch64, "function"
|
||||
el1_entry_aarch64:
|
||||
|
||||
//
|
||||
// Now we're in EL1, setup the application stack
|
||||
// the scatter file allocates 2^14 bytes per app stack
|
||||
//
|
||||
ldr x0, =Image$$HANDLER_STACK$$ZI$$Limit
|
||||
sub x0, x0, x19, lsl #14
|
||||
mov sp, x0
|
||||
MSR SPSel, #0
|
||||
ISB
|
||||
ldr x0, =Image$$ARM_LIB_STACK$$ZI$$Limit
|
||||
sub x0, x0, x19, lsl #14
|
||||
mov sp, x0
|
||||
|
||||
//
|
||||
// Enable floating point
|
||||
//
|
||||
mov x0, #CPACR_EL1_FPEN
|
||||
msr CPACR_EL1, x0
|
||||
|
||||
//
|
||||
// Invalidate caches and TLBs for all stage 1
|
||||
// translations used at EL1
|
||||
//
|
||||
// Cortex-A processors automatically invalidate their caches on reset
|
||||
// (unless suppressed with the DBGL1RSTDISABLE or L2RSTDISABLE pins).
|
||||
// It is therefore not necessary for software to invalidate the caches
|
||||
// on startup, however, this is done here in case of a warm reset.
|
||||
bl InvalidateUDCaches
|
||||
tlbi VMALLE1
|
||||
|
||||
|
||||
//
|
||||
// Set TTBR0 Base address
|
||||
//
|
||||
// The CPUs share one set of translation tables that are
|
||||
// generated by CPU0 at run-time
|
||||
//
|
||||
// TTBR1_EL1 is not used in this example
|
||||
//
|
||||
ldr x1, =Image$$TTB0_L1$$ZI$$Base
|
||||
msr TTBR0_EL1, x1
|
||||
|
||||
|
||||
//
|
||||
// Set up memory attributes
|
||||
//
|
||||
// These equate to:
|
||||
//
|
||||
// 0 -> 0b01000100 = 0x00000044 = Normal, Inner/Outer Non-Cacheable
|
||||
// 1 -> 0b11111111 = 0x0000ff00 = Normal, Inner/Outer WriteBack Read/Write Allocate
|
||||
// 2 -> 0b00000100 = 0x00040000 = Device-nGnRE
|
||||
//
|
||||
mov x1, #0xff44
|
||||
movk x1, #4, LSL #16 // equiv to: movk x1, #0x0000000000040000
|
||||
msr MAIR_EL1, x1
|
||||
|
||||
|
||||
//
|
||||
// Set up TCR_EL1
|
||||
//
|
||||
// We're using only TTBR0 (EPD1 = 1), and the page table entries:
|
||||
// - are using an 8-bit ASID from TTBR0
|
||||
// - have a 4K granularity (TG0 = 0b00)
|
||||
// - are outer-shareable (SH0 = 0b10)
|
||||
// - are using Inner & Outer WBWA Normal memory ([IO]RGN0 = 0b01)
|
||||
// - map
|
||||
// + 32 bits of VA space (T0SZ = 0x20)
|
||||
// + into a 32-bit PA space (IPS = 0b000)
|
||||
//
|
||||
// 36 32 28 24 20 16 12 8 4 0
|
||||
// -----+----+----+----+----+----+----+----+----+----+
|
||||
// | | |OOII| | | |OOII| | |
|
||||
// TT | | |RRRR|E T | T| |RRRR|E T | T|
|
||||
// BB | I I|TTSS|GGGG|P 1 | 1|TTSS|GGGG|P 0 | 0|
|
||||
// IIA| P P|GGHH|NNNN|DAS | S|GGHH|NNNN|D S | S|
|
||||
// 10S| S-S|1111|1111|11Z-|---Z|0000|0000|0 Z-|---Z|
|
||||
//
|
||||
// 000 0000 0000 0000 1000 0000 0010 0101 0010 0000
|
||||
//
|
||||
// 0x 8 0 2 5 2 0
|
||||
//
|
||||
// Note: the ISB is needed to ensure the changes to system
|
||||
// context are before the write of SCTLR_EL1.M to enable
|
||||
// the MMU. It is likely on a "real" implementation that
|
||||
// this setup would work without an ISB, due to the
|
||||
// amount of code that gets executed before enabling the
|
||||
// MMU, but that would not be architecturally correct.
|
||||
//
|
||||
ldr x1, =0x0000000000802520
|
||||
msr TCR_EL1, x1
|
||||
isb
|
||||
|
||||
//
|
||||
// x19 already contains the CPU number, so branch to secondary
|
||||
// code if we're not on CPU0
|
||||
//
|
||||
cbnz x19, el1_secondary
|
||||
|
||||
//
|
||||
// Fall through to primary code
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// ------------------------------------------------------------
|
||||
//
|
||||
// EL1 - primary CPU init code
|
||||
//
|
||||
// This code is run on CPU0, while the other CPUs are in the
|
||||
// holding pen
|
||||
//
|
||||
|
||||
.global el1_primary
|
||||
.type el1_primary, "function"
|
||||
el1_primary:
|
||||
|
||||
//
|
||||
// Turn on the banked GIC distributor enable,
|
||||
// ready for individual CPU enables later
|
||||
//
|
||||
mov w0, #(1 << 1) // gicdctlr_EnableGrp1A
|
||||
bl EnableGICD
|
||||
|
||||
//
|
||||
// Generate TTBR0 L1
|
||||
//
|
||||
// at 4KB granularity, 32-bit VA space, table lookup starts at
|
||||
// L1, with 1GB regions
|
||||
//
|
||||
// we are going to create entries pointing to L2 tables for a
|
||||
// couple of these 1GB regions, the first of which is the
|
||||
// RAM on the VE board model - get the table addresses and
|
||||
// start by emptying out the L1 page tables (4 entries at L1
|
||||
// for a 4K granularity)
|
||||
//
|
||||
// x21 = address of L1 tables
|
||||
//
|
||||
ldr x21, =Image$$TTB0_L1$$ZI$$Base
|
||||
mov x0, x21
|
||||
mov x1, #(4 << 3)
|
||||
bl ZeroBlock
|
||||
|
||||
//
|
||||
// time to start mapping the RAM regions - clear out the
|
||||
// L2 tables and point to them from the L1 tables
|
||||
//
|
||||
// x22 = address of L2 tables, needs to be remembered in case
|
||||
// we want to re-use the tables for mapping peripherals
|
||||
//
|
||||
ldr x22, =Image$$TTB0_L2_RAM$$ZI$$Base
|
||||
mov x1, #(512 << 3)
|
||||
mov x0, x22
|
||||
bl ZeroBlock
|
||||
|
||||
//
|
||||
// Get the start address of RAM (the EXEC region) into x4
|
||||
// and calculate the offset into the L1 table (1GB per region,
|
||||
// max 4GB)
|
||||
//
|
||||
// x23 = L1 table offset, saved for later comparison against
|
||||
// peripheral offset
|
||||
//
|
||||
ldr x4, =Image$$EXEC$$RO$$Base
|
||||
ubfx x23, x4, #30, #2
|
||||
|
||||
orr x1, x22, #TT_S1_ATTR_PAGE
|
||||
str x1, [x21, x23, lsl #3]
|
||||
|
||||
//
|
||||
// we've already used the RAM start address in x4 - we now need
|
||||
// to get this in terms of an offset into the L2 page tables,
|
||||
// where each entry covers 2MB
|
||||
//
|
||||
ubfx x2, x4, #21, #9
|
||||
|
||||
//
|
||||
// TOP_OF_RAM in the scatter file marks the end of the
|
||||
// Execute region in RAM: convert the end of this region to an
|
||||
// offset too, being careful to round up, then calculate the
|
||||
// number of entries to write
|
||||
//
|
||||
ldr x5, =Image$$TOP_OF_RAM$$ZI$$Base
|
||||
sub x3, x5, #1
|
||||
ubfx x3, x3, #21, #9
|
||||
add x3, x3, #1
|
||||
sub x3, x3, x2
|
||||
|
||||
//
|
||||
// set x1 to the required page table attributes, then orr
|
||||
// in the start address (modulo 2MB)
|
||||
//
|
||||
// L2 tables in our configuration cover 2MB per entry - map
|
||||
// memory as Shared, Normal WBWA (MAIR[1]) with a flat
|
||||
// VA->PA translation
|
||||
//
|
||||
bic x4, x4, #((1 << 21) - 1)
|
||||
ldr x1, =(TT_S1_ATTR_BLOCK | \
|
||||
(1 << TT_S1_ATTR_MATTR_LSB) | \
|
||||
TT_S1_ATTR_NS | \
|
||||
TT_S1_ATTR_AP_RW_PL1 | \
|
||||
TT_S1_ATTR_SH_INNER | \
|
||||
TT_S1_ATTR_AF | \
|
||||
TT_S1_ATTR_nG)
|
||||
orr x1, x1, x4
|
||||
|
||||
//
|
||||
// factor the offset into the page table address and then write
|
||||
// the entries
|
||||
//
|
||||
add x0, x22, x2, lsl #3
|
||||
|
||||
loop1:
|
||||
subs x3, x3, #1
|
||||
str x1, [x0], #8
|
||||
add x1, x1, #0x200, LSL #12 // equiv to add x1, x1, #(1 << 21) // 2MB per entry
|
||||
bne loop1
|
||||
|
||||
|
||||
//
|
||||
// now mapping the Peripheral regions - clear out the
|
||||
// L2 tables and point to them from the L1 tables
|
||||
//
|
||||
// The assumption here is that all peripherals live within
|
||||
// a common 1GB region (i.e. that there's a single set of
|
||||
// L2 pages for all the peripherals). We only use a UART
|
||||
// and the GIC in this example, so the assumption is sound
|
||||
//
|
||||
// x24 = address of L2 peripheral tables
|
||||
//
|
||||
ldr x24, =Image$$TTB0_L2_PERIPH$$ZI$$Base
|
||||
|
||||
//
|
||||
// get the GICD address into x4 and calculate
|
||||
// the offset into the L1 table
|
||||
//
|
||||
// x25 = L1 table offset
|
||||
//
|
||||
ldr x4, =Image$$GICD$$ZI$$Base
|
||||
ubfx x25, x4, #30, #2
|
||||
|
||||
//
|
||||
// here's the tricky bit: it's possible that the peripherals are
|
||||
// in the same 1GB region as the RAM, in which case we don't need
|
||||
// to prime a separate set of L2 page tables, nor add them to the
|
||||
// L1 tables
|
||||
//
|
||||
// if we're going to re-use the TTB0_L2_RAM tables, get their
|
||||
// address into x24, which is used later on to write the PTEs
|
||||
//
|
||||
cmp x25, x23
|
||||
csel x24, x22, x24, EQ
|
||||
b.eq nol2setup
|
||||
|
||||
//
|
||||
// Peripherals are in a separate 1GB region, and so have their own
|
||||
// set of L2 tables - clean out the tables and add them to the L1
|
||||
// table
|
||||
//
|
||||
mov x0, x24
|
||||
mov x1, #512 << 3
|
||||
bl ZeroBlock
|
||||
|
||||
orr x1, x24, #TT_S1_ATTR_PAGE
|
||||
str x1, [x21, x25, lsl #3]
|
||||
|
||||
//
|
||||
// there's only going to be a single 2MB region for GICD (in
|
||||
// x4) - get this in terms of an offset into the L2 page tables
|
||||
//
|
||||
// with larger systems, it is possible that the GIC redistributor
|
||||
// registers require extra 2MB pages, in which case extra code
|
||||
// would be required here
|
||||
//
|
||||
nol2setup:
|
||||
ubfx x2, x4, #21, #9
|
||||
|
||||
//
|
||||
// set x1 to the required page table attributes, then orr
|
||||
// in the start address (modulo 2MB)
|
||||
//
|
||||
// L2 tables in our configuration cover 2MB per entry - map
|
||||
// memory as NS Device-nGnRE (MAIR[2]) with a flat VA->PA
|
||||
// translation
|
||||
//
|
||||
bic x4, x4, #((1 << 21) - 1) // start address mod 2MB
|
||||
ldr x1, =(TT_S1_ATTR_BLOCK | \
|
||||
(2 << TT_S1_ATTR_MATTR_LSB) | \
|
||||
TT_S1_ATTR_NS | \
|
||||
TT_S1_ATTR_AP_RW_PL1 | \
|
||||
TT_S1_ATTR_AF | \
|
||||
TT_S1_ATTR_nG)
|
||||
orr x1, x1, x4
|
||||
|
||||
//
|
||||
// only a single L2 entry for this, so no loop as we have for RAM, above
|
||||
//
|
||||
str x1, [x24, x2, lsl #3]
|
||||
|
||||
//
|
||||
// we have CS3_PERIPHERALS that include the UART controller
|
||||
//
|
||||
// Again, the code is making assumptions - this time that the CS3_PERIPHERALS
|
||||
// region uses the same 1GB portion of the address space as the GICD,
|
||||
// and thus shares the same set of L2 page tables
|
||||
//
|
||||
// Get CS3_PERIPHERALS address into x4 and calculate the offset into the
|
||||
// L2 tables
|
||||
//
|
||||
ldr x4, =Image$$CS3_PERIPHERALS$$ZI$$Base
|
||||
ubfx x2, x4, #21, #9
|
||||
|
||||
//
|
||||
// set x1 to the required page table attributes, then orr
|
||||
// in the start address (modulo 2MB)
|
||||
//
|
||||
// L2 tables in our configuration cover 2MB per entry - map
|
||||
// memory as NS Device-nGnRE (MAIR[2]) with a flat VA->PA
|
||||
// translation
|
||||
//
|
||||
bic x4, x4, #((1 << 21) - 1) // start address mod 2MB
|
||||
ldr x1, =(TT_S1_ATTR_BLOCK | \
|
||||
(2 << TT_S1_ATTR_MATTR_LSB) | \
|
||||
TT_S1_ATTR_NS | \
|
||||
TT_S1_ATTR_AP_RW_PL1 | \
|
||||
TT_S1_ATTR_AF | \
|
||||
TT_S1_ATTR_nG)
|
||||
orr x1, x1, x4
|
||||
|
||||
//
|
||||
// only a single L2 entry again - write it
|
||||
//
|
||||
str x1, [x24, x2, lsl #3]
|
||||
|
||||
//
|
||||
// issue a barrier to ensure all table entry writes are complete
|
||||
//
|
||||
dsb ish
|
||||
|
||||
//
|
||||
// Enable the MMU. Caches will be enabled later, after scatterloading.
|
||||
//
|
||||
mrs x1, SCTLR_EL1
|
||||
orr x1, x1, #SCTLR_ELx_M
|
||||
bic x1, x1, #SCTLR_ELx_A // Disable alignment fault checking. To enable, change bic to orr
|
||||
msr SCTLR_EL1, x1
|
||||
isb
|
||||
|
||||
//
|
||||
// Branch to C library init code
|
||||
//
|
||||
b __main
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// AArch64 Arm C library startup add-in:
|
||||
|
||||
// The Arm Architecture Reference Manual for Armv8-A states:
|
||||
//
|
||||
// Instruction accesses to Non-cacheable Normal memory can be held in instruction caches.
|
||||
// Correspondingly, the sequence for ensuring that modifications to instructions are available
|
||||
// for execution must include invalidation of the modified locations from the instruction cache,
|
||||
// even if the instructions are held in Normal Non-cacheable memory.
|
||||
// This includes cases where the instruction cache is disabled.
|
||||
//
|
||||
// To invalidate the AArch64 instruction cache after scatter-loading and before initialization of the stack and heap,
|
||||
// it is necessary for the user to:
|
||||
//
|
||||
// * Implement instruction cache invalidation code in _platform_pre_stackheap_init.
|
||||
// * Ensure all code on the path from the program entry up to and including _platform_pre_stackheap_init is located in a root region.
|
||||
//
|
||||
// In this example, this function is only called once, by the primary core
|
||||
|
||||
.global _platform_pre_stackheap_init
|
||||
.type _platform_pre_stackheap_init, "function"
|
||||
.cfi_startproc
|
||||
_platform_pre_stackheap_init:
|
||||
dsb ish // ensure all previous stores have completed before invalidating
|
||||
ic ialluis // I cache invalidate all inner shareable to PoU (which includes secondary cores)
|
||||
dsb ish // ensure completion on inner shareable domain (which includes secondary cores)
|
||||
isb
|
||||
|
||||
// Scatter-loading is complete, so enable the caches here, so that the C-library's mutex initialization later will work
|
||||
mrs x1, SCTLR_EL1
|
||||
orr x1, x1, #SCTLR_ELx_C
|
||||
orr x1, x1, #SCTLR_ELx_I
|
||||
msr SCTLR_EL1, x1
|
||||
isb
|
||||
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// EL1 - secondary CPU init code
|
||||
//
|
||||
// This code is run on CPUs 1, 2, 3 etc....
|
||||
// ------------------------------------------------------------
|
||||
|
||||
.global el1_secondary
|
||||
.type el1_secondary, "function"
|
||||
el1_secondary:
|
||||
|
||||
//
|
||||
// the primary CPU is going to use SGI 15 as a wakeup event
|
||||
// to let us know when it is OK to proceed, so prepare for
|
||||
// receiving that interrupt
|
||||
//
|
||||
// NS interrupt priorities run from 0 to 15, with 15 being
|
||||
// too low a priority to ever raise an interrupt, so let's
|
||||
// use 14
|
||||
//
|
||||
mov w0, w20
|
||||
mov w1, #15
|
||||
mov w2, #14 << 4 // we're in NS world, so 4 bits of priority,
|
||||
// 8-bit field, - 4 = 4-bit shift
|
||||
bl SetPrivateIntPriority
|
||||
|
||||
mov w0, w20
|
||||
mov w1, #15
|
||||
bl EnablePrivateInt
|
||||
|
||||
//
|
||||
// set priority mask as low as possible; although,being in the
|
||||
// NS World, we can't set bit[7] of the priority, we still
|
||||
// write all 8-bits of priority to an ICC register
|
||||
//
|
||||
mov x0, #31 << 3
|
||||
msr ICC_PMR_EL1, x0
|
||||
|
||||
//
|
||||
// set global enable and wait for our interrupt to arrive
|
||||
//
|
||||
mov x0, #1
|
||||
msr ICC_IGRPEN1_EL1, x0
|
||||
isb
|
||||
|
||||
loop_wfi:
|
||||
dsb SY // Clear all pending data accesses
|
||||
wfi // Go to sleep
|
||||
|
||||
//
|
||||
// something woke us from our wait, was it the required interrupt?
|
||||
//
|
||||
mov w0, w20
|
||||
mov w1, #15
|
||||
bl GetPrivateIntPending
|
||||
cbz w0, loop_wfi
|
||||
|
||||
//
|
||||
// it was - there's no need to actually take the interrupt,
|
||||
// so just clear it
|
||||
//
|
||||
mov w0, w20
|
||||
mov w1, #15
|
||||
bl ClearPrivateIntPending
|
||||
|
||||
//
|
||||
// Enable the MMU and caches
|
||||
//
|
||||
mrs x1, SCTLR_EL1
|
||||
orr x1, x1, #SCTLR_ELx_M
|
||||
orr x1, x1, #SCTLR_ELx_C
|
||||
orr x1, x1, #SCTLR_ELx_I
|
||||
bic x1, x1, #SCTLR_ELx_A // Disable alignment fault checking. To enable, change bic to orr
|
||||
msr SCTLR_EL1, x1
|
||||
isb
|
||||
|
||||
//
|
||||
// Branch to thread start
|
||||
//
|
||||
//B MainApp
|
||||
b __main
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/* Bare-metal example for Armv8-A FVP Base model */
|
||||
|
||||
/* Timer and interrupts */
|
||||
|
||||
/* Copyright (c) 2016-2018 Arm Limited (or its affiliates). All rights reserved. */
|
||||
/* Use, modification and redistribution of this file is subject to your possession of a */
|
||||
/* valid End User License Agreement for the Arm Product of which these examples are part of */
|
||||
/* and your compliance with all applicable terms and conditions of such licence agreement. */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "GICv3.h"
|
||||
#include "GICv3_gicc.h"
|
||||
#include "sp804_timer.h"
|
||||
|
||||
void _tx_timer_interrupt(void);
|
||||
|
||||
// LED Base address
|
||||
#define LED_BASE (volatile unsigned int *)0x1C010008
|
||||
|
||||
|
||||
void nudge_leds(void) // Move LEDs along
|
||||
{
|
||||
static int state = 1;
|
||||
static int value = 1;
|
||||
|
||||
if (state)
|
||||
{
|
||||
int max = (1 << 7);
|
||||
value <<= 1;
|
||||
if (value == max)
|
||||
state = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
value >>= 1;
|
||||
if (value == 1)
|
||||
state = 1;
|
||||
}
|
||||
|
||||
*LED_BASE = value; // Update LEDs hardware
|
||||
}
|
||||
|
||||
|
||||
// Initialize Timer 0 and Interrupt Controller
|
||||
void init_timer(void)
|
||||
{
|
||||
// Enable interrupts
|
||||
__asm("MSR DAIFClr, #0xF");
|
||||
setICC_IGRPEN1_EL1(igrpEnable);
|
||||
|
||||
// Configure the SP804 timer to generate an interrupt
|
||||
setTimerBaseAddress(0x1C110000);
|
||||
initTimer(0x200, SP804_AUTORELOAD, SP804_GENERATE_IRQ);
|
||||
startTimer();
|
||||
|
||||
// The SP804 timer generates SPI INTID 34. Enable
|
||||
// this ID, and route it to core 0.0.0.0 (this one!)
|
||||
SetSPIRoute(34, 0, gicdirouter_ModeSpecific); // Route INTID 34 to 0.0.0.0 (this core)
|
||||
SetSPIPriority(34, 0); // Set INTID 34 to priority to 0
|
||||
ConfigureSPI(34, gicdicfgr_Level); // Set INTID 34 as level-sensitive
|
||||
EnableSPI(34); // Enable INTID 34
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
void irqHandler(void)
|
||||
{
|
||||
unsigned int ID;
|
||||
|
||||
ID = getICC_IAR1(); // readIntAck();
|
||||
|
||||
// Check for reserved IDs
|
||||
if ((1020 <= ID) && (ID <= 1023))
|
||||
{
|
||||
//printf("irqHandler() - Reserved INTID %d\n\n", ID);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(ID)
|
||||
{
|
||||
case 34:
|
||||
// Dual-Timer 0 (SP804)
|
||||
//printf("irqHandler() - External timer interrupt\n\n");
|
||||
nudge_leds();
|
||||
clearTimerIrq();
|
||||
|
||||
/* Call ThreadX timer interrupt processing. */
|
||||
_tx_timer_interrupt();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unexpected ID value
|
||||
//printf("irqHandler() - Unexpected INTID %d\n\n", ID);
|
||||
break;
|
||||
}
|
||||
|
||||
// Write the End of Interrupt register to tell the GIC
|
||||
// we've finished handling the interrupt
|
||||
setICC_EOIR1(ID); // writeAliasedEOI(ID);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
// Not actually used in this example, but provided for completeness
|
||||
|
||||
void fiqHandler(void)
|
||||
{
|
||||
unsigned int ID;
|
||||
unsigned int aliased = 0;
|
||||
|
||||
ID = getICC_IAR0(); // readIntAck();
|
||||
//printf("fiqHandler() - Read %d from IAR0\n", ID);
|
||||
|
||||
// Check for reserved IDs
|
||||
if ((1020 <= ID) && (ID <= 1023))
|
||||
{
|
||||
//printf("fiqHandler() - Reserved INTID %d\n\n", ID);
|
||||
ID = getICC_IAR1(); // readAliasedIntAck();
|
||||
//printf("fiqHandler() - Read %d from AIAR\n", ID);
|
||||
aliased = 1;
|
||||
|
||||
// If still spurious then simply return
|
||||
if ((1020 <= ID) && (ID <= 1023))
|
||||
return;
|
||||
}
|
||||
|
||||
switch(ID)
|
||||
{
|
||||
case 34:
|
||||
// Dual-Timer 0 (SP804)
|
||||
//printf("fiqHandler() - External timer interrupt\n\n");
|
||||
clearTimerIrq();
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unexpected ID value
|
||||
//printf("fiqHandler() - Unexpected INTID %d\n\n", ID);
|
||||
break;
|
||||
}
|
||||
|
||||
// Write the End of Interrupt register to tell the GIC
|
||||
// we've finished handling the interrupt
|
||||
// NOTE: If the ID was read from the Aliased IAR, then
|
||||
// the aliased EOI register must be used
|
||||
if (aliased == 0)
|
||||
setICC_EOIR0(ID); // writeEOI(ID);
|
||||
else
|
||||
setICC_EOIR1(ID); // writeAliasedEOI(ID);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
set semihosting enabled off
|
||||
@@ -0,0 +1,179 @@
|
||||
// ------------------------------------------------------------
|
||||
// Armv8-A AArch64 - Common helper functions
|
||||
//
|
||||
// Copyright (c) 2012-2019 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#include "v8_system.h"
|
||||
|
||||
.text
|
||||
.cfi_sections .debug_frame // put stack frame info into .debug_frame instead of .eh_frame
|
||||
|
||||
.global EnableCachesEL1
|
||||
.global DisableCachesEL1
|
||||
.global InvalidateUDCaches
|
||||
.global GetMIDR
|
||||
.global GetMPIDR
|
||||
.global GetAffinity
|
||||
.global GetCPUID
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
//
|
||||
// void EnableCachesEL1(void)
|
||||
//
|
||||
// enable Instruction and Data caches
|
||||
//
|
||||
.type EnableCachesEL1, "function"
|
||||
.cfi_startproc
|
||||
EnableCachesEL1:
|
||||
|
||||
mrs x0, SCTLR_EL1
|
||||
orr x0, x0, #SCTLR_ELx_I
|
||||
orr x0, x0, #SCTLR_ELx_C
|
||||
msr SCTLR_EL1, x0
|
||||
|
||||
isb
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
.type DisableCachesEL1, "function"
|
||||
.cfi_startproc
|
||||
DisableCachesEL1:
|
||||
|
||||
mrs x0, SCTLR_EL1
|
||||
bic x0, x0, #SCTLR_ELx_I
|
||||
bic x0, x0, #SCTLR_ELx_C
|
||||
msr SCTLR_EL1, x0
|
||||
|
||||
isb
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
//
|
||||
// void InvalidateUDCaches(void)
|
||||
//
|
||||
// Invalidate data and unified caches
|
||||
//
|
||||
.type InvalidateUDCaches, "function"
|
||||
.cfi_startproc
|
||||
InvalidateUDCaches:
|
||||
// From the Armv8-A Architecture Reference Manual
|
||||
|
||||
dmb ish // ensure all prior inner-shareable accesses have been observed
|
||||
|
||||
mrs x0, CLIDR_EL1
|
||||
and w3, w0, #0x07000000 // get 2 x level of coherence
|
||||
lsr w3, w3, #23
|
||||
cbz w3, finished
|
||||
mov w10, #0 // w10 = 2 x cache level
|
||||
mov w8, #1 // w8 = constant 0b1
|
||||
loop_level:
|
||||
add w2, w10, w10, lsr #1 // calculate 3 x cache level
|
||||
lsr w1, w0, w2 // extract 3-bit cache type for this level
|
||||
and w1, w1, #0x7
|
||||
cmp w1, #2
|
||||
b.lt next_level // no data or unified cache at this level
|
||||
msr CSSELR_EL1, x10 // select this cache level
|
||||
isb // synchronize change of csselr
|
||||
mrs x1, CCSIDR_EL1 // read ccsidr
|
||||
and w2, w1, #7 // w2 = log2(linelen)-4
|
||||
add w2, w2, #4 // w2 = log2(linelen)
|
||||
ubfx w4, w1, #3, #10 // w4 = max way number, right aligned
|
||||
clz w5, w4 // w5 = 32-log2(ways), bit position of way in dc operand
|
||||
lsl w9, w4, w5 // w9 = max way number, aligned to position in dc operand
|
||||
lsl w16, w8, w5 // w16 = amount to decrement way number per iteration
|
||||
loop_way:
|
||||
ubfx w7, w1, #13, #15 // w7 = max set number, right aligned
|
||||
lsl w7, w7, w2 // w7 = max set number, aligned to position in dc operand
|
||||
lsl w17, w8, w2 // w17 = amount to decrement set number per iteration
|
||||
loop_set:
|
||||
orr w11, w10, w9 // w11 = combine way number and cache number ...
|
||||
orr w11, w11, w7 // ... and set number for dc operand
|
||||
dc isw, x11 // do data cache invalidate by set and way
|
||||
subs w7, w7, w17 // decrement set number
|
||||
b.ge loop_set
|
||||
subs x9, x9, x16 // decrement way number
|
||||
b.ge loop_way
|
||||
next_level:
|
||||
add w10, w10, #2 // increment 2 x cache level
|
||||
cmp w3, w10
|
||||
b.gt loop_level
|
||||
dsb sy // ensure completion of previous cache maintenance operation
|
||||
isb
|
||||
finished:
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
//
|
||||
// ID Register functions
|
||||
//
|
||||
|
||||
.type GetMIDR, "function"
|
||||
.cfi_startproc
|
||||
GetMIDR:
|
||||
|
||||
mrs x0, MIDR_EL1
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
.type GetMPIDR, "function"
|
||||
.cfi_startproc
|
||||
GetMPIDR:
|
||||
|
||||
mrs x0, MPIDR_EL1
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
.type GetAffinity, "function"
|
||||
.cfi_startproc
|
||||
GetAffinity:
|
||||
|
||||
mrs x0, MPIDR_EL1
|
||||
ubfx x1, x0, #32, #8
|
||||
bfi w0, w1, #24, #8
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
.type GetCPUID, "function"
|
||||
.cfi_startproc
|
||||
GetCPUID:
|
||||
|
||||
mrs x0, MIDR_EL1
|
||||
ubfx x0, x0, #4, #12 // extract PartNum
|
||||
cmp x0, #0xD0D // Cortex-A77
|
||||
b.eq DynamIQ
|
||||
cmp x0, #0xD0B // Cortex-A76
|
||||
b.eq DynamIQ
|
||||
cmp x0, #0xD0A // Cortex-A75
|
||||
b.eq DynamIQ
|
||||
cmp x0, #0xD05 // Cortex-A55
|
||||
b.eq DynamIQ
|
||||
b Others
|
||||
DynamIQ:
|
||||
mrs x0, MPIDR_EL1
|
||||
ubfx x0, x0, #MPIDR_EL1_AFF1_LSB, #MPIDR_EL1_AFF_WIDTH
|
||||
ret
|
||||
|
||||
Others:
|
||||
mrs x0, MPIDR_EL1
|
||||
ubfx x1, x0, #MPIDR_EL1_AFF0_LSB, #MPIDR_EL1_AFF_WIDTH
|
||||
ubfx x2, x0, #MPIDR_EL1_AFF1_LSB, #MPIDR_EL1_AFF_WIDTH
|
||||
add x0, x1, x2, LSL #2
|
||||
ret
|
||||
.cfi_endproc
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
*
|
||||
* Armv8-A AArch64 common helper functions
|
||||
*
|
||||
* Copyright (c) 2012-2014 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
|
||||
#ifndef V8_AARCH64_H
|
||||
#define V8_AARCH64_H
|
||||
|
||||
/*
|
||||
* Parameters for data barriers
|
||||
*/
|
||||
#define OSHLD 1
|
||||
#define OSHST 2
|
||||
#define OSH 3
|
||||
#define NSHLD 5
|
||||
#define NSHST 6
|
||||
#define NSH 7
|
||||
#define ISHLD 9
|
||||
#define ISHST 10
|
||||
#define ISH 11
|
||||
#define LD 13
|
||||
#define ST 14
|
||||
#define SY 15
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* function prototypes
|
||||
*/
|
||||
|
||||
/*
|
||||
* void InvalidateUDCaches(void)
|
||||
* invalidates all Unified and Data Caches
|
||||
*
|
||||
* Inputs
|
||||
* <none>
|
||||
*
|
||||
* Returns
|
||||
* <nothing>
|
||||
*
|
||||
* Side Effects
|
||||
* guarantees that all levels of cache will be invalidated before
|
||||
* returning to caller
|
||||
*/
|
||||
void InvalidateUDCaches(void);
|
||||
|
||||
/*
|
||||
* unsigned long long EnableCachesEL1(void)
|
||||
* enables I- and D- caches at EL1
|
||||
*
|
||||
* Inputs
|
||||
* <none>
|
||||
*
|
||||
* Returns
|
||||
* New value of SCTLR_EL1
|
||||
*
|
||||
* Side Effects
|
||||
* context will be synchronised before returning to caller
|
||||
*/
|
||||
unsigned long long EnableCachesEL1(void);
|
||||
|
||||
/*
|
||||
* unsigned long long GetMIDR(void)
|
||||
* returns the contents of MIDR_EL0
|
||||
*
|
||||
* Inputs
|
||||
* <none>
|
||||
*
|
||||
* Returns
|
||||
* MIDR_EL0
|
||||
*/
|
||||
unsigned long long GetMIDR(void);
|
||||
|
||||
/*
|
||||
* unsigned long long GetMPIDR(void)
|
||||
* returns the contents of MPIDR_EL0
|
||||
*
|
||||
* Inputs
|
||||
* <none>
|
||||
*
|
||||
* Returns
|
||||
* MPIDR_EL0
|
||||
*/
|
||||
unsigned long long GetMPIDR(void);
|
||||
|
||||
/*
|
||||
* unsigned int GetCPUID(void)
|
||||
* returns the Aff0 field of MPIDR_EL0
|
||||
*
|
||||
* Inputs
|
||||
* <none>
|
||||
*
|
||||
* Returns
|
||||
* MPIDR_EL0[7:0]
|
||||
*/
|
||||
unsigned int GetCPUID(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// Defines for v8 Memory Model
|
||||
//
|
||||
// Copyright (c) 2012-2019 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
#ifndef V8_MMU_H
|
||||
#define V8_MMU_H
|
||||
|
||||
//
|
||||
// Translation Control Register fields
|
||||
//
|
||||
// RGN field encodings
|
||||
//
|
||||
#define TCR_RGN_NC 0b00
|
||||
#define TCR_RGN_WBWA 0b01
|
||||
#define TCR_RGN_WT 0b10
|
||||
#define TCR_RGN_WBRA 0b11
|
||||
|
||||
//
|
||||
// Shareability encodings
|
||||
//
|
||||
#define TCR_SHARE_NONE 0b00
|
||||
#define TCR_SHARE_OUTER 0b10
|
||||
#define TCR_SHARE_INNER 0b11
|
||||
|
||||
//
|
||||
// Granule size encodings
|
||||
//
|
||||
#define TCR_GRANULE_4K 0b00
|
||||
#define TCR_GRANULE_64K 0b01
|
||||
#define TCR_GRANULE_16K 0b10
|
||||
|
||||
//
|
||||
// Physical Address sizes
|
||||
//
|
||||
#define TCR_SIZE_4G 0b000
|
||||
#define TCR_SIZE_64G 0b001
|
||||
#define TCR_SIZE_1T 0b010
|
||||
#define TCR_SIZE_4T 0b011
|
||||
#define TCR_SIZE_16T 0b100
|
||||
#define TCR_SIZE_256T 0b101
|
||||
|
||||
//
|
||||
// Translation Control Register fields
|
||||
//
|
||||
#define TCR_EL1_T0SZ_SHIFT 0
|
||||
#define TCR_EL1_EPD0 (1 << 7)
|
||||
#define TCR_EL1_IRGN0_SHIFT 8
|
||||
#define TCR_EL1_ORGN0_SHIFT 10
|
||||
#define TCR_EL1_SH0_SHIFT 12
|
||||
#define TCR_EL1_TG0_SHIFT 14
|
||||
|
||||
#define TCR_EL1_T1SZ_SHIFT 16
|
||||
#define TCR_EL1_A1 (1 << 22)
|
||||
#define TCR_EL1_EPD1 (1 << 23)
|
||||
#define TCR_EL1_IRGN1_SHIFT 24
|
||||
#define TCR_EL1_ORGN1_SHIFT 26
|
||||
#define TCR_EL1_SH1_SHIFT 28
|
||||
#define TCR_EL1_TG1_SHIFT 30
|
||||
#define TCR_EL1_IPS_SHIFT 32
|
||||
#define TCR_EL1_AS (1 << 36)
|
||||
#define TCR_EL1_TBI0 (1 << 37)
|
||||
#define TCR_EL1_TBI1 (1 << 38)
|
||||
|
||||
//
|
||||
// Stage 1 Translation Table descriptor fields
|
||||
//
|
||||
#define TT_S1_ATTR_FAULT (0b00 << 0)
|
||||
#define TT_S1_ATTR_BLOCK (0b01 << 0) // Level 1/2
|
||||
#define TT_S1_ATTR_TABLE (0b11 << 0) // Level 0/1/2
|
||||
#define TT_S1_ATTR_PAGE (0b11 << 0) // Level 3
|
||||
|
||||
#define TT_S1_ATTR_MATTR_LSB 2
|
||||
|
||||
#define TT_S1_ATTR_NS (1 << 5)
|
||||
|
||||
#define TT_S1_ATTR_AP_RW_PL1 (0b00 << 6)
|
||||
#define TT_S1_ATTR_AP_RW_ANY (0b01 << 6)
|
||||
#define TT_S1_ATTR_AP_RO_PL1 (0b10 << 6)
|
||||
#define TT_S1_ATTR_AP_RO_ANY (0b11 << 6)
|
||||
|
||||
#define TT_S1_ATTR_SH_NONE (0b00 << 8)
|
||||
#define TT_S1_ATTR_SH_OUTER (0b10 << 8)
|
||||
#define TT_S1_ATTR_SH_INNER (0b11 << 8)
|
||||
|
||||
#define TT_S1_ATTR_AF (1 << 10)
|
||||
#define TT_S1_ATTR_nG (1 << 11)
|
||||
|
||||
// OA bits [15:12] - If Armv8.2-LPA is implemented, bits[15:12] are bits[51:48]
|
||||
// and bits[47:16] are bits[47:16] of the output address for a page of memory
|
||||
|
||||
#define TT_S1_ATTR_nT (1 << 16) // Present if Armv8.4-TTRem is implemented, otherwise RES0
|
||||
|
||||
#define TT_S1_ATTR_DBM (1 << 51) // Present if Armv8.1-TTHM is implemented, otherwise RES0
|
||||
|
||||
#define TT_S1_ATTR_CONTIG (1 << 52)
|
||||
#define TT_S1_ATTR_PXN (1 << 53)
|
||||
#define TT_S1_ATTR_UXN (1 << 54)
|
||||
|
||||
// PBHA bits[62:59] - If Armv8.2-TTPBHA is implemented, hardware can use these bits
|
||||
// for IMPLEMENTATIONDEFINED purposes, otherwise IGNORED
|
||||
|
||||
#define TT_S1_MAIR_DEV_nGnRnE 0b00000000
|
||||
#define TT_S1_MAIR_DEV_nGnRE 0b00000100
|
||||
#define TT_S1_MAIR_DEV_nGRE 0b00001000
|
||||
#define TT_S1_MAIR_DEV_GRE 0b00001100
|
||||
|
||||
//
|
||||
// Inner and Outer Normal memory attributes use the same bit patterns
|
||||
// Outer attributes just need to be shifted up
|
||||
//
|
||||
#define TT_S1_MAIR_OUTER_SHIFT 4
|
||||
|
||||
#define TT_S1_MAIR_WT_TRANS_RA 0b0010
|
||||
|
||||
#define TT_S1_MAIR_WB_TRANS_RA 0b0110
|
||||
#define TT_S1_MAIR_WB_TRANS_RWA 0b0111
|
||||
|
||||
#define TT_S1_MAIR_WT_RA 0b1010
|
||||
|
||||
#define TT_S1_MAIR_WB_RA 0b1110
|
||||
#define TT_S1_MAIR_WB_RWA 0b1111
|
||||
|
||||
#endif // V8_MMU_H
|
||||
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// Defines for v8 System Registers
|
||||
//
|
||||
// Copyright (c) 2012-2016 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
#ifndef V8_SYSTEM_H
|
||||
#define V8_SYSTEM_H
|
||||
|
||||
//
|
||||
// AArch64 SPSR
|
||||
//
|
||||
#define AARCH64_SPSR_EL3h 0b1101
|
||||
#define AARCH64_SPSR_EL3t 0b1100
|
||||
#define AARCH64_SPSR_EL2h 0b1001
|
||||
#define AARCH64_SPSR_EL2t 0b1000
|
||||
#define AARCH64_SPSR_EL1h 0b0101
|
||||
#define AARCH64_SPSR_EL1t 0b0100
|
||||
#define AARCH64_SPSR_EL0t 0b0000
|
||||
#define AARCH64_SPSR_RW (1 << 4)
|
||||
#define AARCH64_SPSR_F (1 << 6)
|
||||
#define AARCH64_SPSR_I (1 << 7)
|
||||
#define AARCH64_SPSR_A (1 << 8)
|
||||
#define AARCH64_SPSR_D (1 << 9)
|
||||
#define AARCH64_SPSR_IL (1 << 20)
|
||||
#define AARCH64_SPSR_SS (1 << 21)
|
||||
#define AARCH64_SPSR_V (1 << 28)
|
||||
#define AARCH64_SPSR_C (1 << 29)
|
||||
#define AARCH64_SPSR_Z (1 << 30)
|
||||
#define AARCH64_SPSR_N (1 << 31)
|
||||
|
||||
//
|
||||
// Multiprocessor Affinity Register
|
||||
//
|
||||
#define MPIDR_EL1_AFF3_LSB 32
|
||||
#define MPIDR_EL1_U (1 << 30)
|
||||
#define MPIDR_EL1_MT (1 << 24)
|
||||
#define MPIDR_EL1_AFF2_LSB 16
|
||||
#define MPIDR_EL1_AFF1_LSB 8
|
||||
#define MPIDR_EL1_AFF0_LSB 0
|
||||
#define MPIDR_EL1_AFF_WIDTH 8
|
||||
|
||||
//
|
||||
// Data Cache Zero ID Register
|
||||
//
|
||||
#define DCZID_EL0_BS_LSB 0
|
||||
#define DCZID_EL0_BS_WIDTH 4
|
||||
#define DCZID_EL0_DZP_LSB 5
|
||||
#define DCZID_EL0_DZP (1 << 5)
|
||||
|
||||
//
|
||||
// System Control Register
|
||||
//
|
||||
#define SCTLR_EL1_UCI (1 << 26)
|
||||
#define SCTLR_ELx_EE (1 << 25)
|
||||
#define SCTLR_EL1_E0E (1 << 24)
|
||||
#define SCTLR_ELx_WXN (1 << 19)
|
||||
#define SCTLR_EL1_nTWE (1 << 18)
|
||||
#define SCTLR_EL1_nTWI (1 << 16)
|
||||
#define SCTLR_EL1_UCT (1 << 15)
|
||||
#define SCTLR_EL1_DZE (1 << 14)
|
||||
#define SCTLR_ELx_I (1 << 12)
|
||||
#define SCTLR_EL1_UMA (1 << 9)
|
||||
#define SCTLR_EL1_SED (1 << 8)
|
||||
#define SCTLR_EL1_ITD (1 << 7)
|
||||
#define SCTLR_EL1_THEE (1 << 6)
|
||||
#define SCTLR_EL1_CP15BEN (1 << 5)
|
||||
#define SCTLR_EL1_SA0 (1 << 4)
|
||||
#define SCTLR_ELx_SA (1 << 3)
|
||||
#define SCTLR_ELx_C (1 << 2)
|
||||
#define SCTLR_ELx_A (1 << 1)
|
||||
#define SCTLR_ELx_M (1 << 0)
|
||||
|
||||
//
|
||||
// Architectural Feature Access Control Register
|
||||
//
|
||||
#define CPACR_EL1_TTA (1 << 28)
|
||||
#define CPACR_EL1_FPEN (3 << 20)
|
||||
|
||||
//
|
||||
// Architectural Feature Trap Register
|
||||
//
|
||||
#define CPTR_ELx_TCPAC (1 << 31)
|
||||
#define CPTR_ELx_TTA (1 << 20)
|
||||
#define CPTR_ELx_TFP (1 << 10)
|
||||
|
||||
//
|
||||
// Secure Configuration Register
|
||||
//
|
||||
#define SCR_EL3_TWE (1 << 13)
|
||||
#define SCR_EL3_TWI (1 << 12)
|
||||
#define SCR_EL3_ST (1 << 11)
|
||||
#define SCR_EL3_RW (1 << 10)
|
||||
#define SCR_EL3_SIF (1 << 9)
|
||||
#define SCR_EL3_HCE (1 << 8)
|
||||
#define SCR_EL3_SMD (1 << 7)
|
||||
#define SCR_EL3_EA (1 << 3)
|
||||
#define SCR_EL3_FIQ (1 << 2)
|
||||
#define SCR_EL3_IRQ (1 << 1)
|
||||
#define SCR_EL3_NS (1 << 0)
|
||||
|
||||
//
|
||||
// Hypervisor Configuration Register
|
||||
//
|
||||
#define HCR_EL2_ID (1 << 33)
|
||||
#define HCR_EL2_CD (1 << 32)
|
||||
#define HCR_EL2_RW (1 << 31)
|
||||
#define HCR_EL2_TRVM (1 << 30)
|
||||
#define HCR_EL2_HVC (1 << 29)
|
||||
#define HCR_EL2_TDZ (1 << 28)
|
||||
|
||||
#endif // V8_SYSTEM_H
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// Simple utility routines for baremetal v8 code
|
||||
//
|
||||
// Copyright (c) 2013-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
#include "v8_system.h"
|
||||
|
||||
.text
|
||||
.cfi_sections .debug_frame // put stack frame info into .debug_frame instead of .eh_frame
|
||||
|
||||
//
|
||||
// void *ZeroBlock(void *blockPtr, unsigned int nBytes)
|
||||
//
|
||||
// Zero fill a block of memory
|
||||
// Fill memory pages or similar structures with zeros.
|
||||
// The byte count must be a multiple of the block fill size (16 bytes)
|
||||
//
|
||||
// Inputs:
|
||||
// blockPtr - base address of block to fill
|
||||
// nBytes - block size, in bytes
|
||||
//
|
||||
// Returns:
|
||||
// pointer to just filled block, NULL if nBytes is
|
||||
// incompatible with block fill size
|
||||
//
|
||||
.global ZeroBlock
|
||||
.type ZeroBlock, "function"
|
||||
.cfi_startproc
|
||||
ZeroBlock:
|
||||
|
||||
//
|
||||
// we fill data by steam, 16 bytes at a time: check that
|
||||
// blocksize is a multiple of that
|
||||
//
|
||||
ubfx x2, x1, #0, #4
|
||||
cbnz x2, incompatible
|
||||
|
||||
//
|
||||
// we already have one register full of zeros, get another
|
||||
//
|
||||
mov x3, x2
|
||||
|
||||
//
|
||||
// OK, set temporary pointer and away we go
|
||||
//
|
||||
add x0, x0, x1
|
||||
|
||||
loop0:
|
||||
subs x1, x1, #16
|
||||
stp x2, x3, [x0, #-16]!
|
||||
b.ne loop0
|
||||
|
||||
//
|
||||
// that's all - x0 will be back to its start value
|
||||
//
|
||||
ret
|
||||
|
||||
//
|
||||
// parameters are incompatible with block size - return
|
||||
// an indication that this is so
|
||||
//
|
||||
incompatible:
|
||||
mov x0,#0
|
||||
ret
|
||||
.cfi_endproc
|
||||
@@ -0,0 +1,252 @@
|
||||
// ------------------------------------------------------------
|
||||
// Armv8-A Vector tables
|
||||
//
|
||||
// Copyright (c) 2014-2016 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
|
||||
.global el1_vectors
|
||||
.global el2_vectors
|
||||
.global el3_vectors
|
||||
.global c0sync1
|
||||
.global irqHandler
|
||||
.global fiqHandler
|
||||
.global irqFirstLevelHandler
|
||||
.global fiqFirstLevelHandler
|
||||
|
||||
.section EL1VECTORS, "ax"
|
||||
.align 11
|
||||
|
||||
//
|
||||
// Current EL with SP0
|
||||
//
|
||||
el1_vectors:
|
||||
c0sync1: B c0sync1
|
||||
|
||||
.balign 0x80
|
||||
c0irq1: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
c0fiq1: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
c0serr1: B c0serr1
|
||||
|
||||
//
|
||||
// Current EL with SPx
|
||||
//
|
||||
.balign 0x80
|
||||
cxsync1: B cxsync1
|
||||
|
||||
.balign 0x80
|
||||
cxirq1: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
cxfiq1: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
cxserr1: B cxserr1
|
||||
|
||||
//
|
||||
// Lower EL using AArch64
|
||||
//
|
||||
.balign 0x80
|
||||
l64sync1: B l64sync1
|
||||
|
||||
.balign 0x80
|
||||
l64irq1: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l64fiq1: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l64serr1: B l64serr1
|
||||
|
||||
//
|
||||
// Lower EL using AArch32
|
||||
//
|
||||
.balign 0x80
|
||||
l32sync1: B l32sync1
|
||||
|
||||
.balign 0x80
|
||||
l32irq1: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l32fiq1: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l32serr1: B l32serr1
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
.section EL2VECTORS, "ax"
|
||||
.align 11
|
||||
|
||||
//
|
||||
// Current EL with SP0
|
||||
//
|
||||
el2_vectors:
|
||||
c0sync2: B c0sync2
|
||||
|
||||
.balign 0x80
|
||||
c0irq2: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
c0fiq2: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
c0serr2: B c0serr2
|
||||
|
||||
//
|
||||
// Current EL with SPx
|
||||
//
|
||||
.balign 0x80
|
||||
cxsync2: B cxsync2
|
||||
|
||||
.balign 0x80
|
||||
cxirq2: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
cxfiq2: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
cxserr2: B cxserr2
|
||||
|
||||
//
|
||||
// Lower EL using AArch64
|
||||
//
|
||||
.balign 0x80
|
||||
l64sync2: B l64sync2
|
||||
|
||||
.balign 0x80
|
||||
l64irq2: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l64fiq2: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l64serr2: B l64serr2
|
||||
|
||||
//
|
||||
// Lower EL using AArch32
|
||||
//
|
||||
.balign 0x80
|
||||
l32sync2: B l32sync2
|
||||
|
||||
.balign 0x80
|
||||
l32irq2: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l32fiq2: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l32serr2: B l32serr2
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
.section EL3VECTORS, "ax"
|
||||
.align 11
|
||||
|
||||
//
|
||||
// Current EL with SP0
|
||||
//
|
||||
el3_vectors:
|
||||
c0sync3: B c0sync3
|
||||
|
||||
.balign 0x80
|
||||
c0irq3: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
c0fiq3: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
c0serr3: B c0serr3
|
||||
|
||||
//
|
||||
// Current EL with SPx
|
||||
//
|
||||
.balign 0x80
|
||||
cxsync3: B cxsync3
|
||||
|
||||
.balign 0x80
|
||||
cxirq3: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
cxfiq3: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
cxserr3: B cxserr3
|
||||
|
||||
//
|
||||
// Lower EL using AArch64
|
||||
//
|
||||
.balign 0x80
|
||||
l64sync3: B l64sync3
|
||||
|
||||
.balign 0x80
|
||||
l64irq3: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l64fiq3: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l64serr3: B l64serr3
|
||||
|
||||
//
|
||||
// Lower EL using AArch32
|
||||
//
|
||||
.balign 0x80
|
||||
l32sync3: B l32sync3
|
||||
|
||||
.balign 0x80
|
||||
l32irq3: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l32fiq3: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l32serr3: B l32serr3
|
||||
|
||||
|
||||
.section InterruptHandlers, "ax"
|
||||
.balign 4
|
||||
|
||||
.type irqFirstLevelHandler, "function"
|
||||
irqFirstLevelHandler:
|
||||
MSR SPSel, 0
|
||||
STP x29, x30, [sp, #-16]!
|
||||
BL _tx_thread_context_save
|
||||
BL irqHandler
|
||||
B _tx_thread_context_restore
|
||||
|
||||
.type fiqFirstLevelHandler, "function"
|
||||
fiqFirstLevelHandler:
|
||||
STP x29, x30, [sp, #-16]!
|
||||
STP x18, x19, [sp, #-16]!
|
||||
STP x16, x17, [sp, #-16]!
|
||||
STP x14, x15, [sp, #-16]!
|
||||
STP x12, x13, [sp, #-16]!
|
||||
STP x10, x11, [sp, #-16]!
|
||||
STP x8, x9, [sp, #-16]!
|
||||
STP x6, x7, [sp, #-16]!
|
||||
STP x4, x5, [sp, #-16]!
|
||||
STP x2, x3, [sp, #-16]!
|
||||
STP x0, x1, [sp, #-16]!
|
||||
|
||||
BL fiqHandler
|
||||
|
||||
LDP x0, x1, [sp], #16
|
||||
LDP x2, x3, [sp], #16
|
||||
LDP x4, x5, [sp], #16
|
||||
LDP x6, x7, [sp], #16
|
||||
LDP x8, x9, [sp], #16
|
||||
LDP x10, x11, [sp], #16
|
||||
LDP x12, x13, [sp], #16
|
||||
LDP x14, x15, [sp], #16
|
||||
LDP x16, x17, [sp], #16
|
||||
LDP x18, x19, [sp], #16
|
||||
LDP x29, x30, [sp], #16
|
||||
ERET
|
||||
148
ports_arch/ARMv8-A/threadx/ports/ac6/example_build/tx/.cproject
Normal file
148
ports_arch/ARMv8-A/threadx/ports/ac6/example_build/tx/.cproject
Normal file
@@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
|
||||
<cconfiguration id="com.arm.eclipse.build.config.v6.lib.debug.base.332565915">
|
||||
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.lib.debug.base.332565915" moduleId="org.eclipse.cdt.core.settings" name="Debug">
|
||||
|
||||
<externalSettings/>
|
||||
|
||||
<extensions>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="com.arm.eclipse.builder.armcc.error" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<configuration artifactExtension="a" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.staticLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.staticLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.lib.debug.base.332565915" name="Debug" parent="com.arm.eclipse.build.config.v6.lib.debug.base">
|
||||
|
||||
<folderInfo id="com.arm.eclipse.build.config.v6.lib.debug.base.332565915." name="/" resourcePath="">
|
||||
|
||||
<toolChain id="com.arm.toolchain.v6.lib.debug.base.var.arm_compiler_6-6.174366982" name="Arm Compiler 6" superClass="com.arm.toolchain.v6.lib.debug.base.var.arm_compiler_6-6">
|
||||
|
||||
<option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.319260876" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-A35.AArch64.ARMv8.Neon.Crypto" valueType="string"/>
|
||||
|
||||
<targetPlatform id="com.arm.toolchain.v6.lib.debug.base.var.arm_compiler_6-6.174366982.1434986226" name=""/>
|
||||
|
||||
<builder autoBuildTarget="all" buildPath="${workspace_loc:/tx}/Debug" cleanBuildTarget="clean" enableAutoBuild="false" enableCleanBuild="true" enabledIncrementalBuild="true" id="com.arm.toolchain.v6.builder.2017005160" incrementalBuildTarget="all" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="8" superClass="com.arm.toolchain.v6.builder"/>
|
||||
|
||||
<tool id="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.1905027615" name="Arm C Compiler 6" superClass="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6">
|
||||
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.cpu.317101671" name="CPU (-mcpu)" superClass="com.arm.tool.c.compiler.v6.base.option.cpu" useByScannerDiscovery="true" value="cortex-a35" valueType="string"/>
|
||||
|
||||
<option id="com.arm.tool.c.compiler.v6.base.options.preproc.enableToolSpecificSettings.1714523388" name="Enable tool specific settings" superClass="com.arm.tool.c.compiler.v6.base.options.preproc.enableToolSpecificSettings" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.tool.c.compiler.v6.base.option.defmac.1928960091" name="Define macro (-D)" superClass="com.arm.tool.c.compiler.v6.base.option.defmac" useByScannerDiscovery="false" valueType="definedSymbols">
|
||||
|
||||
<listOptionValue builtIn="false" value="STANDALONE"/>
|
||||
|
||||
<listOptionValue builtIn="false" value="ENABLE_ARM_FP"/>
|
||||
|
||||
</option>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.tool.c.compiler.v6.base.option.incpath.866578922" name="Include path (-I)" superClass="com.arm.tool.c.compiler.v6.base.option.incpath" useByScannerDiscovery="false" valueType="includePath">
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc_generic}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc_port}""/>
|
||||
|
||||
</option>
|
||||
|
||||
<option id="com.arm.tool.c.compiler.v6.base.options.debug.level.448503435" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.options.debug.level.std" valueType="enumerated"/>
|
||||
|
||||
<inputType id="com.arm.tool.c.compiler.v6.base.input.409900163" superClass="com.arm.tool.c.compiler.v6.base.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.tool.cpp.compiler.v6.base.var.arm_compiler_6-6.87976211" name="Arm C++ Compiler 6" superClass="com.arm.tool.cpp.compiler.v6.base.var.arm_compiler_6-6">
|
||||
|
||||
<option id="com.arm.tool.c.compiler.v6.base.options.debug.level.542056309" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.options.debug.level.std" valueType="enumerated"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.tool.assembler.v6.base.var.arm_compiler_6-6.567657544" name="Arm Assembler 6" superClass="com.arm.tool.assembler.v6.base.var.arm_compiler_6-6">
|
||||
|
||||
<option id="com.arm.tool.assembler.v6.base.option.cpu.230057138" name="CPU (-mcpu)" superClass="com.arm.tool.assembler.v6.base.option.cpu" useByScannerDiscovery="false" value="cortex-a35" valueType="string"/>
|
||||
|
||||
<option id="com.arm.tool.assembler.v6.base.options.preproc.enableToolSpecificSettings.2042679359" name="Enable tool specific settings" superClass="com.arm.tool.assembler.v6.base.options.preproc.enableToolSpecificSettings" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
|
||||
<option id="com.arm.tool.assembler.v6.base.options.debug.level.481373844" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" useByScannerDiscovery="false" value="com.arm.tool.assembler.v6.base.options.debug.level.std" valueType="enumerated"/>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.tool.assembler.v6.base.option.defmac.323399329" name="Define macro (-D)" superClass="com.arm.tool.assembler.v6.base.option.defmac" useByScannerDiscovery="false" valueType="definedSymbols">
|
||||
|
||||
<listOptionValue builtIn="false" value="EL1"/>
|
||||
|
||||
</option>
|
||||
|
||||
<inputType id="com.arm.tool.assembler.v6.base.input.424570744" superClass="com.arm.tool.assembler.v6.base.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.tool.c.linker.v6.base.var.arm_compiler_6-6.302832878" name="Arm Linker 6" superClass="com.arm.tool.c.linker.v6.base.var.arm_compiler_6-6"/>
|
||||
|
||||
<tool id="com.arm.tool.librarian.v6.base.var.arm_compiler_6-6.1893346540" name="Arm Librarian 6" superClass="com.arm.tool.librarian.v6.base.var.arm_compiler_6-6"/>
|
||||
|
||||
</toolChain>
|
||||
|
||||
</folderInfo>
|
||||
|
||||
<sourceEntries>
|
||||
|
||||
<entry excluding="src_generic/tx_misra.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
|
||||
</sourceEntries>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
|
||||
</cconfiguration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<project id="tx.com.arm.eclipse.build.project.v6.lib.1209080418" name="Static Library"/>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
|
||||
<storageModule moduleId="refreshScope" versionNumber="2">
|
||||
|
||||
<configuration configurationName="Debug">
|
||||
|
||||
<resource resourceType="PROJECT" workspacePath="/tx"/>
|
||||
|
||||
</configuration>
|
||||
|
||||
<configuration configurationName="Release">
|
||||
|
||||
<resource resourceType="PROJECT" workspacePath="/tx"/>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
|
||||
<storageModule moduleId="com.arm.projectSettings" version="6.0.0"/>
|
||||
|
||||
</cproject>
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>tx</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
<linkedResources>
|
||||
<link>
|
||||
<name>inc_generic</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common/inc</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>inc_port</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/inc</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src_generic</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common/src</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src_port</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/src</locationURI>
|
||||
</link>
|
||||
</linkedResources>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,108 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Initialize */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_initialize_low_level ARMv8-A */
|
||||
/* 6.1.10 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for any low-level processor */
|
||||
/* initialization, including setting up interrupt vectors, setting */
|
||||
/* up a periodic timer interrupt source, saving the system stack */
|
||||
/* pointer for use in ISR processing later, and finding the first */
|
||||
/* available RAM memory address for tx_application_define. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_initialize_low_level(VOID)
|
||||
// {
|
||||
.global _tx_initialize_low_level
|
||||
.type _tx_initialize_low_level, @function
|
||||
_tx_initialize_low_level:
|
||||
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
|
||||
|
||||
/* Save the system stack pointer. */
|
||||
// _tx_thread_system_stack_ptr = (VOID_PTR) (sp);
|
||||
|
||||
LDR x0, =_tx_thread_system_stack_ptr // Pickup address of system stack ptr
|
||||
MOV x1, sp // Pickup SP
|
||||
SUB x1, x1, #15 //
|
||||
BIC x1, x1, #0xF // Get 16-bit alignment
|
||||
STR x1, [x0] // Store system stack
|
||||
|
||||
/* Save the first available memory address. */
|
||||
// _tx_initialize_unused_memory = (VOID_PTR) Image$$ZI$$Limit;
|
||||
|
||||
LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr
|
||||
LDR x1, =zi_limit // Pickup unused memory address
|
||||
LDR x1, [x1] //
|
||||
STR x1, [x0] // Store unused memory address
|
||||
|
||||
/* Done, return to caller. */
|
||||
|
||||
RET // Return to caller
|
||||
// }
|
||||
|
||||
|
||||
zi_limit:
|
||||
.quad (Image$$TOP_OF_RAM$$Base)
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
|
||||
<cconfiguration id="com.arm.eclipse.build.config.v6.exe.debug.base.515451048">
|
||||
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.exe.debug.base.515451048" moduleId="org.eclipse.cdt.core.settings" name="Debug">
|
||||
|
||||
<externalSettings/>
|
||||
|
||||
<extensions>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<configuration artifactExtension="axf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.exe.debug.base.515451048" name="Debug" parent="com.arm.eclipse.build.config.v6.exe.debug.base">
|
||||
|
||||
<folderInfo id="com.arm.eclipse.build.config.v6.exe.debug.base.515451048." name="/" resourcePath="">
|
||||
|
||||
<toolChain id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.toolchain.var.gcc-8.3.0-aarch64-elf.33749088" name="GCC 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.toolchain.var.gcc-8.3.0-aarch64-elf">
|
||||
|
||||
<targetPlatform id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.toolchain.var.gcc-8.3.0-aarch64-elf.33749088.1343346543" name=""/>
|
||||
|
||||
<builder buildPath="${workspace_loc:/sample_threadx}/Debug" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.target.builder.910370896" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="8" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.target.builder"/>
|
||||
|
||||
<tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.var.gcc-8.3.0-aarch64-elf.1331565505" name="GCC C Compiler 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.var.gcc-8.3.0-aarch64-elf">
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.includepath.831465095" name="Include paths (-I)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.includepath" useByScannerDiscovery="false" valueType="includePath">
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/tx/inc_generic}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/tx/inc_port}""/>
|
||||
|
||||
</option>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.defsym.1613866201" name="Defined symbols (-D)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.defsym" useByScannerDiscovery="false" valueType="definedSymbols">
|
||||
|
||||
<listOptionValue builtIn="false" value="STANDALONE"/>
|
||||
|
||||
</option>
|
||||
|
||||
<option defaultValue="gnu.c.optimization.level.none" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt.1769854265" name="Optimization Level" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt" useByScannerDiscovery="false" valueType="enumerated"/>
|
||||
|
||||
<option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.debug.268949876" name="Debug Level" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.debug" useByScannerDiscovery="false"/>
|
||||
|
||||
<option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.cpu.1607040325" name="CPU (-mcpu)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.cpu" useByScannerDiscovery="false" value="" valueType="string"/>
|
||||
|
||||
<inputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.input.301538030" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.compiler.var.gcc-8.3.0-aarch64-elf.64294854" name="GCC C++ Compiler 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.compiler.var.gcc-8.3.0-aarch64-elf">
|
||||
|
||||
<option defaultValue="gnu.c.optimization.level.none" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt.1835980884" name="Optimization Level" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt" useByScannerDiscovery="false" valueType="enumerated"/>
|
||||
|
||||
<option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.debug.788212214" name="Debug Level" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.debug" useByScannerDiscovery="false"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool command="aarch64-elf-gcc.exe" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.var.gcc-8.3.0-aarch64-elf.1804365799" name="GCC Assembler 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.var.gcc-8.3.0-aarch64-elf">
|
||||
|
||||
<option defaultValue="true" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.debug.490655419" name="Generate debugging information (-g)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.debug" useByScannerDiscovery="false" valueType="boolean"/>
|
||||
|
||||
<option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.cpu.694327385" name="CPU (-mcpu)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.cpu" useByScannerDiscovery="false" value="" valueType="string"/>
|
||||
|
||||
<inputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.input.883450564" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.var.gcc-8.3.0-aarch64-elf.891273559" name="GCC C Linker 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.var.gcc-8.3.0-aarch64-elf">
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.libs.654731770" name="Libraries (-l)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.libs" useByScannerDiscovery="false" valueType="libs">
|
||||
|
||||
<listOptionValue builtIn="false" value="tx"/>
|
||||
|
||||
</option>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.libsearch.764636049" name="Library search path (-L)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.libsearch" useByScannerDiscovery="false" valueType="libPaths">
|
||||
|
||||
<listOptionValue builtIn="false" value=""..\..\tx\Debug""/>
|
||||
|
||||
</option>
|
||||
|
||||
<option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.script.1545347593" name="Linker script" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.script" useByScannerDiscovery="false" value="..\sample_threadx.ld" valueType="string"/>
|
||||
|
||||
<option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.flags.846498594" name="Other flags" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.flags" useByScannerDiscovery="false" value="--specs=rdimon.specs" valueType="string"/>
|
||||
|
||||
<inputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.input.1672586300" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.input">
|
||||
|
||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
||||
|
||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
||||
|
||||
</inputType>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.linker.var.gcc-8.3.0-aarch64-elf.2107716357" name="GCC C++ Linker 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.linker.var.gcc-8.3.0-aarch64-elf"/>
|
||||
|
||||
<tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.archiver.var.gcc-8.3.0-aarch64-elf.1675872554" name="GCC Archiver 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.archiver.var.gcc-8.3.0-aarch64-elf"/>
|
||||
|
||||
</toolChain>
|
||||
|
||||
</folderInfo>
|
||||
|
||||
<sourceEntries>
|
||||
|
||||
<entry excluding="startup_el3.S|startup_el2.S|startup_el1.S|startup_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
|
||||
</sourceEntries>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
|
||||
</cconfiguration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<project id="sample_threadx.com.arm.eclipse.build.project.v6.exe.1027551600" name="Executable"/>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
|
||||
<storageModule moduleId="refreshScope" versionNumber="2">
|
||||
|
||||
<configuration configurationName="Debug">
|
||||
|
||||
<resource resourceType="PROJECT" workspacePath="/sample_threadx"/>
|
||||
|
||||
</configuration>
|
||||
|
||||
<configuration configurationName="Release">
|
||||
|
||||
<resource resourceType="PROJECT" workspacePath="/sample_threadx"/>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
|
||||
<storageModule moduleId="com.arm.projectSettings" version="6.0.0"/>
|
||||
|
||||
</cproject>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>sample_threadx</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,561 @@
|
||||
/*
|
||||
* GICv3.h - data types and function prototypes for GICv3 utility routines
|
||||
*
|
||||
* Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#ifndef GICV3_h
|
||||
#define GICV3_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* extra flags for GICD enable
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
gicdctlr_EnableGrp0 = (1 << 0),
|
||||
gicdctlr_EnableGrp1NS = (1 << 1),
|
||||
gicdctlr_EnableGrp1A = (1 << 1),
|
||||
gicdctlr_EnableGrp1S = (1 << 2),
|
||||
gicdctlr_EnableAll = (1 << 2) | (1 << 1) | (1 << 0),
|
||||
gicdctlr_ARE_S = (1 << 4), /* Enable Secure state affinity routing */
|
||||
gicdctlr_ARE_NS = (1 << 5), /* Enable Non-Secure state affinity routing */
|
||||
gicdctlr_DS = (1 << 6), /* Disable Security support */
|
||||
gicdctlr_E1NWF = (1 << 7) /* Enable "1-of-N" wakeup model */
|
||||
} GICDCTLRFlags_t;
|
||||
|
||||
/*
|
||||
* modes for SPI routing
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
gicdirouter_ModeSpecific = 0,
|
||||
gicdirouter_ModeAny = (1 << 31)
|
||||
} GICDIROUTERBits_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
gicdicfgr_Level = 0,
|
||||
gicdicfgr_Edge = (1 << 1)
|
||||
} GICDICFGRBits_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
gicigroupr_G0S = 0,
|
||||
gicigroupr_G1NS = (1 << 0),
|
||||
gicigroupr_G1S = (1 << 2)
|
||||
} GICIGROUPRBits_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
gicrwaker_ProcessorSleep = (1 << 1),
|
||||
gicrwaker_ChildrenAsleep = (1 << 2)
|
||||
} GICRWAKERBits_t;
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* Utility macros & functions
|
||||
*/
|
||||
#define RANGE_LIMIT(x) ((sizeof(x) / sizeof((x)[0])) - 1)
|
||||
|
||||
static inline uint64_t gicv3PackAffinity(uint32_t aff3, uint32_t aff2,
|
||||
uint32_t aff1, uint32_t aff0)
|
||||
{
|
||||
/*
|
||||
* only need to cast aff3 to get type promotion for all affinities
|
||||
*/
|
||||
return ((((uint64_t)aff3 & 0xff) << 32) |
|
||||
((aff2 & 0xff) << 16) |
|
||||
((aff1 & 0xff) << 8) | aff0);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* GIC Distributor Function Prototypes
|
||||
*/
|
||||
|
||||
/*
|
||||
* ConfigGICD - configure GIC Distributor prior to enabling it
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* control - control flags
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* ConfigGICD() will set an absolute flags value, whereas
|
||||
* {En,Dis}ableGICD() will only {set,clear} the flag bits
|
||||
* passed as a parameter
|
||||
*/
|
||||
void ConfigGICD(GICDCTLRFlags_t flags);
|
||||
|
||||
/*
|
||||
* EnableGICD - top-level enable for GIC Distributor
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* flags - new control flags to set
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* ConfigGICD() will set an absolute flags value, whereas
|
||||
* {En,Dis}ableGICD() will only {set,clear} the flag bits
|
||||
* passed as a parameter
|
||||
*/
|
||||
void EnableGICD(GICDCTLRFlags_t flags);
|
||||
|
||||
/*
|
||||
* DisableGICD - top-level disable for GIC Distributor
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* flags - control flags to clear
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* ConfigGICD() will set an absolute flags value, whereas
|
||||
* {En,Dis}ableGICD() will only {set,clear} the flag bits
|
||||
* passed as a parameter
|
||||
*/
|
||||
void DisableGICD(GICDCTLRFlags_t flags);
|
||||
|
||||
/*
|
||||
* SyncAREinGICD - synchronise GICD Address Routing Enable bits
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* flags - absolute flag bits to set in GIC Distributor
|
||||
*
|
||||
* dosync - flag whether to wait for ARE bits to match passed
|
||||
* flag field (dosync = true), or whether to set absolute
|
||||
* flag bits (dosync = false)
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* This function is used to resolve a race in an MP system whereby secondary
|
||||
* CPUs cannot reliably program all Redistributor registers until the
|
||||
* primary CPU has enabled Address Routing. The primary CPU will call this
|
||||
* function with dosync = false, while the secondaries will call it with
|
||||
* dosync = true.
|
||||
*/
|
||||
void SyncAREinGICD(GICDCTLRFlags_t flags, uint32_t dosync);
|
||||
|
||||
/*
|
||||
* EnableSPI - enable a specific shared peripheral interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - which interrupt to enable
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void EnableSPI(uint32_t id);
|
||||
|
||||
/*
|
||||
* DisableSPI - disable a specific shared peripheral interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - which interrupt to disable
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void DisableSPI(uint32_t id);
|
||||
|
||||
/*
|
||||
* SetSPIPriority - configure the priority for a shared peripheral interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* priority - 8-bit priority to program (see note below)
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* The GICv3 architecture makes this function sensitive to the Security
|
||||
* context in terms of what effect it has on the programmed priority: no
|
||||
* attempt is made to adjust for the reduced priority range available
|
||||
* when making Non-Secure accesses to the GIC
|
||||
*/
|
||||
void SetSPIPriority(uint32_t id, uint32_t priority);
|
||||
|
||||
/*
|
||||
* GetSPIPriority - determine the priority for a shared peripheral interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* interrupt priority in the range 0 - 0xff
|
||||
*/
|
||||
uint32_t GetSPIPriority(uint32_t id);
|
||||
|
||||
/*
|
||||
* SetSPIRoute - specify interrupt routing when gicdctlr_ARE is enabled
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* affinity - prepacked "dotted quad" affinity routing. NOTE: use the
|
||||
* gicv3PackAffinity() helper routine to generate this input
|
||||
*
|
||||
* mode - select routing mode (specific affinity, or any recipient)
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPIRoute(uint32_t id, uint64_t affinity, GICDIROUTERBits_t mode);
|
||||
|
||||
/*
|
||||
* GetSPIRoute - read ARE-enabled interrupt routing information
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* routing configuration
|
||||
*/
|
||||
uint64_t GetSPIRoute(uint32_t id);
|
||||
|
||||
/*
|
||||
* SetSPITarget - configure the set of processor targets for an interrupt
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* target - 8-bit target bitmap
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPITarget(uint32_t id, uint32_t target);
|
||||
|
||||
/*
|
||||
* GetSPITarget - read the set of processor targets for an interrupt
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* 8-bit target bitmap
|
||||
*/
|
||||
uint32_t GetSPITarget(uint32_t id);
|
||||
|
||||
/*
|
||||
* ConfigureSPI - setup an interrupt as edge- or level-triggered
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* config - desired configuration
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void ConfigureSPI(uint32_t id, GICDICFGRBits_t config);
|
||||
|
||||
/*
|
||||
* SetSPIPending - mark an interrupt as pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPIPending(uint32_t id);
|
||||
|
||||
/*
|
||||
* ClearSPIPending - mark an interrupt as not pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void ClearSPIPending(uint32_t id);
|
||||
|
||||
/*
|
||||
* GetSPIPending - query whether an interrupt is pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* pending status
|
||||
*/
|
||||
uint32_t GetSPIPending(uint32_t id);
|
||||
|
||||
/*
|
||||
* SetSPISecurity - mark a shared peripheral interrupt as
|
||||
* security <group>
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - which interrupt to mark
|
||||
*
|
||||
* group - the group for the interrupt
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPISecurity(uint32_t id, GICIGROUPRBits_t group);
|
||||
|
||||
/*
|
||||
* SetSPISecurityBlock - mark a block of 32 shared peripheral
|
||||
* interrupts as security <group>
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* block - which block to mark (e.g. 1 = Ints 32-63)
|
||||
*
|
||||
* group - the group for the interrupts
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPISecurityBlock(uint32_t block, GICIGROUPRBits_t group);
|
||||
|
||||
/*
|
||||
* SetSPISecurityAll - mark all shared peripheral interrupts
|
||||
* as security <group>
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* group - the group for the interrupts
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPISecurityAll(GICIGROUPRBits_t group);
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* GIC Re-Distributor Function Prototypes
|
||||
*
|
||||
* The model for calling Redistributor functions is that, rather than
|
||||
* identifying the target redistributor with every function call, the
|
||||
* SelectRedistributor() function is used to identify which redistributor
|
||||
* is to be used for all functions until a different redistributor is
|
||||
* explicitly selected
|
||||
*/
|
||||
|
||||
/*
|
||||
* WakeupGICR - wake up a Redistributor
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to wakeup
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void WakeupGICR(uint32_t gicr);
|
||||
|
||||
/*
|
||||
* EnablePrivateInt - enable a private (SGI/PPI) interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - which interrupt to enable
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void EnablePrivateInt(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* DisablePrivateInt - disable a private (SGI/PPI) interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - which interrupt to disable
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void DisablePrivateInt(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* SetPrivateIntPriority - configure the priority for a private
|
||||
* (SGI/PPI) interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* priority - 8-bit priority to program (see note below)
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* The GICv3 architecture makes this function sensitive to the Security
|
||||
* context in terms of what effect it has on the programmed priority: no
|
||||
* attempt is made to adjust for the reduced priority range available
|
||||
* when making Non-Secure accesses to the GIC
|
||||
*/
|
||||
void SetPrivateIntPriority(uint32_t gicr, uint32_t id, uint32_t priority);
|
||||
|
||||
/*
|
||||
* GetPrivateIntPriority - configure the priority for a private
|
||||
* (SGI/PPI) interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Int priority
|
||||
*/
|
||||
uint32_t GetPrivateIntPriority(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* SetPrivateIntPending - mark a private (SGI/PPI) interrupt as pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetPrivateIntPending(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* ClearPrivateIntPending - mark a private (SGI/PPI) interrupt as not pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void ClearPrivateIntPending(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* GetPrivateIntPending - query whether a private (SGI/PPI) interrupt is pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* pending status
|
||||
*/
|
||||
uint32_t GetPrivateIntPending(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* SetPrivateIntSecurity - mark a private (SGI/PPI) interrupt as
|
||||
* security <group>
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - which interrupt to mark
|
||||
*
|
||||
* group - the group for the interrupt
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetPrivateIntSecurity(uint32_t gicr, uint32_t id, GICIGROUPRBits_t group);
|
||||
|
||||
/*
|
||||
* SetPrivateIntSecurityBlock - mark all 32 private (SGI/PPI)
|
||||
* interrupts as security <group>
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* group - the group for the interrupt
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetPrivateIntSecurityBlock(uint32_t gicr, GICIGROUPRBits_t group);
|
||||
|
||||
#endif /* ndef GICV3_h */
|
||||
|
||||
/* EOF GICv3.h */
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Aliases for GICv3 registers
|
||||
//
|
||||
// Copyright (c) 2016-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
#ifndef GICV3_ALIASES_H
|
||||
#define GICV3_ALIASES_H
|
||||
|
||||
#ifndef __clang__
|
||||
|
||||
/*
|
||||
* Mapping of MSR and MRS to physical and virtual CPU interface registers
|
||||
*
|
||||
* Arm Generic Interrupt Controller Architecture Specification
|
||||
* GIC architecture version 3.0 and version 4.0
|
||||
* Table 8-5
|
||||
*/
|
||||
#define ICC_AP0R0_EL1 S3_0_C12_C8_4
|
||||
#define ICC_AP0R1_EL1 S3_0_C12_C8_5
|
||||
#define ICC_AP0R2_EL1 S3_0_C12_C8_6
|
||||
#define ICC_AP0R3_EL1 S3_0_C12_C8_7
|
||||
|
||||
#define ICC_AP1R0_EL1 S3_0_C12_C9_0
|
||||
#define ICC_AP1R1_EL1 S3_0_C12_C9_1
|
||||
#define ICC_AP1R2_EL1 S3_0_C12_C9_2
|
||||
#define ICC_AP1R3_EL1 S3_0_C12_C9_3
|
||||
|
||||
#define ICC_ASGI1R_EL1 S3_0_C12_C11_6
|
||||
|
||||
#define ICC_BPR0_EL1 S3_0_C12_C8_3
|
||||
#define ICC_BPR1_EL1 S3_0_C12_C12_3
|
||||
|
||||
#define ICC_CTLR_EL1 S3_0_C12_C12_4
|
||||
#define ICC_CTLR_EL3 S3_6_C12_C12_4
|
||||
|
||||
#define ICC_DIR_EL1 S3_0_C12_C11_1
|
||||
|
||||
#define ICC_EOIR0_EL1 S3_0_C12_C8_1
|
||||
#define ICC_EOIR1_EL1 S3_0_C12_C12_1
|
||||
|
||||
#define ICC_HPPIR0_EL1 S3_0_C12_C8_2
|
||||
#define ICC_HPPIR1_EL1 S3_0_C12_C12_2
|
||||
|
||||
#define ICC_IAR0_EL1 S3_0_C12_C8_0
|
||||
#define ICC_IAR1_EL1 S3_0_C12_C12_0
|
||||
|
||||
#define ICC_IGRPEN0_EL1 S3_0_C12_C12_6
|
||||
#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7
|
||||
#define ICC_IGRPEN1_EL3 S3_6_C12_C12_7
|
||||
|
||||
#define ICC_PMR_EL1 S3_0_C4_C6_0
|
||||
#define ICC_RPR_EL1 S3_0_C12_C11_3
|
||||
|
||||
#define ICC_SGI0R_EL1 S3_0_C12_C11_7
|
||||
#define ICC_SGI1R_EL1 S3_0_C12_C11_5
|
||||
|
||||
#define ICC_SRE_EL1 S3_0_C12_C12_5
|
||||
#define ICC_SRE_EL2 S3_4_C12_C9_5
|
||||
#define ICC_SRE_EL3 S3_6_C12_C12_5
|
||||
|
||||
/*
|
||||
* Mapping of MSR and MRS to virtual interface control registers
|
||||
*
|
||||
* Arm Generic Interrupt Controller Architecture Specification
|
||||
* GIC architecture version 3.0 and version 4.0
|
||||
* Table 8-6
|
||||
*/
|
||||
#define ICH_AP0R0_EL2 S3_4_C12_C8_0
|
||||
#define ICH_AP0R1_EL2 S3_4_C12_C8_1
|
||||
#define ICH_AP0R2_EL2 S3_4_C12_C8_2
|
||||
#define ICH_AP0R3_EL2 S3_4_C12_C8_3
|
||||
|
||||
#define ICH_AP1R0_EL2 S3_4_C12_C9_0
|
||||
#define ICH_AP1R1_EL2 S3_4_C12_C9_1
|
||||
#define ICH_AP1R2_EL2 S3_4_C12_C9_2
|
||||
#define ICH_AP1R3_EL2 S3_4_C12_C9_3
|
||||
|
||||
#define ICH_HCR_EL2 S3_4_C12_C11_0
|
||||
|
||||
#define ICH_VTR_EL2 S3_4_C12_C11_1
|
||||
|
||||
#define ICH_MISR_EL2 S3_4_C12_C11_2
|
||||
|
||||
#define ICH_EISR_EL2 S3_4_C12_C11_3
|
||||
|
||||
#define ICH_ELRSR_EL2 S3_4_C12_C11_5
|
||||
|
||||
#define ICH_VMCR_EL2 S3_4_C12_C11_7
|
||||
|
||||
#define ICH_LR0_EL2 S3_4_C12_C12_0
|
||||
#define ICH_LR1_EL2 S3_4_C12_C12_1
|
||||
#define ICH_LR2_EL2 S3_4_C12_C12_2
|
||||
#define ICH_LR3_EL2 S3_4_C12_C12_3
|
||||
#define ICH_LR4_EL2 S3_4_C12_C12_4
|
||||
#define ICH_LR5_EL2 S3_4_C12_C12_5
|
||||
#define ICH_LR6_EL2 S3_4_C12_C12_6
|
||||
#define ICH_LR7_EL2 S3_4_C12_C12_7
|
||||
#define ICH_LR8_EL2 S3_4_C12_C13_0
|
||||
#define ICH_LR9_EL2 S3_4_C12_C13_1
|
||||
#define ICH_LR10_EL2 S3_4_C12_C13_2
|
||||
#define ICH_LR11_EL2 S3_4_C12_C13_3
|
||||
#define ICH_LR12_EL2 S3_4_C12_C13_4
|
||||
#define ICH_LR13_EL2 S3_4_C12_C13_5
|
||||
#define ICH_LR14_EL2 S3_4_C12_C13_6
|
||||
#define ICH_LR15_EL2 S3_4_C12_C13_7
|
||||
|
||||
#endif /* not __clang__ */
|
||||
|
||||
#endif /* GICV3_ALIASES */
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* GICv3_gicc.h - prototypes and inline functions for GICC system register operations
|
||||
*
|
||||
* Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#ifndef GICV3_gicc_h
|
||||
#define GICV3_gicc_h
|
||||
|
||||
#include "GICv3_aliases.h"
|
||||
|
||||
#define stringify_no_expansion(x) #x
|
||||
#define stringify(x) stringify_no_expansion(x)
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sreSRE = (1 << 0),
|
||||
sreDFB = (1 << 1),
|
||||
sreDIB = (1 << 2),
|
||||
sreEnable = (1 << 3)
|
||||
} ICC_SREBits_t;
|
||||
|
||||
static inline void setICC_SRE_EL1(ICC_SREBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_SRE_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_SRE_EL1(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_SRE_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline void setICC_SRE_EL2(ICC_SREBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_SRE_EL2)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_SRE_EL2(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_SRE_EL2)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline void setICC_SRE_EL3(ICC_SREBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_SRE_EL3)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_SRE_EL3(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_SRE_EL3)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
igrpEnable = (1 << 0),
|
||||
igrpEnableGrp1NS = (1 << 0),
|
||||
igrpEnableGrp1S = (1 << 2)
|
||||
} ICC_IGRPBits_t;
|
||||
|
||||
static inline void setICC_IGRPEN0_EL1(ICC_IGRPBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_IGRPEN0_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline void setICC_IGRPEN1_EL1(ICC_IGRPBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_IGRPEN1_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline void setICC_IGRPEN1_EL3(ICC_IGRPBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_IGRPEN1_EL3)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ctlrCBPR = (1 << 0),
|
||||
ctlrCBPR_EL1S = (1 << 0),
|
||||
ctlrEOImode = (1 << 1),
|
||||
ctlrCBPR_EL1NS = (1 << 1),
|
||||
ctlrEOImode_EL3 = (1 << 2),
|
||||
ctlrEOImode_EL1S = (1 << 3),
|
||||
ctlrEOImode_EL1NS = (1 << 4),
|
||||
ctlrRM = (1 << 5),
|
||||
ctlrPMHE = (1 << 6)
|
||||
} ICC_CTLRBits_t;
|
||||
|
||||
static inline void setICC_CTLR_EL1(ICC_CTLRBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_CTLR_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_CTLR_EL1(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_CTLR_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline void setICC_CTLR_EL3(ICC_CTLRBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_CTLR_EL3)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_CTLR_EL3(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_CTLR_EL3)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static inline uint64_t getICC_IAR0(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_IAR0_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_IAR1(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_IAR1_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline void setICC_EOIR0(uint32_t interrupt)
|
||||
{
|
||||
asm("msr "stringify(ICC_EOIR0_EL1)", %0\n; isb" :: "r" ((uint64_t)interrupt));
|
||||
}
|
||||
|
||||
static inline void setICC_EOIR1(uint32_t interrupt)
|
||||
{
|
||||
asm("msr "stringify(ICC_EOIR1_EL1)", %0\n; isb" :: "r" ((uint64_t)interrupt));
|
||||
}
|
||||
|
||||
static inline void setICC_DIR(uint32_t interrupt)
|
||||
{
|
||||
asm("msr "stringify(ICC_DIR_EL1)", %0\n; isb" :: "r" ((uint64_t)interrupt));
|
||||
}
|
||||
|
||||
static inline void setICC_PMR(uint32_t priority)
|
||||
{
|
||||
asm("msr "stringify(ICC_PMR_EL1)", %0\n; isb" :: "r" ((uint64_t)priority));
|
||||
}
|
||||
|
||||
static inline void setICC_BPR0(uint32_t binarypoint)
|
||||
{
|
||||
asm("msr "stringify(ICC_BPR0_EL1)", %0\n; isb" :: "r" ((uint64_t)binarypoint));
|
||||
}
|
||||
|
||||
static inline void setICC_BPR1(uint32_t binarypoint)
|
||||
{
|
||||
asm("msr "stringify(ICC_BPR1_EL1)", %0\n; isb" :: "r" ((uint64_t)binarypoint));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_BPR0(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_BPR0_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_BPR1(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_BPR1_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_RPR(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_RPR_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sgirIRMTarget = 0,
|
||||
sgirIRMAll = (1ull << 40)
|
||||
} ICC_SGIRBits_t;
|
||||
|
||||
static inline void setICC_SGI0R(uint8_t aff3, uint8_t aff2,
|
||||
uint8_t aff1, ICC_SGIRBits_t irm,
|
||||
uint16_t targetlist, uint8_t intid)
|
||||
{
|
||||
uint64_t packedbits = (((uint64_t)aff3 << 48) | ((uint64_t)aff2 << 32) | \
|
||||
((uint64_t)aff1 << 16) | irm | targetlist | \
|
||||
((uint64_t)(intid & 0x0f) << 24));
|
||||
|
||||
asm("msr "stringify(ICC_SGI0R_EL1)", %0\n; isb" :: "r" (packedbits));
|
||||
}
|
||||
|
||||
static inline void setICC_SGI1R(uint8_t aff3, uint8_t aff2,
|
||||
uint8_t aff1, ICC_SGIRBits_t irm,
|
||||
uint16_t targetlist, uint8_t intid)
|
||||
{
|
||||
uint64_t packedbits = (((uint64_t)aff3 << 48) | ((uint64_t)aff2 << 32) | \
|
||||
((uint64_t)aff1 << 16) | irm | targetlist | \
|
||||
((uint64_t)(intid & 0x0f) << 24));
|
||||
|
||||
asm("msr "stringify(ICC_SGI1R_EL1)", %0\n; isb" :: "r" (packedbits));
|
||||
}
|
||||
|
||||
static inline void setICC_ASGI1R(uint8_t aff3, uint8_t aff2,
|
||||
uint8_t aff1, ICC_SGIRBits_t irm,
|
||||
uint16_t targetlist, uint8_t intid)
|
||||
{
|
||||
uint64_t packedbits = (((uint64_t)aff3 << 48) | ((uint64_t)aff2 << 32) | \
|
||||
((uint64_t)aff1 << 16) | irm | targetlist | \
|
||||
((uint64_t)(intid & 0x0f) << 24));
|
||||
|
||||
asm("msr "stringify(ICC_ASGI1R_EL1)", %0\n; isb" :: "r" (packedbits));
|
||||
}
|
||||
|
||||
#endif /* ndef GICV3_gicc_h */
|
||||
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* GICv3_gicd.c - generic driver code for GICv3 distributor
|
||||
*
|
||||
* Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#include "GICv3.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t GICD_CTLR; // +0x0000
|
||||
const volatile uint32_t GICD_TYPER; // +0x0004
|
||||
const volatile uint32_t GICD_IIDR; // +0x0008
|
||||
|
||||
const volatile uint32_t padding0; // +0x000c
|
||||
|
||||
volatile uint32_t GICD_STATUSR; // +0x0010
|
||||
|
||||
const volatile uint32_t padding1[3]; // +0x0014
|
||||
|
||||
volatile uint32_t IMP_DEF[8]; // +0x0020
|
||||
|
||||
volatile uint32_t GICD_SETSPI_NSR; // +0x0040
|
||||
const volatile uint32_t padding2; // +0x0044
|
||||
volatile uint32_t GICD_CLRSPI_NSR; // +0x0048
|
||||
const volatile uint32_t padding3; // +0x004c
|
||||
volatile uint32_t GICD_SETSPI_SR; // +0x0050
|
||||
const volatile uint32_t padding4; // +0x0054
|
||||
volatile uint32_t GICD_CLRSPI_SR; // +0x0058
|
||||
|
||||
const volatile uint32_t padding5[3]; // +0x005c
|
||||
|
||||
volatile uint32_t GICD_SEIR; // +0x0068
|
||||
|
||||
const volatile uint32_t padding6[5]; // +0x006c
|
||||
|
||||
volatile uint32_t GICD_IGROUPR[32]; // +0x0080
|
||||
|
||||
volatile uint32_t GICD_ISENABLER[32]; // +0x0100
|
||||
volatile uint32_t GICD_ICENABLER[32]; // +0x0180
|
||||
volatile uint32_t GICD_ISPENDR[32]; // +0x0200
|
||||
volatile uint32_t GICD_ICPENDR[32]; // +0x0280
|
||||
volatile uint32_t GICD_ISACTIVER[32]; // +0x0300
|
||||
volatile uint32_t GICD_ICACTIVER[32]; // +0x0380
|
||||
|
||||
volatile uint8_t GICD_IPRIORITYR[1024]; // +0x0400
|
||||
volatile uint8_t GICD_ITARGETSR[1024]; // +0x0800
|
||||
volatile uint32_t GICD_ICFGR[64]; // +0x0c00
|
||||
volatile uint32_t GICD_IGRPMODR[32]; // +0x0d00
|
||||
const volatile uint32_t padding7[32]; // +0x0d80
|
||||
volatile uint32_t GICD_NSACR[64]; // +0x0e00
|
||||
|
||||
volatile uint32_t GICD_SGIR; // +0x0f00
|
||||
|
||||
const volatile uint32_t padding8[3]; // +0x0f04
|
||||
|
||||
volatile uint32_t GICD_CPENDSGIR[4]; // +0x0f10
|
||||
volatile uint32_t GICD_SPENDSGIR[4]; // +0x0f20
|
||||
|
||||
const volatile uint32_t padding9[52]; // +0x0f30
|
||||
const volatile uint32_t padding10[5120]; // +0x1000
|
||||
|
||||
volatile uint64_t GICD_IROUTER[1024]; // +0x6000
|
||||
} GICv3_distributor;
|
||||
|
||||
/*
|
||||
* use the scatter file to place GICD
|
||||
*/
|
||||
GICv3_distributor __attribute__((section(".gicd"))) gicd;
|
||||
|
||||
void ConfigGICD(GICDCTLRFlags_t flags)
|
||||
{
|
||||
gicd.GICD_CTLR = flags;
|
||||
}
|
||||
|
||||
void EnableGICD(GICDCTLRFlags_t flags)
|
||||
{
|
||||
gicd.GICD_CTLR |= flags;
|
||||
}
|
||||
|
||||
void DisableGICD(GICDCTLRFlags_t flags)
|
||||
{
|
||||
gicd.GICD_CTLR &= ~flags;
|
||||
}
|
||||
|
||||
void SyncAREinGICD(GICDCTLRFlags_t flags, uint32_t dosync)
|
||||
{
|
||||
if (dosync)
|
||||
{
|
||||
const uint32_t tmask = gicdctlr_ARE_S | gicdctlr_ARE_NS;
|
||||
const uint32_t tval = flags & tmask;
|
||||
|
||||
while ((gicd.GICD_CTLR & tmask) != tval)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
gicd.GICD_CTLR = flags;
|
||||
}
|
||||
|
||||
void EnableSPI(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ISENABLER has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ISENABLER);
|
||||
id &= 32 - 1;
|
||||
|
||||
gicd.GICD_ISENABLER[bank] = 1 << id;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DisableSPI(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ISENABLER has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ICENABLER);
|
||||
id &= 32 - 1;
|
||||
|
||||
gicd.GICD_ICENABLER[bank] = 1 << id;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void SetSPIPriority(uint32_t id, uint32_t priority)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_IPRIORITYR has one byte-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_IPRIORITYR);
|
||||
|
||||
gicd.GICD_IPRIORITYR[bank] = priority;
|
||||
}
|
||||
|
||||
uint32_t GetSPIPriority(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_IPRIORITYR has one byte-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_IPRIORITYR);
|
||||
|
||||
return (uint32_t)(gicd.GICD_IPRIORITYR[bank]);
|
||||
}
|
||||
|
||||
void SetSPIRoute(uint32_t id, uint64_t affinity, GICDIROUTERBits_t mode)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_IROUTER has one doubleword-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_IROUTER);
|
||||
|
||||
gicd.GICD_IROUTER[bank] = affinity | (uint64_t)mode;
|
||||
}
|
||||
|
||||
uint64_t GetSPIRoute(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_IROUTER has one doubleword-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_IROUTER);
|
||||
|
||||
return gicd.GICD_IROUTER[bank];
|
||||
}
|
||||
|
||||
void SetSPITarget(uint32_t id, uint32_t target)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ITARGETSR has one byte-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_ITARGETSR);
|
||||
|
||||
gicd.GICD_ITARGETSR[bank] = target;
|
||||
}
|
||||
|
||||
uint32_t GetSPITarget(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ITARGETSR has one byte-wide entry per interrupt
|
||||
*/
|
||||
/*
|
||||
* GICD_ITARGETSR has 4 interrupts per register, i.e. 8-bits of
|
||||
* target bitmap per register
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_ITARGETSR);
|
||||
|
||||
return (uint32_t)(gicd.GICD_ITARGETSR[bank]);
|
||||
}
|
||||
|
||||
void ConfigureSPI(uint32_t id, GICDICFGRBits_t config)
|
||||
{
|
||||
uint32_t bank, tmp;
|
||||
|
||||
/*
|
||||
* GICD_ICFGR has 16 interrupts per register, i.e. 2-bits of
|
||||
* configuration per register
|
||||
*/
|
||||
bank = (id >> 4) & RANGE_LIMIT(gicd.GICD_ICFGR);
|
||||
config &= 3;
|
||||
|
||||
id = (id & 0xf) << 1;
|
||||
|
||||
tmp = gicd.GICD_ICFGR[bank];
|
||||
tmp &= ~(3 << id);
|
||||
tmp |= config << id;
|
||||
gicd.GICD_ICFGR[bank] = tmp;
|
||||
}
|
||||
|
||||
void SetSPIPending(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ISPENDR has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ISPENDR);
|
||||
id &= 0x1f;
|
||||
|
||||
gicd.GICD_ISPENDR[bank] = 1 << id;
|
||||
}
|
||||
|
||||
void ClearSPIPending(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ICPENDR has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ICPENDR);
|
||||
id &= 0x1f;
|
||||
|
||||
gicd.GICD_ICPENDR[bank] = 1 << id;
|
||||
}
|
||||
|
||||
uint32_t GetSPIPending(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ICPENDR has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ICPENDR);
|
||||
id &= 0x1f;
|
||||
|
||||
return (gicd.GICD_ICPENDR[bank] >> id) & 1;
|
||||
}
|
||||
|
||||
void SetSPISecurity(uint32_t id, GICIGROUPRBits_t group)
|
||||
{
|
||||
uint32_t bank, groupmod;
|
||||
|
||||
/*
|
||||
* GICD_IGROUPR has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_IGROUPR);
|
||||
id &= 0x1f;
|
||||
|
||||
/*
|
||||
* the single group argument is split into two separate
|
||||
* registers, so filter out and remove the (new to gicv3)
|
||||
* group modifier bit
|
||||
*/
|
||||
groupmod = (group >> 1) & 1;
|
||||
group &= 1;
|
||||
|
||||
/*
|
||||
* either set or clear the Group bit for the interrupt as appropriate
|
||||
*/
|
||||
if (group)
|
||||
gicd.GICD_IGROUPR[bank] |= 1 << id;
|
||||
else
|
||||
gicd.GICD_IGROUPR[bank] &= ~(1 << id);
|
||||
|
||||
/*
|
||||
* now deal with groupmod
|
||||
*/
|
||||
if (groupmod)
|
||||
gicd.GICD_IGRPMODR[bank] |= 1 << id;
|
||||
else
|
||||
gicd.GICD_IGRPMODR[bank] &= ~(1 << id);
|
||||
}
|
||||
|
||||
void SetSPISecurityBlock(uint32_t block, GICIGROUPRBits_t group)
|
||||
{
|
||||
uint32_t groupmod;
|
||||
const uint32_t nbits = (sizeof group * 8) - 1;
|
||||
|
||||
/*
|
||||
* GICD_IGROUPR has 32 interrupts per register
|
||||
*/
|
||||
block &= RANGE_LIMIT(gicd.GICD_IGROUPR);
|
||||
|
||||
/*
|
||||
* get each bit of group config duplicated over all 32-bits in a word
|
||||
*/
|
||||
groupmod = (uint32_t)(((int32_t)group << (nbits - 1)) >> 31);
|
||||
group = (uint32_t)(((int32_t)group << nbits) >> 31);
|
||||
|
||||
/*
|
||||
* set the security state for this block of SPIs
|
||||
*/
|
||||
gicd.GICD_IGROUPR[block] = group;
|
||||
gicd.GICD_IGRPMODR[block] = groupmod;
|
||||
}
|
||||
|
||||
void SetSPISecurityAll(GICIGROUPRBits_t group)
|
||||
{
|
||||
uint32_t block;
|
||||
|
||||
/*
|
||||
* GICD_TYPER.ITLinesNumber gives (No. SPIS / 32) - 1, and we
|
||||
* want to iterate over all blocks excluding 0 (which are the
|
||||
* SGI/PPI interrupts, and not relevant here)
|
||||
*/
|
||||
for (block = (gicd.GICD_TYPER & ((1 << 5) - 1)); block > 0; --block)
|
||||
SetSPISecurityBlock(block, group);
|
||||
}
|
||||
|
||||
/* EOF GICv3_gicd.c */
|
||||
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* GICv3_gicr.c - generic driver code for GICv3 redistributor
|
||||
*
|
||||
* Copyright (c) 2014-2019 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#include "GICv3.h"
|
||||
|
||||
/*
|
||||
* physical LPI Redistributor register map
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t GICR_CTLR; // +0x0000 - RW - Redistributor Control Register
|
||||
const volatile uint32_t GICR_IIDR; // +0x0004 - RO - Implementer Identification Register
|
||||
const volatile uint32_t GICR_TYPER[2]; // +0x0008 - RO - Redistributor Type Register
|
||||
volatile uint32_t GICR_STATUSR; // +0x0010 - RW - Error Reporting Status Register, optional
|
||||
volatile uint32_t GICR_WAKER; // +0x0014 - RW - Redistributor Wake Register
|
||||
const volatile uint32_t padding1[2]; // +0x0018 - RESERVED
|
||||
#ifndef USE_GIC600
|
||||
volatile uint32_t IMPDEF1[8]; // +0x0020 - ?? - IMPLEMENTATION DEFINED
|
||||
#else
|
||||
volatile uint32_t GICR_FCTLR; // +0x0020 - RW - Function Control Register
|
||||
volatile uint32_t GICR_PWRR; // +0x0024 - RW - Power Management Control Register
|
||||
volatile uint32_t GICR_CLASS; // +0x0028 - RW - Class Register
|
||||
const volatile uint32_t padding2[5]; // +0x002C - RESERVED
|
||||
#endif
|
||||
volatile uint64_t GICR_SETLPIR; // +0x0040 - WO - Set LPI Pending Register
|
||||
volatile uint64_t GICR_CLRLPIR; // +0x0048 - WO - Clear LPI Pending Register
|
||||
const volatile uint32_t padding3[8]; // +0x0050 - RESERVED
|
||||
volatile uint64_t GICR_PROPBASER; // +0x0070 - RW - Redistributor Properties Base Address Register
|
||||
volatile uint64_t GICR_PENDBASER; // +0x0078 - RW - Redistributor LPI Pending Table Base Address Register
|
||||
const volatile uint32_t padding4[8]; // +0x0080 - RESERVED
|
||||
volatile uint64_t GICR_INVLPIR; // +0x00A0 - WO - Redistributor Invalidate LPI Register
|
||||
const volatile uint32_t padding5[2]; // +0x00A8 - RESERVED
|
||||
volatile uint64_t GICR_INVALLR; // +0x00B0 - WO - Redistributor Invalidate All Register
|
||||
const volatile uint32_t padding6[2]; // +0x00B8 - RESERVED
|
||||
volatile uint64_t GICR_SYNCR; // +0x00C0 - RO - Redistributor Synchronize Register
|
||||
const volatile uint32_t padding7[2]; // +0x00C8 - RESERVED
|
||||
const volatile uint32_t padding8[12]; // +0x00D0 - RESERVED
|
||||
volatile uint64_t IMPDEF2; // +0x0100 - WO - IMPLEMENTATION DEFINED
|
||||
const volatile uint32_t padding9[2]; // +0x0108 - RESERVED
|
||||
volatile uint64_t IMPDEF3; // +0x0110 - WO - IMPLEMENTATION DEFINED
|
||||
const volatile uint32_t padding10[2]; // +0x0118 - RESERVED
|
||||
} GICv3_redistributor_RD;
|
||||
|
||||
/*
|
||||
* SGI and PPI Redistributor register map
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const volatile uint32_t padding1[32]; // +0x0000 - RESERVED
|
||||
volatile uint32_t GICR_IGROUPR0; // +0x0080 - RW - Interrupt Group Registers (Security Registers in GICv1)
|
||||
const volatile uint32_t padding2[31]; // +0x0084 - RESERVED
|
||||
volatile uint32_t GICR_ISENABLER; // +0x0100 - RW - Interrupt Set-Enable Registers
|
||||
const volatile uint32_t padding3[31]; // +0x0104 - RESERVED
|
||||
volatile uint32_t GICR_ICENABLER; // +0x0180 - RW - Interrupt Clear-Enable Registers
|
||||
const volatile uint32_t padding4[31]; // +0x0184 - RESERVED
|
||||
volatile uint32_t GICR_ISPENDR; // +0x0200 - RW - Interrupt Set-Pending Registers
|
||||
const volatile uint32_t padding5[31]; // +0x0204 - RESERVED
|
||||
volatile uint32_t GICR_ICPENDR; // +0x0280 - RW - Interrupt Clear-Pending Registers
|
||||
const volatile uint32_t padding6[31]; // +0x0284 - RESERVED
|
||||
volatile uint32_t GICR_ISACTIVER; // +0x0300 - RW - Interrupt Set-Active Register
|
||||
const volatile uint32_t padding7[31]; // +0x0304 - RESERVED
|
||||
volatile uint32_t GICR_ICACTIVER; // +0x0380 - RW - Interrupt Clear-Active Register
|
||||
const volatile uint32_t padding8[31]; // +0x0184 - RESERVED
|
||||
volatile uint8_t GICR_IPRIORITYR[32]; // +0x0400 - RW - Interrupt Priority Registers
|
||||
const volatile uint32_t padding9[504]; // +0x0420 - RESERVED
|
||||
volatile uint32_t GICR_ICnoFGR[2]; // +0x0C00 - RW - Interrupt Configuration Registers
|
||||
const volatile uint32_t padding10[62]; // +0x0C08 - RESERVED
|
||||
volatile uint32_t GICR_IGRPMODR0; // +0x0D00 - RW - ????
|
||||
const volatile uint32_t padding11[63]; // +0x0D04 - RESERVED
|
||||
volatile uint32_t GICR_NSACR; // +0x0E00 - RW - Non-Secure Access Control Register
|
||||
} GICv3_redistributor_SGI;
|
||||
|
||||
/*
|
||||
* We have a multiplicity of GIC Redistributors; on the GIC-AEM and
|
||||
* GIC-500 they are arranged as one 128KB region per redistributor: one
|
||||
* 64KB page of GICR LPI registers, and one 64KB page of GICR Private
|
||||
* Int registers
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
GICv3_redistributor_RD RD_base;
|
||||
uint8_t padding[64 * 1024];
|
||||
} RDblock;
|
||||
|
||||
union
|
||||
{
|
||||
GICv3_redistributor_SGI SGI_base;
|
||||
uint8_t padding[64 * 1024];
|
||||
} SGIblock;
|
||||
} GICv3_GICR;
|
||||
|
||||
/*
|
||||
* use the scatter file to place GIC Redistributor base address
|
||||
*
|
||||
* although this code doesn't know how many Redistributor banks
|
||||
* a particular system will have, we declare gicrbase as an array
|
||||
* to avoid unwanted compiler optimisations when calculating the
|
||||
* base of a particular Redistributor bank
|
||||
*/
|
||||
static const GICv3_GICR gicrbase[2] __attribute__((section (".gicr")));
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* utility functions to calculate base of a particular
|
||||
* Redistributor bank
|
||||
*/
|
||||
|
||||
static inline GICv3_redistributor_RD *const getgicrRD(uint32_t gicr)
|
||||
{
|
||||
GICv3_GICR *const arraybase = (GICv3_GICR *const)&gicrbase;
|
||||
|
||||
return &((arraybase + gicr)->RDblock.RD_base);
|
||||
}
|
||||
|
||||
static inline GICv3_redistributor_SGI *const getgicrSGI(uint32_t gicr)
|
||||
{
|
||||
GICv3_GICR *arraybase = (GICv3_GICR *)(&gicrbase);
|
||||
|
||||
return &(arraybase[gicr].SGIblock.SGI_base);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
// This function walks a block of RDs to find one with the matching affinity
|
||||
uint32_t GetGICR(uint32_t affinity)
|
||||
{
|
||||
GICv3_redistributor_RD* gicr;
|
||||
uint32_t index = 0;
|
||||
|
||||
do
|
||||
{
|
||||
gicr = getgicrRD(index);
|
||||
if (gicr->GICR_TYPER[1] == affinity)
|
||||
return index;
|
||||
|
||||
index++;
|
||||
}
|
||||
while((gicr->GICR_TYPER[0] & (1<<4)) == 0); // Keep looking until GICR_TYPER.Last reports no more RDs in block
|
||||
|
||||
return 0xFFFFFFFF; // return -1 to signal not RD found
|
||||
}
|
||||
|
||||
void WakeupGICR(uint32_t gicr)
|
||||
{
|
||||
GICv3_redistributor_RD *const gicrRD = getgicrRD(gicr);
|
||||
#ifdef USE_GIC600
|
||||
//Power up Re-distributor for GIC-600
|
||||
gicrRD->GICR_PWRR = 0x2;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* step 1 - ensure GICR_WAKER.ProcessorSleep is off
|
||||
*/
|
||||
gicrRD->GICR_WAKER &= ~gicrwaker_ProcessorSleep;
|
||||
|
||||
/*
|
||||
* step 2 - wait for children asleep to be cleared
|
||||
*/
|
||||
while ((gicrRD->GICR_WAKER & gicrwaker_ChildrenAsleep) != 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* OK, GICR is go
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
void EnablePrivateInt(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
id &= 0x1f;
|
||||
|
||||
gicrSGI->GICR_ISENABLER = 1 << id;
|
||||
}
|
||||
|
||||
void DisablePrivateInt(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
id &= 0x1f;
|
||||
|
||||
gicrSGI->GICR_ICENABLER = 1 << id;
|
||||
}
|
||||
|
||||
void SetPrivateIntPriority(uint32_t gicr, uint32_t id, uint32_t priority)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICD_IPRIORITYR has one byte-wide entry per interrupt
|
||||
*/
|
||||
id &= RANGE_LIMIT(gicrSGI->GICR_IPRIORITYR);
|
||||
|
||||
gicrSGI->GICR_IPRIORITYR[id] = priority;
|
||||
}
|
||||
|
||||
uint32_t GetPrivateIntPriority(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICD_IPRIORITYR has one byte-wide entry per interrupt
|
||||
*/
|
||||
id &= RANGE_LIMIT(gicrSGI->GICR_IPRIORITYR);
|
||||
|
||||
return (uint32_t)(gicrSGI->GICR_IPRIORITYR[id]);
|
||||
}
|
||||
|
||||
void SetPrivateIntPending(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICR_ISPENDR is one 32-bit register
|
||||
*/
|
||||
id &= 0x1f;
|
||||
|
||||
gicrSGI->GICR_ISPENDR = 1 << id;
|
||||
}
|
||||
|
||||
void ClearPrivateIntPending(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICR_ICPENDR is one 32-bit register
|
||||
*/
|
||||
id &= 0x1f;
|
||||
|
||||
gicrSGI->GICR_ICPENDR = 1 << id;
|
||||
}
|
||||
|
||||
uint32_t GetPrivateIntPending(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICR_ISPENDR is one 32-bit register
|
||||
*/
|
||||
id &= 0x1f;
|
||||
|
||||
return (gicrSGI->GICR_ISPENDR >> id) & 0x01;
|
||||
}
|
||||
|
||||
void SetPrivateIntSecurity(uint32_t gicr, uint32_t id, GICIGROUPRBits_t group)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
uint32_t groupmod;
|
||||
|
||||
/*
|
||||
* GICR_IGROUPR0 is one 32-bit register
|
||||
*/
|
||||
id &= 0x1f;
|
||||
|
||||
/*
|
||||
* the single group argument is split into two separate
|
||||
* registers, so filter out and remove the (new to gicv3)
|
||||
* group modifier bit
|
||||
*/
|
||||
groupmod = (group >> 1) & 1;
|
||||
group &= 1;
|
||||
|
||||
/*
|
||||
* either set or clear the Group bit for the interrupt as appropriate
|
||||
*/
|
||||
if (group)
|
||||
gicrSGI->GICR_IGROUPR0 |= 1 << id;
|
||||
else
|
||||
gicrSGI->GICR_IGROUPR0 &= ~(1 << id);
|
||||
|
||||
/*
|
||||
* now deal with groupmod
|
||||
*/
|
||||
if (groupmod)
|
||||
gicrSGI->GICR_IGRPMODR0 |= 1 << id;
|
||||
else
|
||||
gicrSGI->GICR_IGRPMODR0 &= ~(1 << id);
|
||||
}
|
||||
|
||||
void SetPrivateIntSecurityBlock(uint32_t gicr, GICIGROUPRBits_t group)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
const uint32_t nbits = (sizeof group * 8) - 1;
|
||||
uint32_t groupmod;
|
||||
|
||||
/*
|
||||
* get each bit of group config duplicated over all 32-bits
|
||||
*/
|
||||
groupmod = (uint32_t)(((int32_t)group << (nbits - 1)) >> 31);
|
||||
group = (uint32_t)(((int32_t)group << nbits) >> 31);
|
||||
|
||||
/*
|
||||
* set the security state for this block of SPIs
|
||||
*/
|
||||
gicrSGI->GICR_IGROUPR0 = group;
|
||||
gicrSGI->GICR_IGRPMODR0 = groupmod;
|
||||
}
|
||||
|
||||
/* EOF GICv3_gicr.c */
|
||||
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// Armv8-A AArch64 - Basic Mutex Example
|
||||
// Includes the option (USE_LSE_ATOMIC) to use Large System Extension (LSE) atomics introduced in Armv8.1-A
|
||||
//
|
||||
// Copyright (c) 2012-2019 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
|
||||
.text
|
||||
.cfi_sections .debug_frame // put stack frame info into .debug_frame instead of .eh_frame
|
||||
|
||||
|
||||
.global _mutex_initialize
|
||||
.global _mutex_acquire
|
||||
.global _mutex_release
|
||||
|
||||
//
|
||||
// These routines implement the mutex management functions required for running
|
||||
// the Arm C library in a multi-threaded environment.
|
||||
//
|
||||
// They use a value of 0 to represent an unlocked mutex, and 1 for a locked mutex
|
||||
//
|
||||
// **********************************************************************
|
||||
//
|
||||
|
||||
.type _mutex_initialize, "function"
|
||||
.cfi_startproc
|
||||
_mutex_initialize:
|
||||
|
||||
//
|
||||
// mark the mutex as unlocked
|
||||
//
|
||||
mov w1, #0
|
||||
str w1, [x0]
|
||||
|
||||
//
|
||||
// we are running multi-threaded, so set a non-zero return
|
||||
// value (function prototype says use 1)
|
||||
//
|
||||
mov w0, #1
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
#if !defined(USE_LSE_ATOMIC)
|
||||
|
||||
.type _mutex_acquire, "function"
|
||||
.cfi_startproc
|
||||
_mutex_acquire:
|
||||
|
||||
//
|
||||
// send ourselves an event, so we don't stick on the wfe at the
|
||||
// top of the loop
|
||||
//
|
||||
sevl
|
||||
|
||||
//
|
||||
// wait until the mutex is available
|
||||
//
|
||||
loop:
|
||||
wfe
|
||||
ldaxr w1, [x0]
|
||||
cbnz w1, loop
|
||||
|
||||
//
|
||||
// mutex is (at least, it was) available - try to claim it
|
||||
//
|
||||
mov w1, #1
|
||||
stxr w2, w1, [x0]
|
||||
cbnz w2, loop
|
||||
|
||||
//
|
||||
// OK, we have the mutex, our work is done here
|
||||
//
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
.type _mutex_release, "function"
|
||||
.cfi_startproc
|
||||
_mutex_release:
|
||||
|
||||
mov w1, #0
|
||||
stlr w1, [x0]
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
#else // LSE version
|
||||
|
||||
.type _mutex_acquire, "function"
|
||||
.cfi_startproc
|
||||
_mutex_acquire:
|
||||
// This uses a "ticket lock". The lock is stored as a 32-bit value:
|
||||
// - the upper 16-bits record the thread's ticket number ("take a ticket")
|
||||
// - the lower 16-bits record the ticket being served ("now serving")
|
||||
|
||||
// atomically load then increment the thread's ticket number ("take a ticket")
|
||||
mov w3, #(1 << 16)
|
||||
ldadda w3, w1, [x0]
|
||||
|
||||
// is the ticket now being served?
|
||||
eor w2, w1, w1, ror #16
|
||||
cbz w2, loop_exit
|
||||
|
||||
// no, so wait for the ticket to be served
|
||||
|
||||
// send a local event to avoid missing an unlock before the exclusive load
|
||||
sevl
|
||||
|
||||
loop:
|
||||
wfe
|
||||
ldaxrh w3, [x0]
|
||||
eor w2, w3, w1, lsr #16
|
||||
cbnz w2, loop
|
||||
|
||||
//
|
||||
// OK, we have the mutex, our work is done here
|
||||
//
|
||||
loop_exit:
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
.type _mutex_release, "function"
|
||||
.cfi_startproc
|
||||
_mutex_release:
|
||||
mov w1, #1
|
||||
staddlh w1, [x0]
|
||||
ret
|
||||
.cfi_endproc
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Armv8-A AArch64 - Basic Mutex Example
|
||||
*
|
||||
* Copyright (c) 2012-2014 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#ifndef MP_MUTEX_H
|
||||
#define MP_MUTEX_H
|
||||
|
||||
/*
|
||||
* The Arm C library calls-out to these functions to manage multithreading.
|
||||
* They can also be called by user application code.
|
||||
*
|
||||
* Mutex type is specified by the Arm C library
|
||||
*
|
||||
* Declare function prototypes for libc mutex routines
|
||||
*/
|
||||
typedef signed int *mutex;
|
||||
|
||||
/*
|
||||
* int _mutex_initialize(mutex *m)
|
||||
*
|
||||
* Inputs
|
||||
* mutex *m - pointer to the 32-bit word associated with the mutex
|
||||
*
|
||||
* Returns
|
||||
* 0 - application is non-threaded
|
||||
* 1 - application is threaded
|
||||
* The C library uses the return result to indicate whether it is being used in a multithreaded environment.
|
||||
*/
|
||||
int _mutex_initialize(mutex *m);
|
||||
|
||||
/*
|
||||
* void _mutex_acquire(mutex *m)
|
||||
*
|
||||
* Inputs
|
||||
* mutex *m - pointer to the 32-bit word associated with the mutex
|
||||
*
|
||||
* Returns
|
||||
* <nothing>
|
||||
*
|
||||
* Side Effects
|
||||
* Routine does not return until the mutex has been claimed. A load-acquire
|
||||
* is used to guarantee that the mutex claim is properly ordered with
|
||||
* respect to any accesses to the resource protected by the mutex
|
||||
*/
|
||||
void _mutex_acquire(mutex *m);
|
||||
|
||||
/*
|
||||
* void _mutex_release(mutex *m)
|
||||
*
|
||||
* Inputs
|
||||
* mutex *m - pointer to the 32-bit word associated with the mutex
|
||||
*
|
||||
* Returns
|
||||
* <nothing>
|
||||
*
|
||||
* Side Effects
|
||||
* A store-release is used to guarantee that the mutex release is properly
|
||||
* ordered with respect any accesses to the resource protected by the mutex
|
||||
*/
|
||||
void _mutex_release(mutex *m);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// Private Peripheral Map for the v8 Architecture Envelope Model
|
||||
//
|
||||
// Copyright (c) 2012-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
#ifndef PPM_AEM_H
|
||||
#define PPM_AEM_H
|
||||
|
||||
//
|
||||
// Distributor layout
|
||||
//
|
||||
#define GICD_CTLR 0x0000
|
||||
#define GICD_TYPER 0x0004
|
||||
#define GICD_IIDR 0x0008
|
||||
#define GICD_IGROUP 0x0080
|
||||
#define GICD_ISENABLE 0x0100
|
||||
#define GICD_ICENABLE 0x0180
|
||||
#define GICD_ISPEND 0x0200
|
||||
#define GICD_ICPEND 0x0280
|
||||
#define GICD_ISACTIVE 0x0300
|
||||
#define GICD_ICACTIVE 0x0380
|
||||
#define GICD_IPRIORITY 0x0400
|
||||
#define GICD_ITARGETS 0x0800
|
||||
#define GICD_ICFG 0x0c00
|
||||
#define GICD_PPISR 0x0d00
|
||||
#define GICD_SPISR 0x0d04
|
||||
#define GICD_SGIR 0x0f00
|
||||
#define GICD_CPENDSGI 0x0f10
|
||||
#define GICD_SPENDSGI 0x0f20
|
||||
#define GICD_PIDR4 0x0fd0
|
||||
#define GICD_PIDR5 0x0fd4
|
||||
#define GICD_PIDR6 0x0fd8
|
||||
#define GICD_PIDR7 0x0fdc
|
||||
#define GICD_PIDR0 0x0fe0
|
||||
#define GICD_PIDR1 0x0fe4
|
||||
#define GICD_PIDR2 0x0fe8
|
||||
#define GICD_PIDR3 0x0fec
|
||||
#define GICD_CIDR0 0x0ff0
|
||||
#define GICD_CIDR1 0x0ff4
|
||||
#define GICD_CIDR2 0x0ff8
|
||||
#define GICD_CIDR3 0x0ffc
|
||||
|
||||
//
|
||||
// CPU Interface layout
|
||||
//
|
||||
#define GICC_CTLR 0x0000
|
||||
#define GICC_PMR 0x0004
|
||||
#define GICC_BPR 0x0008
|
||||
#define GICC_IAR 0x000c
|
||||
#define GICC_EOIR 0x0010
|
||||
#define GICC_RPR 0x0014
|
||||
#define GICC_HPPIR 0x0018
|
||||
#define GICC_ABPR 0x001c
|
||||
#define GICC_AIAR 0x0020
|
||||
#define GICC_AEOIR 0x0024
|
||||
#define GICC_AHPPIR 0x0028
|
||||
#define GICC_APR0 0x00d0
|
||||
#define GICC_NSAPR0 0x00e0
|
||||
#define GICC_IIDR 0x00fc
|
||||
#define GICC_DIR 0x1000
|
||||
|
||||
#endif // PPM_AEM_H
|
||||
@@ -0,0 +1,328 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="com.arm.debugger.launcher2">
|
||||
<stringAttribute key="ANDROID_ACTIVITY_NAME" value=""/>
|
||||
<stringAttribute key="ANDROID_APPLICATION" value=""/>
|
||||
<stringAttribute key="ANDROID_APP_DIR" value=""/>
|
||||
<stringAttribute key="ANDROID_PROCESS_NAME" value=""/>
|
||||
<mapAttribute key="AverageDurationTracker">
|
||||
<mapEntry key="*Fetching Data Model" value="210253"/>
|
||||
<mapEntry key="*list global low level symbols" value="1091370"/>
|
||||
<mapEntry key="*loading memory from target" value="820184"/>
|
||||
<mapEntry key="*loading values from target" value="7611554"/>
|
||||
<mapEntry key="*trace" value="322915988"/>
|
||||
<mapEntry key="*updating expressions" value="82423423"/>
|
||||
<mapEntry key="*updating registers" value="71328946"/>
|
||||
<mapEntry key="*updating variables" value="8591428"/>
|
||||
<mapEntry key="Add Watchpoint" value="24597988"/>
|
||||
<mapEntry key="AddEventObserver" value="2339600"/>
|
||||
<mapEntry key="Evaluate" value="1178890"/>
|
||||
<mapEntry key="GlobalsLoaderCommand" value="154351059"/>
|
||||
<mapEntry key="areCachesAvailable" value="512640"/>
|
||||
<mapEntry key="backtrace" value="5112231"/>
|
||||
<mapEntry key="break" value="4014913"/>
|
||||
<mapEntry key="checking tracepoints" value="200317"/>
|
||||
<mapEntry key="compute execution mode" value="466572"/>
|
||||
<mapEntry key="continue" value="15148060"/>
|
||||
<mapEntry key="core" value="3940900"/>
|
||||
<mapEntry key="directory" value="1503592"/>
|
||||
<mapEntry key="disable" value="1478680"/>
|
||||
<mapEntry key="disassemble" value="57572371"/>
|
||||
<mapEntry key="enable" value="1860234"/>
|
||||
<mapEntry key="evaluate" value="2783965"/>
|
||||
<mapEntry key="evaluate address" value="17239727"/>
|
||||
<mapEntry key="get byte order" value="472733"/>
|
||||
<mapEntry key="get capabilities" value="202552"/>
|
||||
<mapEntry key="get execution addresss" value="394564"/>
|
||||
<mapEntry key="get source lines" value="295618"/>
|
||||
<mapEntry key="get substitute paths" value="353179"/>
|
||||
<mapEntry key="get value" value="402104"/>
|
||||
<mapEntry key="getValidEncodings" value="513752"/>
|
||||
<mapEntry key="initialize command help" value="74015139"/>
|
||||
<mapEntry key="interrupt" value="7175224"/>
|
||||
<mapEntry key="list breakpoint options" value="199731"/>
|
||||
<mapEntry key="list breakpoints" value="630899"/>
|
||||
<mapEntry key="list instruction sets" value="261430"/>
|
||||
<mapEntry key="list signals" value="407465"/>
|
||||
<mapEntry key="list source files" value="864344"/>
|
||||
<mapEntry key="list watchpoint options" value="268722"/>
|
||||
<mapEntry key="list watchpoints" value="488478"/>
|
||||
<mapEntry key="loadfile" value="37843801"/>
|
||||
<mapEntry key="next" value="28879002"/>
|
||||
<mapEntry key="nexti" value="29780513"/>
|
||||
<mapEntry key="remove" value="1542853"/>
|
||||
<mapEntry key="run script" value="33363950"/>
|
||||
<mapEntry key="set CWD" value="2457367"/>
|
||||
<mapEntry key="set breakpoint properties" value="5020796"/>
|
||||
<mapEntry key="set debug-from" value="865786"/>
|
||||
<mapEntry key="set substitute-path" value="8017078"/>
|
||||
<mapEntry key="set watchpoint properties" value="1458988"/>
|
||||
<mapEntry key="source use_model_semihosting.ds" value="3779014"/>
|
||||
<mapEntry key="start" value="14956585"/>
|
||||
<mapEntry key="step" value="30965896"/>
|
||||
<mapEntry key="stepi" value="30815174"/>
|
||||
<mapEntry key="synchronizing trace ranges" value="26037"/>
|
||||
<mapEntry key="toggleBreakpoint" value="7270567"/>
|
||||
<mapEntry key="waitForTargetToStop" value="10448502"/>
|
||||
<mapEntry key="write expression" value="5812240"/>
|
||||
</mapAttribute>
|
||||
<listAttribute key="DEBUG_TAB."/>
|
||||
<stringAttribute key="DEBUG_TAB..RESOURCES.0.TYPE" value="SOURCE_DIR"/>
|
||||
<stringAttribute key="DEBUG_TAB..RESOURCES.0.VALUE" value="${workspace_loc:/tx}"/>
|
||||
<intAttribute key="DEBUG_TAB..RESOURCES.COUNT" value="1"/>
|
||||
<intAttribute key="FILES.CONNECT_TO_GDB_SERVER.RESOURCES.COUNT" value="0"/>
|
||||
<intAttribute key="FILES.DEBUG_EXISTING_ANDROID.RESOURCES.COUNT" value="0"/>
|
||||
<listAttribute key="FILES.DEBUG_RESIDENT_ANDROID"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.0.VALUE" value=""/>
|
||||
<intAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.COUNT" value="1"/>
|
||||
<listAttribute key="FILES.DEBUG_RESIDENT_APP"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.0.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.1.TYPE" value="APPLICATION_ON_TARGET"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.1.VALUE" value=""/>
|
||||
<intAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.COUNT" value="2"/>
|
||||
<listAttribute key="FILES.DOWNLOAD_AND_DEBUG">
|
||||
<listEntry value="ON_DEMAND_LOAD"/>
|
||||
<listEntry value="ALSO_LOAD_SYMBOLS"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.TYPE" value="TARGET_DOWNLOAD_DIR"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.VALUE" value=""/>
|
||||
<intAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.COUNT" value="3"/>
|
||||
<listAttribute key="FILES.DOWNLOAD_DEBUG">
|
||||
<listEntry value="ON_DEMAND_LOAD"/>
|
||||
<listEntry value="ALSO_LOAD_SYMBOLS"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.TYPE" value="TARGET_DOWNLOAD_DIR"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.VALUE" value=""/>
|
||||
<intAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.COUNT" value="3"/>
|
||||
<intAttribute key="FILES.DOWNLOAD_DEBUG_ANDROID.RESOURCES.COUNT" value="0"/>
|
||||
<listAttribute key="FILES.ICE_DEBUG">
|
||||
<listEntry value="ON_DEMAND_LOAD"/>
|
||||
<listEntry value="ALSO_LOAD_SYMBOLS"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.VALUE" value="${workspace_loc:/sample_threadx/Debug/sample_threadx.axf}"/>
|
||||
<intAttribute key="FILES.ICE_DEBUG.RESOURCES.COUNT" value="1"/>
|
||||
<listAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE">
|
||||
<listEntry value="ON_DEMAND_LOAD"/>
|
||||
<listEntry value="ALSO_LOAD_SYMBOLS"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.VALUE" value=""/>
|
||||
<intAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.COUNT" value="1"/>
|
||||
<listAttribute key="FILES.ICE_DEBUG_WITH_TRACE">
|
||||
<listEntry value="ON_DEMAND_LOAD"/>
|
||||
<listEntry value="ALSO_LOAD_SYMBOLS"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.VALUE" value=""/>
|
||||
<intAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.COUNT" value="1"/>
|
||||
<stringAttribute key="FILES.SELECTED_DEBUG_OPEATION" value="ICE_DEBUG"/>
|
||||
<stringAttribute key="HOST_WORKING_DIR" value="${workspace_loc}"/>
|
||||
<booleanAttribute key="HOST_WORKING_DIR_USE_DEFAULT" value="true"/>
|
||||
<booleanAttribute key="InstructionStepping" value="false"/>
|
||||
<booleanAttribute key="KEY_COMMANDS_AFTER_CONNECT" value="true"/>
|
||||
<stringAttribute key="KEY_COMMANDS_AFTER_CONNECT_TEXT" value="add-symbol-file "${workspace_loc:/sample_threadx/Debug/sample_threadx.axf}" EL1N:0"/>
|
||||
<booleanAttribute key="KEY_COMMANDS_AS_CONNECT" value="false"/>
|
||||
<intAttribute key="Messages.POST_TRIGGER_CAPTURE_SIZE.getLocalisedValue().FMTrace" value="50"/>
|
||||
<booleanAttribute key="Messages.STOP_ON_TRIGGER.getLocalisedValue().FMTrace" value="false"/>
|
||||
<booleanAttribute key="RSE_USE_HOSTNAME" value="true"/>
|
||||
<stringAttribute key="TCP_DISABLE_EXTENDED_MODE" value="true"/>
|
||||
<booleanAttribute key="TCP_KILL_ON_EXIT" value="false"/>
|
||||
<listAttribute key="TREE_NODE_PROPERTIES:debugger.view.ExpressionsView">
|
||||
<listEntry value="NODE CACHE VERSION 1"/>
|
||||
<listEntry value="EXPRESSION_GROUP:Expressions:VALUE:gic_dist:VALUE:(gic_dist)->padding0"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="element formatter"/>
|
||||
<listEntry value="Unsigned Decimal"/>
|
||||
<listEntry value="EXPRESSION_GROUP:Expressions:VALUE:_tx_thread_current_ptr->tx_thread_name"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="element formatter"/>
|
||||
<listEntry value="Character"/>
|
||||
<listEntry value="EXPRESSION_GROUP:Expressions:VALUE:$AARCH64::$Core::$SP"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="TREE_NODE_PROPERTIES:debugger.view.NewRegisterView">
|
||||
<listEntry value="NODE CACHE VERSION 1"/>
|
||||
<listEntry value="REGISTER_SET:$AARCH64"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="expanded"/>
|
||||
<listEntry value="true"/>
|
||||
<listEntry value="REGISTER_GROUP:$AARCH64::$Core"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="expanded"/>
|
||||
<listEntry value="true"/>
|
||||
</listAttribute>
|
||||
<booleanAttribute key="VFS_ENABLED" value="true"/>
|
||||
<stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/>
|
||||
<stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/>
|
||||
<stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x0000000080000800" debugFile="C:/Users/nisohack/Documents/work/x-ware_libs/threadx/ports/cortex_a35/gnu/example_build/sample_threadx/vectors.S" hostFile="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports\cortex_a35\gnu\example_build\sample_threadx\vectors.S" line="27"/> 		<location index="0" enabled="true" version="2" address="EL3:0x0000000080000800" debugFile="C:/Users/nisohack/Documents/work/x-ware_libs/threadx/ports/cortex_a35/gnu/example_build/sample_threadx/vectors.S" hostFile="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports\cortex_a35\gnu\example_build\sample_threadx\vectors.S" line="27"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x0000000080000800" debugFile="C:/Users/nisohack/Documents/work/x-ware_libs/threadx/ports/cortex_a35/gnu/example_build/sample_threadx/vectors.S" hostFile="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports\cortex_a35\gnu\example_build\sample_threadx\vectors.S" line="27"/> 	</breakpoint> </breakpoints> "/>
|
||||
<listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses">
|
||||
<listEntry value="<Next Instruction>"/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value="EL1N:0x0000000080006444"/>
|
||||
<listEntry value="EL1N:0x000000008000A7E4"/>
|
||||
<listEntry value="0x0000000080009140"/>
|
||||
<listEntry value="0x000000008000E660"/>
|
||||
<listEntry value="EL1N:0x000000008000E660"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.ranges">
|
||||
<listEntry value="100"/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.MemoryView.addresses">
|
||||
<listEntry value=""/>
|
||||
<listEntry value="0x000000008000E600"/>
|
||||
<listEntry value="0x000000008000EE00"/>
|
||||
<listEntry value="thread_2.tx_thread_stack_start"/>
|
||||
<listEntry value="0x000000008000E500"/>
|
||||
<listEntry value="0x000000008000E670"/>
|
||||
<listEntry value="0x8000de30"/>
|
||||
<listEntry value="0x8000de00"/>
|
||||
<listEntry value="0x8000de48"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.MemoryView.ranges">
|
||||
<listEntry value=""/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.addresses">
|
||||
<listEntry value="_tx_thread_schedule"/>
|
||||
<listEntry value="<Next Instruction>"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges">
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="config_db_activity_name" value="Debug Cortex-A35"/>
|
||||
<stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option dtsl_config_script model_params config_file setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/>
|
||||
<stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/>
|
||||
<stringAttribute key="config_db_platform_name" value="Arm FVP (Installed with Arm DS) - Base_A35x1"/>
|
||||
<stringAttribute key="config_db_project_type" value="Bare Metal Debug"/>
|
||||
<stringAttribute key="config_db_project_type_id" value="BARE_METAL"/>
|
||||
<stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp_installedwitharmds_/base_a35x1"/>
|
||||
<stringAttribute key="config_file" value="CDB://cadi_config.xml"/>
|
||||
<booleanAttribute key="connectOnly" value="false"/>
|
||||
<listAttribute key="debugger.view.DisassemblyView:current">
|
||||
<listEntry value="<Next Instruction>"/>
|
||||
<listEntry value="100"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="debugger.view.DisassemblyView:current:133102083840333696.viewid=2">
|
||||
<listEntry value="<Next Instruction>"/>
|
||||
<listEntry value="100"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="debugger.view.DisassemblyView:current:3239034212381883008.viewid=2">
|
||||
<listEntry value="_tx_thread_schedule"/>
|
||||
<listEntry value="100"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="debugger.view.DisassemblyView:current:4564877728016551851.viewid=3">
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
</listAttribute>
|
||||
<listAttribute key="debugger.view.ExpressionsView">
|
||||
<listEntry value="thread_0_counter"/>
|
||||
<listEntry value="thread_1_counter"/>
|
||||
<listEntry value="thread_2_counter"/>
|
||||
<listEntry value="thread_3_counter"/>
|
||||
<listEntry value="thread_4_counter"/>
|
||||
<listEntry value="thread_5_counter"/>
|
||||
<listEntry value="thread_6_counter"/>
|
||||
<listEntry value="thread_7_counter"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="debugger.view.ExpressionsView.ExpressionTypes">
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
</listAttribute>
|
||||
<mapAttribute key="debugger.view.ExpressionsView.ExpressionsData">
|
||||
<mapEntry key="0" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="1" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="2" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="3" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="4" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="5" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="6" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="7" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
</mapAttribute>
|
||||
<stringAttribute key="debugger.view.ExpressionsView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	187	-1	true	1	false	true	90	-1	true	2	true	true	108	-1	true	3	true	true	57	-1	true	4	true	true	50	-1	true	5	true	true	37	-1	true	6	true	true	157	-1	true	7	true	true	53	-1	true"/>
|
||||
<stringAttribute key="debugger.view.MemoryView" value="<?xml version="1.0" encoding="UTF-8"?> <page> 	<memoryView/> </page> "/>
|
||||
<listAttribute key="debugger.view.MemoryView:current">
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="debugger.view.NewRegisterView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	false	206	-1	true	1	false	true	90	-1	true	2	true	false	420	-1	true	3	false	true	41	-1	true	4	false	true	50	-1	true	5	true	false	37	-1	true	6	false	true	62	-1	true	7	true	false	53	-1	true"/>
|
||||
<stringAttribute key="debugger.view.NewRegisterView:_selectedRegisterSet" value="All registers"/>
|
||||
<mapAttribute key="debugger.view.NewRegisterView_registerSets"/>
|
||||
<stringAttribute key="debugger.view.StackView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	49	-1	true	1	false	true	90	-1	true	2	true	true	45	-1	true	3	true	true	41	-1	true	4	true	true	50	-1	true	5	true	true	37	-1	true	6	true	true	62	-1	true	7	true	true	53	-1	true"/>
|
||||
<listAttribute key="debugger.view.TraceView:TRACE_EXPORT_FILTERS"/>
|
||||
<stringAttribute key="debugger.view.VariableTreeView:DebugOutlineColumnState" value="OutlineConfig1	0"/>
|
||||
<listAttribute key="debugger.view.VariableTreeView:USER_ADDED_FILE_STATICS"/>
|
||||
<listAttribute key="debugger.view.VariableTreeView:USER_ADDED_GLOBALS"/>
|
||||
<listAttribute key="debugger.view.VariableTreeView:USER_ADDED_UNRESOLVED"/>
|
||||
<booleanAttribute key="debugger.view.expression.DrawAsHex" value="false"/>
|
||||
<booleanAttribute key="debugger.view.register.DrawAsHex" value="false"/>
|
||||
<stringAttribute key="dtsl_config" value="DtslScript"/>
|
||||
<stringAttribute key="dtsl_config_script" value="CDB://dtsl_config_script.py"/>
|
||||
<stringAttribute key="dtsl_options_file" value="default"/>
|
||||
<stringAttribute key="dtsl_tracecapture_option" value="options.traceBuffer.traceCaptureDevice"/>
|
||||
<stringAttribute key="launch_configuration_version" value="5.21.1"/>
|
||||
<booleanAttribute key="linuxOS" value="false"/>
|
||||
<stringAttribute key="model_params" value="-C bp.secure_memory=false -C cache_state_modelled=0"/>
|
||||
<booleanAttribute key="runAfterConnect" value="false"/>
|
||||
<stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/>
|
||||
<mapAttribute key="scripts_view_script_links">
|
||||
<mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports\cortex_a35\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/>
|
||||
<mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports\cortex_a35\gnu\example_build\sample_threadx\use_model_semihosting.ds" value=""/>
|
||||
</mapAttribute>
|
||||
<listAttribute key="setup">
|
||||
<listEntry value="CDB://Scripts/rtsm_launcher.py"/>
|
||||
<listEntry value=""FVP_Base_Cortex-A35x1""/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/>
|
||||
<stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:\temp1702\tx\</ta> 		<tb>C:\temp1702\tx\</tb> 	</tuple> </tuplelist> "/>
|
||||
<stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/>
|
||||
</launchConfiguration>
|
||||
@@ -0,0 +1,245 @@
|
||||
/* Linker script to place sections and symbol values.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* start64 : Entry point
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __cs3_peripherals
|
||||
* __code_start
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __data_start
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* __stack
|
||||
* __el3_stack
|
||||
* __ttb0_l1
|
||||
* __ttb0_l2_ram
|
||||
* __ttb0_l2_private
|
||||
* __ttb0_l2_periph
|
||||
* __top_of_ram
|
||||
*/
|
||||
|
||||
ENTRY(start64)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/*
|
||||
* CS3 Peripherals is a 64MB region from 0x1c000000
|
||||
* that includes the following:
|
||||
* System Registers at 0x1C010000
|
||||
* UART0 (PL011) at 0x1C090000
|
||||
* Color LCD Controller (PL111) at 0x1C1F0000
|
||||
* plus a number of others.
|
||||
* CS3_PERIPHERALS is used by the startup code for page-table generation
|
||||
* This region is not truly empty, but we have no
|
||||
* predefined objects that live within it
|
||||
*/
|
||||
__cs3_peripherals = 0x1c000000;
|
||||
|
||||
/*
|
||||
* GICv3 distributor
|
||||
*/
|
||||
.gicd 0x2f000000 (NOLOAD):
|
||||
{
|
||||
*(.gicd)
|
||||
}
|
||||
|
||||
/*
|
||||
* GICv3 redistributors
|
||||
* 128KB for each redistributor in the system
|
||||
*/
|
||||
.gicr 0x2f100000 (NOLOAD):
|
||||
{
|
||||
*(.gicr)
|
||||
}
|
||||
|
||||
.vectors 0x80000000:
|
||||
{
|
||||
__code_start = .;
|
||||
KEEP(*(StartUp))
|
||||
KEEP(*(EL1VECTORS EL2VECTORS EL3VECTORS))
|
||||
}
|
||||
|
||||
.init :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
}
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text*)
|
||||
}
|
||||
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
}
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
}
|
||||
|
||||
.eh_frame :
|
||||
{
|
||||
KEEP (*(.eh_frame))
|
||||
}
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
}
|
||||
|
||||
.ARM.exidx :
|
||||
{
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
__exidx_end = .;
|
||||
}
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
}
|
||||
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array ))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
}
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
KEEP (*(.fini_array ))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
}
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
|
||||
.jcr :
|
||||
{
|
||||
KEEP (*(.jcr))
|
||||
}
|
||||
|
||||
.data :
|
||||
{
|
||||
__data_start = . ;
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
}
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
}
|
||||
|
||||
.heap (NOLOAD):
|
||||
{
|
||||
. = ALIGN(64);
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
. = . + 0x1000;
|
||||
}
|
||||
|
||||
.stack (NOLOAD):
|
||||
{
|
||||
. = ALIGN(64);
|
||||
. = . + 8 * 0x4000;
|
||||
__handler_stack = .;
|
||||
}
|
||||
|
||||
.stack (NOLOAD):
|
||||
{
|
||||
. = ALIGN(64);
|
||||
. = . + 8 * 0x4000;
|
||||
__stack = .;
|
||||
}
|
||||
|
||||
.el3_stack (NOLOAD):
|
||||
{
|
||||
. = ALIGN(64);
|
||||
. = . + 8 * 0x1000;
|
||||
__el3_stack = .;
|
||||
}
|
||||
|
||||
.ttb0_l1 (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4096);
|
||||
__ttb0_l1 = .;
|
||||
. = . + 0x1000;
|
||||
}
|
||||
|
||||
.ttb0_l2_ram (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4096);
|
||||
__ttb0_l2_ram = .;
|
||||
. = . + 0x1000;
|
||||
}
|
||||
|
||||
.ttb0_l2_private (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4096);
|
||||
__ttb0_l2_private = .;
|
||||
. = . + 0x1000;
|
||||
}
|
||||
|
||||
.ttb0_l2_periph (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4096);
|
||||
__ttb0_l2_periph = .;
|
||||
. = . + 0x1000;
|
||||
}
|
||||
|
||||
/*
|
||||
* The startup code uses the end of this region to calculate
|
||||
* the top of memory - don't place any RAM regions after it
|
||||
*/
|
||||
__top_of_ram = .;
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
// ------------------------------------------------------------
|
||||
// SP804 Dual Timer
|
||||
//
|
||||
// Copyright (c) 2009-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#include "sp804_timer.h"
|
||||
|
||||
#define TIMER_SP804_CTRL_TIMEREN (1 << 7)
|
||||
#define TIMER_SP804_CTRL_TIMERMODE (1 << 6) // Bit 6:
|
||||
#define TIMER_SP804_CTRL_INTENABLE (1 << 5)
|
||||
#define TIMER_SP804_CTRL_TIMERSIZE (1 << 1) // Bit 1: 0=16-bit, 1=32-bit
|
||||
#define TIMER_SP804_CTRL_ONESHOT (1 << 0) // Bit 0: 0=wrapping, 1=one-shot
|
||||
|
||||
#define TIMER_SP804_CTRL_PRESCALE_1 (0 << 2) // clk/1
|
||||
#define TIMER_SP804_CTRL_PRESCALE_4 (1 << 2) // clk/4
|
||||
#define TIMER_SP804_CTRL_PRESCALE_8 (2 << 2) // clk/8
|
||||
|
||||
struct sp804_timer
|
||||
{
|
||||
volatile uint32_t Time1Load; // +0x00
|
||||
const volatile uint32_t Time1Value; // +0x04 - RO
|
||||
volatile uint32_t Timer1Control; // +0x08
|
||||
volatile uint32_t Timer1IntClr; // +0x0C - WO
|
||||
const volatile uint32_t Timer1RIS; // +0x10 - RO
|
||||
const volatile uint32_t Timer1MIS; // +0x14 - RO
|
||||
volatile uint32_t Timer1BGLoad; // +0x18
|
||||
|
||||
volatile uint32_t Time2Load; // +0x20
|
||||
volatile uint32_t Time2Value; // +0x24
|
||||
volatile uint8_t Timer2Control; // +0x28
|
||||
volatile uint32_t Timer2IntClr; // +0x2C - WO
|
||||
const volatile uint32_t Timer2RIS; // +0x30 - RO
|
||||
const volatile uint32_t Timer2MIS; // +0x34 - RO
|
||||
volatile uint32_t Timer2BGLoad; // +0x38
|
||||
|
||||
// Not including ID registers
|
||||
|
||||
};
|
||||
|
||||
// Instance of the dual timer, will be placed using the scatter file
|
||||
struct sp804_timer* dual_timer;
|
||||
|
||||
|
||||
// Set base address of timer
|
||||
// address - virtual address of SP804 timer
|
||||
void setTimerBaseAddress(uint64_t address)
|
||||
{
|
||||
dual_timer = (struct sp804_timer*)address;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Sets up the private timer
|
||||
// load_value - Initial value of timer
|
||||
// auto_reload - Periodic (SP804_AUTORELOAD) or one shot (SP804_SINGLESHOT)
|
||||
// interrupt - Whether to generate an interrupt
|
||||
void initTimer(uint32_t load_value, uint32_t auto_reload, uint32_t interrupt)
|
||||
{
|
||||
uint32_t tmp = 0;
|
||||
|
||||
dual_timer->Time1Load = load_value;
|
||||
|
||||
// Fixed setting: 32-bit, no prescaling
|
||||
tmp = TIMER_SP804_CTRL_TIMERSIZE | TIMER_SP804_CTRL_PRESCALE_1 | TIMER_SP804_CTRL_TIMERMODE;
|
||||
|
||||
// Settings from parameters: interrupt generation & reload
|
||||
tmp = tmp | interrupt | auto_reload;
|
||||
|
||||
// Write control register
|
||||
dual_timer->Timer1Control = tmp;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Starts the timer
|
||||
void startTimer(void)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = dual_timer->Timer1Control;
|
||||
tmp = tmp | TIMER_SP804_CTRL_TIMEREN; // Set TimerEn (bit 7)
|
||||
dual_timer->Timer1Control = tmp;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Stops the timer
|
||||
void stopTimer(void)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = dual_timer->Timer1Control;
|
||||
tmp = tmp & ~TIMER_SP804_CTRL_TIMEREN; // Clear TimerEn (bit 7)
|
||||
dual_timer->Timer1Control = tmp;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Returns the current timer count
|
||||
uint32_t getTimerCount(void)
|
||||
{
|
||||
return dual_timer->Time1Value;
|
||||
}
|
||||
|
||||
|
||||
void clearTimerIrq(void)
|
||||
{
|
||||
// A write to this register, of any value, clears the interrupt
|
||||
dual_timer->Timer1IntClr = 1;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// End of sp804_timer.c
|
||||
// ------------------------------------------------------------
|
||||
@@ -0,0 +1,53 @@
|
||||
// ------------------------------------------------------------
|
||||
// SP804 Dual Timer
|
||||
// Header Filer
|
||||
//
|
||||
// Copyright (c) 2009-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#ifndef _SP804_TIMER_
|
||||
#define _SP804_TIMER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Set base address of timer
|
||||
// address - virtual address of SP804 timer
|
||||
void setTimerBaseAddress(uint64_t address);
|
||||
|
||||
|
||||
// Sets up the private timer
|
||||
// load_value - Initial value of timer
|
||||
// auto_reload - Periodic (SP804_AUTORELOAD) or one shot (SP804_SINGLESHOT)
|
||||
// interrupt - Whether to generate an interrupt
|
||||
|
||||
#define SP804_AUTORELOAD (0)
|
||||
#define SP804_SINGLESHOT (1)
|
||||
#define SP804_GENERATE_IRQ (1 << 5)
|
||||
#define SP804_NO_IRQ (0)
|
||||
|
||||
void initTimer(uint32_t load_value, uint32_t auto_reload, uint32_t interrupt);
|
||||
|
||||
|
||||
// Starts the timer
|
||||
void startTimer(void);
|
||||
|
||||
|
||||
// Stops the timer
|
||||
void stopTimer(void);
|
||||
|
||||
|
||||
// Returns the current timer count
|
||||
uint32_t getTimerCount(void);
|
||||
|
||||
|
||||
// Clears the timer interrupt
|
||||
void clearTimerIrq(void);
|
||||
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// End of sp804_timer.h
|
||||
// ------------------------------------------------------------
|
||||
@@ -0,0 +1,787 @@
|
||||
// ------------------------------------------------------------
|
||||
// Armv8-A MPCore EL3 AArch64 Startup Code
|
||||
//
|
||||
// Basic Vectors, MMU, caches and GICv3 initialization
|
||||
//
|
||||
// Exits in EL1 AArch64
|
||||
//
|
||||
// Copyright (c) 2014-2019 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#include "v8_mmu.h"
|
||||
#include "v8_system.h"
|
||||
#include "GICv3_aliases.h"
|
||||
|
||||
.section StartUp, "ax"
|
||||
.balign 4
|
||||
|
||||
|
||||
.global el1_vectors
|
||||
.global el2_vectors
|
||||
.global el3_vectors
|
||||
|
||||
.global InvalidateUDCaches
|
||||
.global ZeroBlock
|
||||
|
||||
.global SetPrivateIntSecurityBlock
|
||||
.global SetSPISecurityAll
|
||||
.global SetPrivateIntPriority
|
||||
|
||||
.global GetGICR
|
||||
.global WakeupGICR
|
||||
.global SyncAREinGICD
|
||||
.global EnableGICD
|
||||
.global EnablePrivateInt
|
||||
.global GetPrivateIntPending
|
||||
.global ClearPrivateIntPending
|
||||
|
||||
.global _start
|
||||
.global MainApp
|
||||
|
||||
.global __code_start
|
||||
.global __ttb0_l1
|
||||
.global __ttb0_l2_ram
|
||||
.global __ttb0_l2_periph
|
||||
.global __top_of_ram
|
||||
.global gicd
|
||||
.global __stack
|
||||
.global __el3_stack
|
||||
.global __cs3_peripherals
|
||||
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
.global start64
|
||||
.type start64, "function"
|
||||
start64:
|
||||
|
||||
//
|
||||
// program the VBARs
|
||||
//
|
||||
ldr x1, =el1_vectors
|
||||
msr VBAR_EL1, x1
|
||||
|
||||
ldr x1, =el2_vectors
|
||||
msr VBAR_EL2, x1
|
||||
|
||||
ldr x1, =el3_vectors
|
||||
msr VBAR_EL3, x1
|
||||
|
||||
|
||||
// GIC-500 comes out of reset in GICv2 compatibility mode - first set
|
||||
// system register enables for all relevant exception levels, and
|
||||
// select GICv3 operating mode
|
||||
//
|
||||
msr SCR_EL3, xzr // Ensure NS bit is initially clear, so secure copy of ICC_SRE_EL1 can be configured
|
||||
isb
|
||||
|
||||
mov x0, #15
|
||||
msr ICC_SRE_EL3, x0
|
||||
isb
|
||||
msr ICC_SRE_EL1, x0 // Secure copy of ICC_SRE_EL1
|
||||
|
||||
//
|
||||
// set lower exception levels as non-secure, with no access
|
||||
// back to EL2 or EL3, and are AArch64 capable
|
||||
//
|
||||
mov x3, #(SCR_EL3_RW | \
|
||||
SCR_EL3_SMD | \
|
||||
SCR_EL3_NS) // Set NS bit, to access Non-secure registers
|
||||
msr SCR_EL3, x3
|
||||
isb
|
||||
|
||||
mov x0, #15
|
||||
msr ICC_SRE_EL2, x0
|
||||
isb
|
||||
msr ICC_SRE_EL1, x0 // Non-secure copy of ICC_SRE_EL1
|
||||
|
||||
|
||||
//
|
||||
// no traps or VM modifications from the Hypervisor, EL1 is AArch64
|
||||
//
|
||||
mov x2, #HCR_EL2_RW
|
||||
msr HCR_EL2, x2
|
||||
|
||||
//
|
||||
// VMID is still significant, even when virtualisation is not
|
||||
// being used, so ensure VTTBR_EL2 is properly initialised
|
||||
//
|
||||
msr VTTBR_EL2, xzr
|
||||
|
||||
//
|
||||
// VMPIDR_EL2 holds the value of the Virtualization Multiprocessor ID. This is the value returned by Non-secure EL1 reads of MPIDR_EL1.
|
||||
// VPIDR_EL2 holds the value of the Virtualization Processor ID. This is the value returned by Non-secure EL1 reads of MIDR_EL1.
|
||||
// Both of these registers are architecturally UNKNOWN at reset, and so they must be set to the correct value
|
||||
// (even if EL2/virtualization is not being used), otherwise non-secure EL1 reads of MPIDR_EL1/MIDR_EL1 will return garbage values.
|
||||
// This guarantees that any future reads of MPIDR_EL1 and MIDR_EL1 from Non-secure EL1 will return the correct value.
|
||||
//
|
||||
mrs x0, MPIDR_EL1
|
||||
msr VMPIDR_EL2, x0
|
||||
mrs x0, MIDR_EL1
|
||||
msr VPIDR_EL2, x0
|
||||
|
||||
// extract the core number from MPIDR_EL1 and store it in
|
||||
// x19 (defined by the AAPCS as callee-saved), so we can re-use
|
||||
// the number later
|
||||
//
|
||||
bl GetCPUID
|
||||
mov x19, x0
|
||||
|
||||
//
|
||||
// neither EL3 nor EL2 trap floating point or accesses to CPACR
|
||||
//
|
||||
msr CPTR_EL3, xzr
|
||||
msr CPTR_EL2, xzr
|
||||
|
||||
//
|
||||
// SCTLR_ELx may come out of reset with UNKNOWN values so we will
|
||||
// set the fields to 0 except, possibly, the endianess field(s).
|
||||
// Note that setting SCTLR_EL2 or the EL0 related fields of SCTLR_EL1
|
||||
// is not strictly needed, since we're never in EL2 or EL0
|
||||
//
|
||||
#ifdef __ARM_BIG_ENDIAN
|
||||
mov x0, #(SCTLR_ELx_EE | SCTLR_EL1_E0E)
|
||||
#else
|
||||
mov x0, #0
|
||||
#endif
|
||||
msr SCTLR_EL3, x0
|
||||
msr SCTLR_EL2, x0
|
||||
msr SCTLR_EL1, x0
|
||||
|
||||
#ifdef CORTEXA
|
||||
//
|
||||
// Configure ACTLR_EL[23]
|
||||
// ----------------------
|
||||
//
|
||||
// These bits are IMPLEMENTATION DEFINED, so are different for
|
||||
// different processors
|
||||
//
|
||||
// For Cortex-A57, the controls we set are:
|
||||
//
|
||||
// Enable lower level access to CPUACTLR_EL1
|
||||
// Enable lower level access to CPUECTLR_EL1
|
||||
// Enable lower level access to L2CTLR_EL1
|
||||
// Enable lower level access to L2ECTLR_EL1
|
||||
// Enable lower level access to L2ACTLR_EL1
|
||||
//
|
||||
mov x0, #((1 << 0) | \
|
||||
(1 << 1) | \
|
||||
(1 << 4) | \
|
||||
(1 << 5) | \
|
||||
(1 << 6))
|
||||
|
||||
msr ACTLR_EL3, x0
|
||||
msr ACTLR_EL2, x0
|
||||
|
||||
//
|
||||
// configure CPUECTLR_EL1
|
||||
//
|
||||
// These bits are IMP DEF, so need to different for different
|
||||
// processors
|
||||
//
|
||||
// SMPEN - bit 6 - Enables the processor to receive cache
|
||||
// and TLB maintenance operations
|
||||
//
|
||||
// Note: For Cortex-A57/53 SMPEN should be set before enabling
|
||||
// the caches and MMU, or performing any cache and TLB
|
||||
// maintenance operations.
|
||||
//
|
||||
// This register has a defined reset value, so we use a
|
||||
// read-modify-write sequence to set SMPEN
|
||||
//
|
||||
mrs x0, S3_1_c15_c2_1 // Read EL1 CPU Extended Control Register
|
||||
orr x0, x0, #(1 << 6) // Set the SMPEN bit
|
||||
msr S3_1_c15_c2_1, x0 // Write EL1 CPU Extended Control Register
|
||||
|
||||
isb
|
||||
#endif
|
||||
|
||||
//
|
||||
// That's the last of the control settings for now
|
||||
//
|
||||
// Note: no ISB after all these changes, as registers won't be
|
||||
// accessed until after an exception return, which is itself a
|
||||
// context synchronisation event
|
||||
//
|
||||
|
||||
//
|
||||
// Setup some EL3 stack space, ready for calling some subroutines, below.
|
||||
//
|
||||
// Stack space allocation is CPU-specific, so use CPU
|
||||
// number already held in x19
|
||||
//
|
||||
// 2^12 bytes per CPU for the EL3 stacks
|
||||
//
|
||||
ldr x0, =__el3_stack
|
||||
sub x0, x0, x19, lsl #12
|
||||
mov sp, x0
|
||||
|
||||
//
|
||||
// we need to configure the GIC while still in secure mode, specifically
|
||||
// all PPIs and SPIs have to be programmed as Group1 interrupts
|
||||
//
|
||||
|
||||
//
|
||||
// Before the GIC can be reliably programmed, we need to
|
||||
// enable Affinity Routing, as this affects where the configuration
|
||||
// registers are (with Affinity Routing enabled, some registers are
|
||||
// in the Redistributor, whereas those same registers are in the
|
||||
// Distributor with Affinity Routing disabled (i.e. when in GICv2
|
||||
// compatibility mode).
|
||||
//
|
||||
mov x0, #(1 << 4) | (1 << 5) // gicdctlr_ARE_S | gicdctlr_ARE_NS
|
||||
mov x1, x19
|
||||
bl SyncAREinGICD
|
||||
|
||||
//
|
||||
// The Redistributor comes out of reset assuming the processor is
|
||||
// asleep - correct that assumption
|
||||
//
|
||||
bl GetAffinity
|
||||
bl GetGICR
|
||||
mov w20, w0 // Keep a copy for later
|
||||
bl WakeupGICR
|
||||
|
||||
//
|
||||
// Now we're ready to set security and other initialisations
|
||||
//
|
||||
// This is a per-CPU configuration for these interrupts
|
||||
//
|
||||
// for the first cluster, CPU number is the redistributor index
|
||||
//
|
||||
mov w0, w20
|
||||
mov w1, #1 // gicigroupr_G1NS
|
||||
bl SetPrivateIntSecurityBlock
|
||||
|
||||
//
|
||||
// While we're in the Secure World, set the priority mask low enough
|
||||
// for it to be writable in the Non-Secure World
|
||||
//
|
||||
//mov x0, #16 << 3 // 5 bits of priority in the Secure world
|
||||
mov x0, #0xFF // for Non-Secure interrupts
|
||||
msr ICC_PMR_EL1, x0
|
||||
|
||||
//
|
||||
// there's more GIC setup to do, but only for the primary CPU
|
||||
//
|
||||
cbnz x19, drop_to_el1
|
||||
|
||||
//
|
||||
// There's more to do to the GIC - call the utility routine to set
|
||||
// all SPIs to Group1
|
||||
//
|
||||
mov w0, #1 // gicigroupr_G1NS
|
||||
bl SetSPISecurityAll
|
||||
|
||||
//
|
||||
// Set up EL1 entry point and "dummy" exception return information,
|
||||
// then perform exception return to enter EL1
|
||||
//
|
||||
.global drop_to_el1
|
||||
drop_to_el1:
|
||||
adr x1, el1_entry_aarch64
|
||||
msr ELR_EL3, x1
|
||||
mov x1, #(AARCH64_SPSR_EL1h | \
|
||||
AARCH64_SPSR_F | \
|
||||
AARCH64_SPSR_I | \
|
||||
AARCH64_SPSR_A)
|
||||
msr SPSR_EL3, x1
|
||||
eret
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// EL1 - Common start-up code
|
||||
// ------------------------------------------------------------
|
||||
|
||||
.global el1_entry_aarch64
|
||||
.type el1_entry_aarch64, "function"
|
||||
el1_entry_aarch64:
|
||||
|
||||
//
|
||||
// Now we're in EL1, setup the application stack
|
||||
// the scatter file allocates 2^14 bytes per app stack
|
||||
//
|
||||
ldr x0, =__handler_stack
|
||||
sub x0, x0, x19, lsl #14
|
||||
mov sp, x0
|
||||
MSR SPSel, #0
|
||||
ISB
|
||||
ldr x0, =__stack
|
||||
sub x0, x0, x19, lsl #14
|
||||
mov sp, x0
|
||||
|
||||
//
|
||||
// Enable floating point
|
||||
//
|
||||
mov x0, #CPACR_EL1_FPEN
|
||||
msr CPACR_EL1, x0
|
||||
|
||||
//
|
||||
// Invalidate caches and TLBs for all stage 1
|
||||
// translations used at EL1
|
||||
//
|
||||
// Cortex-A processors automatically invalidate their caches on reset
|
||||
// (unless suppressed with the DBGL1RSTDISABLE or L2RSTDISABLE pins).
|
||||
// It is therefore not necessary for software to invalidate the caches
|
||||
// on startup, however, this is done here in case of a warm reset.
|
||||
bl InvalidateUDCaches
|
||||
tlbi VMALLE1
|
||||
|
||||
|
||||
//
|
||||
// Set TTBR0 Base address
|
||||
//
|
||||
// The CPUs share one set of translation tables that are
|
||||
// generated by CPU0 at run-time
|
||||
//
|
||||
// TTBR1_EL1 is not used in this example
|
||||
//
|
||||
ldr x1, =__ttb0_l1
|
||||
msr TTBR0_EL1, x1
|
||||
|
||||
|
||||
//
|
||||
// Set up memory attributes
|
||||
//
|
||||
// These equate to:
|
||||
//
|
||||
// 0 -> 0b01000100 = 0x00000044 = Normal, Inner/Outer Non-Cacheable
|
||||
// 1 -> 0b11111111 = 0x0000ff00 = Normal, Inner/Outer WriteBack Read/Write Allocate
|
||||
// 2 -> 0b00000100 = 0x00040000 = Device-nGnRE
|
||||
//
|
||||
mov x1, #0xff44
|
||||
movk x1, #4, LSL #16 // equiv to: movk x1, #0x0000000000040000
|
||||
msr MAIR_EL1, x1
|
||||
|
||||
|
||||
//
|
||||
// Set up TCR_EL1
|
||||
//
|
||||
// We're using only TTBR0 (EPD1 = 1), and the page table entries:
|
||||
// - are using an 8-bit ASID from TTBR0
|
||||
// - have a 4K granularity (TG0 = 0b00)
|
||||
// - are outer-shareable (SH0 = 0b10)
|
||||
// - are using Inner & Outer WBWA Normal memory ([IO]RGN0 = 0b01)
|
||||
// - map
|
||||
// + 32 bits of VA space (T0SZ = 0x20)
|
||||
// + into a 32-bit PA space (IPS = 0b000)
|
||||
//
|
||||
// 36 32 28 24 20 16 12 8 4 0
|
||||
// -----+----+----+----+----+----+----+----+----+----+
|
||||
// | | |OOII| | | |OOII| | |
|
||||
// TT | | |RRRR|E T | T| |RRRR|E T | T|
|
||||
// BB | I I|TTSS|GGGG|P 1 | 1|TTSS|GGGG|P 0 | 0|
|
||||
// IIA| P P|GGHH|NNNN|DAS | S|GGHH|NNNN|D S | S|
|
||||
// 10S| S-S|1111|1111|11Z-|---Z|0000|0000|0 Z-|---Z|
|
||||
//
|
||||
// 000 0000 0000 0000 1000 0000 0010 0101 0010 0000
|
||||
//
|
||||
// 0x 8 0 2 5 2 0
|
||||
//
|
||||
// Note: the ISB is needed to ensure the changes to system
|
||||
// context are before the write of SCTLR_EL1.M to enable
|
||||
// the MMU. It is likely on a "real" implementation that
|
||||
// this setup would work without an ISB, due to the
|
||||
// amount of code that gets executed before enabling the
|
||||
// MMU, but that would not be architecturally correct.
|
||||
//
|
||||
ldr x1, =0x0000000000802520
|
||||
msr TCR_EL1, x1
|
||||
isb
|
||||
|
||||
//
|
||||
// x19 already contains the CPU number, so branch to secondary
|
||||
// code if we're not on CPU0
|
||||
//
|
||||
cbnz x19, el1_secondary
|
||||
|
||||
//
|
||||
// Fall through to primary code
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// ------------------------------------------------------------
|
||||
//
|
||||
// EL1 - primary CPU init code
|
||||
//
|
||||
// This code is run on CPU0, while the other CPUs are in the
|
||||
// holding pen
|
||||
//
|
||||
|
||||
.global el1_primary
|
||||
.type el1_primary, "function"
|
||||
el1_primary:
|
||||
|
||||
//
|
||||
// Turn on the banked GIC distributor enable,
|
||||
// ready for individual CPU enables later
|
||||
//
|
||||
mov w0, #(1 << 1) // gicdctlr_EnableGrp1A
|
||||
bl EnableGICD
|
||||
|
||||
//
|
||||
// Generate TTBR0 L1
|
||||
//
|
||||
// at 4KB granularity, 32-bit VA space, table lookup starts at
|
||||
// L1, with 1GB regions
|
||||
//
|
||||
// we are going to create entries pointing to L2 tables for a
|
||||
// couple of these 1GB regions, the first of which is the
|
||||
// RAM on the VE board model - get the table addresses and
|
||||
// start by emptying out the L1 page tables (4 entries at L1
|
||||
// for a 4K granularity)
|
||||
//
|
||||
// x21 = address of L1 tables
|
||||
//
|
||||
ldr x21, =__ttb0_l1
|
||||
mov x0, x21
|
||||
mov x1, #(4 << 3)
|
||||
bl ZeroBlock
|
||||
|
||||
//
|
||||
// time to start mapping the RAM regions - clear out the
|
||||
// L2 tables and point to them from the L1 tables
|
||||
//
|
||||
// x22 = address of L2 tables, needs to be remembered in case
|
||||
// we want to re-use the tables for mapping peripherals
|
||||
//
|
||||
ldr x22, =__ttb0_l2_ram
|
||||
mov x1, #(512 << 3)
|
||||
mov x0, x22
|
||||
bl ZeroBlock
|
||||
|
||||
//
|
||||
// Get the start address of RAM (the EXEC region) into x4
|
||||
// and calculate the offset into the L1 table (1GB per region,
|
||||
// max 4GB)
|
||||
//
|
||||
// x23 = L1 table offset, saved for later comparison against
|
||||
// peripheral offset
|
||||
//
|
||||
ldr x4, =__code_start
|
||||
ubfx x23, x4, #30, #2
|
||||
|
||||
orr x1, x22, #TT_S1_ATTR_PAGE
|
||||
str x1, [x21, x23, lsl #3]
|
||||
|
||||
//
|
||||
// we've already used the RAM start address in x4 - we now need
|
||||
// to get this in terms of an offset into the L2 page tables,
|
||||
// where each entry covers 2MB
|
||||
//
|
||||
ubfx x2, x4, #21, #9
|
||||
|
||||
//
|
||||
// TOP_OF_RAM in the scatter file marks the end of the
|
||||
// Execute region in RAM: convert the end of this region to an
|
||||
// offset too, being careful to round up, then calculate the
|
||||
// number of entries to write
|
||||
//
|
||||
ldr x5, =__top_of_ram
|
||||
sub x3, x5, #1
|
||||
ubfx x3, x3, #21, #9
|
||||
add x3, x3, #1
|
||||
sub x3, x3, x2
|
||||
|
||||
//
|
||||
// set x1 to the required page table attributes, then orr
|
||||
// in the start address (modulo 2MB)
|
||||
//
|
||||
// L2 tables in our configuration cover 2MB per entry - map
|
||||
// memory as Shared, Normal WBWA (MAIR[1]) with a flat
|
||||
// VA->PA translation
|
||||
//
|
||||
bic x4, x4, #((1 << 21) - 1)
|
||||
ldr x1, =(TT_S1_ATTR_BLOCK | \
|
||||
(1 << TT_S1_ATTR_MATTR_LSB) | \
|
||||
TT_S1_ATTR_NS | \
|
||||
TT_S1_ATTR_AP_RW_PL1 | \
|
||||
TT_S1_ATTR_SH_INNER | \
|
||||
TT_S1_ATTR_AF | \
|
||||
TT_S1_ATTR_nG)
|
||||
orr x1, x1, x4
|
||||
|
||||
//
|
||||
// factor the offset into the page table address and then write
|
||||
// the entries
|
||||
//
|
||||
add x0, x22, x2, lsl #3
|
||||
|
||||
loop1:
|
||||
subs x3, x3, #1
|
||||
str x1, [x0], #8
|
||||
add x1, x1, #0x200, LSL #12 // equiv to add x1, x1, #(1 << 21) // 2MB per entry
|
||||
bne loop1
|
||||
|
||||
|
||||
//
|
||||
// now mapping the Peripheral regions - clear out the
|
||||
// L2 tables and point to them from the L1 tables
|
||||
//
|
||||
// The assumption here is that all peripherals live within
|
||||
// a common 1GB region (i.e. that there's a single set of
|
||||
// L2 pages for all the peripherals). We only use a UART
|
||||
// and the GIC in this example, so the assumption is sound
|
||||
//
|
||||
// x24 = address of L2 peripheral tables
|
||||
//
|
||||
ldr x24, =__ttb0_l2_periph
|
||||
|
||||
//
|
||||
// get the GICD address into x4 and calculate
|
||||
// the offset into the L1 table
|
||||
//
|
||||
// x25 = L1 table offset
|
||||
//
|
||||
ldr x4, =gicd
|
||||
ubfx x25, x4, #30, #2
|
||||
|
||||
//
|
||||
// here's the tricky bit: it's possible that the peripherals are
|
||||
// in the same 1GB region as the RAM, in which case we don't need
|
||||
// to prime a separate set of L2 page tables, nor add them to the
|
||||
// L1 tables
|
||||
//
|
||||
// if we're going to re-use the TTB0_L2_RAM tables, get their
|
||||
// address into x24, which is used later on to write the PTEs
|
||||
//
|
||||
cmp x25, x23
|
||||
csel x24, x22, x24, EQ
|
||||
b.eq nol2setup
|
||||
|
||||
//
|
||||
// Peripherals are in a separate 1GB region, and so have their own
|
||||
// set of L2 tables - clean out the tables and add them to the L1
|
||||
// table
|
||||
//
|
||||
mov x0, x24
|
||||
mov x1, #512 << 3
|
||||
bl ZeroBlock
|
||||
|
||||
orr x1, x24, #TT_S1_ATTR_PAGE
|
||||
str x1, [x21, x25, lsl #3]
|
||||
|
||||
//
|
||||
// there's only going to be a single 2MB region for GICD (in
|
||||
// x4) - get this in terms of an offset into the L2 page tables
|
||||
//
|
||||
// with larger systems, it is possible that the GIC redistributor
|
||||
// registers require extra 2MB pages, in which case extra code
|
||||
// would be required here
|
||||
//
|
||||
nol2setup:
|
||||
ubfx x2, x4, #21, #9
|
||||
|
||||
//
|
||||
// set x1 to the required page table attributes, then orr
|
||||
// in the start address (modulo 2MB)
|
||||
//
|
||||
// L2 tables in our configuration cover 2MB per entry - map
|
||||
// memory as NS Device-nGnRE (MAIR[2]) with a flat VA->PA
|
||||
// translation
|
||||
//
|
||||
bic x4, x4, #((1 << 21) - 1) // start address mod 2MB
|
||||
ldr x1, =(TT_S1_ATTR_BLOCK | \
|
||||
(2 << TT_S1_ATTR_MATTR_LSB) | \
|
||||
TT_S1_ATTR_NS | \
|
||||
TT_S1_ATTR_AP_RW_PL1 | \
|
||||
TT_S1_ATTR_AF | \
|
||||
TT_S1_ATTR_nG)
|
||||
orr x1, x1, x4
|
||||
|
||||
//
|
||||
// only a single L2 entry for this, so no loop as we have for RAM, above
|
||||
//
|
||||
str x1, [x24, x2, lsl #3]
|
||||
|
||||
//
|
||||
// we have CS3_PERIPHERALS that include the UART controller
|
||||
//
|
||||
// Again, the code is making assumptions - this time that the CS3_PERIPHERALS
|
||||
// region uses the same 1GB portion of the address space as the GICD,
|
||||
// and thus shares the same set of L2 page tables
|
||||
//
|
||||
// Get CS3_PERIPHERALS address into x4 and calculate the offset into the
|
||||
// L2 tables
|
||||
//
|
||||
ldr x4, =__cs3_peripherals
|
||||
ubfx x2, x4, #21, #9
|
||||
|
||||
//
|
||||
// set x1 to the required page table attributes, then orr
|
||||
// in the start address (modulo 2MB)
|
||||
//
|
||||
// L2 tables in our configuration cover 2MB per entry - map
|
||||
// memory as NS Device-nGnRE (MAIR[2]) with a flat VA->PA
|
||||
// translation
|
||||
//
|
||||
bic x4, x4, #((1 << 21) - 1) // start address mod 2MB
|
||||
ldr x1, =(TT_S1_ATTR_BLOCK | \
|
||||
(2 << TT_S1_ATTR_MATTR_LSB) | \
|
||||
TT_S1_ATTR_NS | \
|
||||
TT_S1_ATTR_AP_RW_PL1 | \
|
||||
TT_S1_ATTR_AF | \
|
||||
TT_S1_ATTR_nG)
|
||||
orr x1, x1, x4
|
||||
|
||||
//
|
||||
// only a single L2 entry again - write it
|
||||
//
|
||||
str x1, [x24, x2, lsl #3]
|
||||
|
||||
//
|
||||
// issue a barrier to ensure all table entry writes are complete
|
||||
//
|
||||
dsb ish
|
||||
|
||||
//
|
||||
// Enable the MMU. Caches will be enabled later, after scatterloading.
|
||||
//
|
||||
mrs x1, SCTLR_EL1
|
||||
orr x1, x1, #SCTLR_ELx_M
|
||||
bic x1, x1, #SCTLR_ELx_A // Disable alignment fault checking. To enable, change bic to orr
|
||||
msr SCTLR_EL1, x1
|
||||
isb
|
||||
|
||||
//
|
||||
// The Arm Architecture Reference Manual for Armv8-A states:
|
||||
//
|
||||
// Instruction accesses to Non-cacheable Normal memory can be held in instruction caches.
|
||||
// Correspondingly, the sequence for ensuring that modifications to instructions are available
|
||||
// for execution must include invalidation of the modified locations from the instruction cache,
|
||||
// even if the instructions are held in Normal Non-cacheable memory.
|
||||
// This includes cases where the instruction cache is disabled.
|
||||
//
|
||||
|
||||
dsb ish // ensure all previous stores have completed before invalidating
|
||||
ic ialluis // I cache invalidate all inner shareable to PoU (which includes secondary cores)
|
||||
dsb ish // ensure completion on inner shareable domain (which includes secondary cores)
|
||||
isb
|
||||
|
||||
// Scatter-loading is complete, so enable the caches here, so that the C-library's mutex initialization later will work
|
||||
mrs x1, SCTLR_EL1
|
||||
orr x1, x1, #SCTLR_ELx_C
|
||||
orr x1, x1, #SCTLR_ELx_I
|
||||
msr SCTLR_EL1, x1
|
||||
isb
|
||||
|
||||
// Zero the bss
|
||||
ldr x0, =__bss_start__ // Start of block
|
||||
mov x1, #0 // Fill value
|
||||
ldr x2, =__bss_end__ // End of block
|
||||
sub x2, x2, x0 // Length of block
|
||||
bl memset
|
||||
|
||||
// Set up the standard file handles
|
||||
bl initialise_monitor_handles
|
||||
|
||||
// Set up _fini and fini_array to be called at exit
|
||||
ldr x0, =__libc_fini_array
|
||||
bl atexit
|
||||
|
||||
// Call preinit_array, _init and init_array
|
||||
bl __libc_init_array
|
||||
|
||||
// Set argc = 1, argv[0] = "" and then call main
|
||||
.pushsection .data
|
||||
.align 3
|
||||
argv:
|
||||
.dword arg0
|
||||
.dword 0
|
||||
arg0:
|
||||
.byte 0
|
||||
.popsection
|
||||
|
||||
mov x0, #1
|
||||
ldr x1, =argv
|
||||
bl main
|
||||
|
||||
b exit // Will not return
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// EL1 - secondary CPU init code
|
||||
//
|
||||
// This code is run on CPUs 1, 2, 3 etc....
|
||||
// ------------------------------------------------------------
|
||||
|
||||
.global el1_secondary
|
||||
.type el1_secondary, "function"
|
||||
el1_secondary:
|
||||
|
||||
//
|
||||
// the primary CPU is going to use SGI 15 as a wakeup event
|
||||
// to let us know when it is OK to proceed, so prepare for
|
||||
// receiving that interrupt
|
||||
//
|
||||
// NS interrupt priorities run from 0 to 15, with 15 being
|
||||
// too low a priority to ever raise an interrupt, so let's
|
||||
// use 14
|
||||
//
|
||||
mov w0, w20
|
||||
mov w1, #15
|
||||
mov w2, #14 << 4 // we're in NS world, so 4 bits of priority,
|
||||
// 8-bit field, - 4 = 4-bit shift
|
||||
bl SetPrivateIntPriority
|
||||
|
||||
mov w0, w20
|
||||
mov w1, #15
|
||||
bl EnablePrivateInt
|
||||
|
||||
//
|
||||
// set priority mask as low as possible; although,being in the
|
||||
// NS World, we can't set bit[7] of the priority, we still
|
||||
// write all 8-bits of priority to an ICC register
|
||||
//
|
||||
mov x0, #31 << 3
|
||||
msr ICC_PMR_EL1, x0
|
||||
|
||||
//
|
||||
// set global enable and wait for our interrupt to arrive
|
||||
//
|
||||
mov x0, #1
|
||||
msr ICC_IGRPEN1_EL1, x0
|
||||
isb
|
||||
|
||||
loop_wfi:
|
||||
dsb SY // Clear all pending data accesses
|
||||
wfi // Go to sleep
|
||||
|
||||
//
|
||||
// something woke us from our wait, was it the required interrupt?
|
||||
//
|
||||
mov w0, w20
|
||||
mov w1, #15
|
||||
bl GetPrivateIntPending
|
||||
cbz w0, loop_wfi
|
||||
|
||||
//
|
||||
// it was - there's no need to actually take the interrupt,
|
||||
// so just clear it
|
||||
//
|
||||
mov w0, w20
|
||||
mov w1, #15
|
||||
bl ClearPrivateIntPending
|
||||
|
||||
//
|
||||
// Enable the MMU and caches
|
||||
//
|
||||
mrs x1, SCTLR_EL1
|
||||
orr x1, x1, #SCTLR_ELx_M
|
||||
orr x1, x1, #SCTLR_ELx_C
|
||||
orr x1, x1, #SCTLR_ELx_I
|
||||
bic x1, x1, #SCTLR_ELx_A // Disable alignment fault checking. To enable, change bic to orr
|
||||
msr SCTLR_EL1, x1
|
||||
isb
|
||||
|
||||
//
|
||||
// Branch to thread start
|
||||
//
|
||||
//B MainApp
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/* Bare-metal example for Armv8-A FVP Base model */
|
||||
|
||||
/* Timer and interrupts */
|
||||
|
||||
/* Copyright (c) 2016-2018 Arm Limited (or its affiliates). All rights reserved. */
|
||||
/* Use, modification and redistribution of this file is subject to your possession of a */
|
||||
/* valid End User License Agreement for the Arm Product of which these examples are part of */
|
||||
/* and your compliance with all applicable terms and conditions of such licence agreement. */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "GICv3.h"
|
||||
#include "GICv3_gicc.h"
|
||||
#include "sp804_timer.h"
|
||||
|
||||
void _tx_timer_interrupt(void);
|
||||
|
||||
// LED Base address
|
||||
#define LED_BASE (volatile unsigned int *)0x1C010008
|
||||
|
||||
|
||||
void nudge_leds(void) // Move LEDs along
|
||||
{
|
||||
static int state = 1;
|
||||
static int value = 1;
|
||||
|
||||
if (state)
|
||||
{
|
||||
int max = (1 << 7);
|
||||
value <<= 1;
|
||||
if (value == max)
|
||||
state = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
value >>= 1;
|
||||
if (value == 1)
|
||||
state = 1;
|
||||
}
|
||||
|
||||
*LED_BASE = value; // Update LEDs hardware
|
||||
}
|
||||
|
||||
|
||||
// Initialize Timer 0 and Interrupt Controller
|
||||
void init_timer(void)
|
||||
{
|
||||
// Enable interrupts
|
||||
__asm("MSR DAIFClr, #0xF");
|
||||
setICC_IGRPEN1_EL1(igrpEnable);
|
||||
|
||||
// Configure the SP804 timer to generate an interrupt
|
||||
setTimerBaseAddress(0x1C110000);
|
||||
initTimer(0x200, SP804_AUTORELOAD, SP804_GENERATE_IRQ);
|
||||
startTimer();
|
||||
|
||||
// The SP804 timer generates SPI INTID 34. Enable
|
||||
// this ID, and route it to core 0.0.0.0 (this one!)
|
||||
SetSPIRoute(34, 0, gicdirouter_ModeSpecific); // Route INTID 34 to 0.0.0.0 (this core)
|
||||
SetSPIPriority(34, 0); // Set INTID 34 to priority to 0
|
||||
ConfigureSPI(34, gicdicfgr_Level); // Set INTID 34 as level-sensitive
|
||||
EnableSPI(34); // Enable INTID 34
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
void irqHandler(void)
|
||||
{
|
||||
unsigned int ID;
|
||||
|
||||
ID = getICC_IAR1(); // readIntAck();
|
||||
|
||||
// Check for reserved IDs
|
||||
if ((1020 <= ID) && (ID <= 1023))
|
||||
{
|
||||
//printf("irqHandler() - Reserved INTID %d\n\n", ID);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(ID)
|
||||
{
|
||||
case 34:
|
||||
// Dual-Timer 0 (SP804)
|
||||
//printf("irqHandler() - External timer interrupt\n\n");
|
||||
nudge_leds();
|
||||
clearTimerIrq();
|
||||
|
||||
/* Call ThreadX timer interrupt processing. */
|
||||
_tx_timer_interrupt();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unexpected ID value
|
||||
//printf("irqHandler() - Unexpected INTID %d\n\n", ID);
|
||||
break;
|
||||
}
|
||||
|
||||
// Write the End of Interrupt register to tell the GIC
|
||||
// we've finished handling the interrupt
|
||||
setICC_EOIR1(ID); // writeAliasedEOI(ID);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
// Not actually used in this example, but provided for completeness
|
||||
|
||||
void fiqHandler(void)
|
||||
{
|
||||
unsigned int ID;
|
||||
unsigned int aliased = 0;
|
||||
|
||||
ID = getICC_IAR0(); // readIntAck();
|
||||
//printf("fiqHandler() - Read %d from IAR0\n", ID);
|
||||
|
||||
// Check for reserved IDs
|
||||
if ((1020 <= ID) && (ID <= 1023))
|
||||
{
|
||||
//printf("fiqHandler() - Reserved INTID %d\n\n", ID);
|
||||
ID = getICC_IAR1(); // readAliasedIntAck();
|
||||
//printf("fiqHandler() - Read %d from AIAR\n", ID);
|
||||
aliased = 1;
|
||||
|
||||
// If still spurious then simply return
|
||||
if ((1020 <= ID) && (ID <= 1023))
|
||||
return;
|
||||
}
|
||||
|
||||
switch(ID)
|
||||
{
|
||||
case 34:
|
||||
// Dual-Timer 0 (SP804)
|
||||
//printf("fiqHandler() - External timer interrupt\n\n");
|
||||
clearTimerIrq();
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unexpected ID value
|
||||
//printf("fiqHandler() - Unexpected INTID %d\n\n", ID);
|
||||
break;
|
||||
}
|
||||
|
||||
// Write the End of Interrupt register to tell the GIC
|
||||
// we've finished handling the interrupt
|
||||
// NOTE: If the ID was read from the Aliased IAR, then
|
||||
// the aliased EOI register must be used
|
||||
if (aliased == 0)
|
||||
setICC_EOIR0(ID); // writeEOI(ID);
|
||||
else
|
||||
setICC_EOIR1(ID); // writeAliasedEOI(ID);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
set semihosting enabled off
|
||||
@@ -0,0 +1,179 @@
|
||||
// ------------------------------------------------------------
|
||||
// Armv8-A AArch64 - Common helper functions
|
||||
//
|
||||
// Copyright (c) 2012-2019 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#include "v8_system.h"
|
||||
|
||||
.text
|
||||
.cfi_sections .debug_frame // put stack frame info into .debug_frame instead of .eh_frame
|
||||
|
||||
.global EnableCachesEL1
|
||||
.global DisableCachesEL1
|
||||
.global InvalidateUDCaches
|
||||
.global GetMIDR
|
||||
.global GetMPIDR
|
||||
.global GetAffinity
|
||||
.global GetCPUID
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
//
|
||||
// void EnableCachesEL1(void)
|
||||
//
|
||||
// enable Instruction and Data caches
|
||||
//
|
||||
.type EnableCachesEL1, "function"
|
||||
.cfi_startproc
|
||||
EnableCachesEL1:
|
||||
|
||||
mrs x0, SCTLR_EL1
|
||||
orr x0, x0, #SCTLR_ELx_I
|
||||
orr x0, x0, #SCTLR_ELx_C
|
||||
msr SCTLR_EL1, x0
|
||||
|
||||
isb
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
.type DisableCachesEL1, "function"
|
||||
.cfi_startproc
|
||||
DisableCachesEL1:
|
||||
|
||||
mrs x0, SCTLR_EL1
|
||||
bic x0, x0, #SCTLR_ELx_I
|
||||
bic x0, x0, #SCTLR_ELx_C
|
||||
msr SCTLR_EL1, x0
|
||||
|
||||
isb
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
//
|
||||
// void InvalidateUDCaches(void)
|
||||
//
|
||||
// Invalidate data and unified caches
|
||||
//
|
||||
.type InvalidateUDCaches, "function"
|
||||
.cfi_startproc
|
||||
InvalidateUDCaches:
|
||||
// From the Armv8-A Architecture Reference Manual
|
||||
|
||||
dmb ish // ensure all prior inner-shareable accesses have been observed
|
||||
|
||||
mrs x0, CLIDR_EL1
|
||||
and w3, w0, #0x07000000 // get 2 x level of coherence
|
||||
lsr w3, w3, #23
|
||||
cbz w3, finished
|
||||
mov w10, #0 // w10 = 2 x cache level
|
||||
mov w8, #1 // w8 = constant 0b1
|
||||
loop_level:
|
||||
add w2, w10, w10, lsr #1 // calculate 3 x cache level
|
||||
lsr w1, w0, w2 // extract 3-bit cache type for this level
|
||||
and w1, w1, #0x7
|
||||
cmp w1, #2
|
||||
b.lt next_level // no data or unified cache at this level
|
||||
msr CSSELR_EL1, x10 // select this cache level
|
||||
isb // synchronize change of csselr
|
||||
mrs x1, CCSIDR_EL1 // read ccsidr
|
||||
and w2, w1, #7 // w2 = log2(linelen)-4
|
||||
add w2, w2, #4 // w2 = log2(linelen)
|
||||
ubfx w4, w1, #3, #10 // w4 = max way number, right aligned
|
||||
clz w5, w4 // w5 = 32-log2(ways), bit position of way in dc operand
|
||||
lsl w9, w4, w5 // w9 = max way number, aligned to position in dc operand
|
||||
lsl w16, w8, w5 // w16 = amount to decrement way number per iteration
|
||||
loop_way:
|
||||
ubfx w7, w1, #13, #15 // w7 = max set number, right aligned
|
||||
lsl w7, w7, w2 // w7 = max set number, aligned to position in dc operand
|
||||
lsl w17, w8, w2 // w17 = amount to decrement set number per iteration
|
||||
loop_set:
|
||||
orr w11, w10, w9 // w11 = combine way number and cache number ...
|
||||
orr w11, w11, w7 // ... and set number for dc operand
|
||||
dc isw, x11 // do data cache invalidate by set and way
|
||||
subs w7, w7, w17 // decrement set number
|
||||
b.ge loop_set
|
||||
subs x9, x9, x16 // decrement way number
|
||||
b.ge loop_way
|
||||
next_level:
|
||||
add w10, w10, #2 // increment 2 x cache level
|
||||
cmp w3, w10
|
||||
b.gt loop_level
|
||||
dsb sy // ensure completion of previous cache maintenance operation
|
||||
isb
|
||||
finished:
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
//
|
||||
// ID Register functions
|
||||
//
|
||||
|
||||
.type GetMIDR, "function"
|
||||
.cfi_startproc
|
||||
GetMIDR:
|
||||
|
||||
mrs x0, MIDR_EL1
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
.type GetMPIDR, "function"
|
||||
.cfi_startproc
|
||||
GetMPIDR:
|
||||
|
||||
mrs x0, MPIDR_EL1
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
.type GetAffinity, "function"
|
||||
.cfi_startproc
|
||||
GetAffinity:
|
||||
|
||||
mrs x0, MPIDR_EL1
|
||||
ubfx x1, x0, #32, #8
|
||||
bfi w0, w1, #24, #8
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
.type GetCPUID, "function"
|
||||
.cfi_startproc
|
||||
GetCPUID:
|
||||
|
||||
mrs x0, MIDR_EL1
|
||||
ubfx x0, x0, #4, #12 // extract PartNum
|
||||
cmp x0, #0xD0D // Cortex-A77
|
||||
b.eq DynamIQ
|
||||
cmp x0, #0xD0B // Cortex-A76
|
||||
b.eq DynamIQ
|
||||
cmp x0, #0xD0A // Cortex-A75
|
||||
b.eq DynamIQ
|
||||
cmp x0, #0xD05 // Cortex-A55
|
||||
b.eq DynamIQ
|
||||
b Others
|
||||
DynamIQ:
|
||||
mrs x0, MPIDR_EL1
|
||||
ubfx x0, x0, #MPIDR_EL1_AFF1_LSB, #MPIDR_EL1_AFF_WIDTH
|
||||
ret
|
||||
|
||||
Others:
|
||||
mrs x0, MPIDR_EL1
|
||||
ubfx x1, x0, #MPIDR_EL1_AFF0_LSB, #MPIDR_EL1_AFF_WIDTH
|
||||
ubfx x2, x0, #MPIDR_EL1_AFF1_LSB, #MPIDR_EL1_AFF_WIDTH
|
||||
add x0, x1, x2, LSL #2
|
||||
ret
|
||||
.cfi_endproc
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
*
|
||||
* Armv8-A AArch64 common helper functions
|
||||
*
|
||||
* Copyright (c) 2012-2014 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
|
||||
#ifndef V8_AARCH64_H
|
||||
#define V8_AARCH64_H
|
||||
|
||||
/*
|
||||
* Parameters for data barriers
|
||||
*/
|
||||
#define OSHLD 1
|
||||
#define OSHST 2
|
||||
#define OSH 3
|
||||
#define NSHLD 5
|
||||
#define NSHST 6
|
||||
#define NSH 7
|
||||
#define ISHLD 9
|
||||
#define ISHST 10
|
||||
#define ISH 11
|
||||
#define LD 13
|
||||
#define ST 14
|
||||
#define SY 15
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* function prototypes
|
||||
*/
|
||||
|
||||
/*
|
||||
* void InvalidateUDCaches(void)
|
||||
* invalidates all Unified and Data Caches
|
||||
*
|
||||
* Inputs
|
||||
* <none>
|
||||
*
|
||||
* Returns
|
||||
* <nothing>
|
||||
*
|
||||
* Side Effects
|
||||
* guarantees that all levels of cache will be invalidated before
|
||||
* returning to caller
|
||||
*/
|
||||
void InvalidateUDCaches(void);
|
||||
|
||||
/*
|
||||
* unsigned long long EnableCachesEL1(void)
|
||||
* enables I- and D- caches at EL1
|
||||
*
|
||||
* Inputs
|
||||
* <none>
|
||||
*
|
||||
* Returns
|
||||
* New value of SCTLR_EL1
|
||||
*
|
||||
* Side Effects
|
||||
* context will be synchronised before returning to caller
|
||||
*/
|
||||
unsigned long long EnableCachesEL1(void);
|
||||
|
||||
/*
|
||||
* unsigned long long GetMIDR(void)
|
||||
* returns the contents of MIDR_EL0
|
||||
*
|
||||
* Inputs
|
||||
* <none>
|
||||
*
|
||||
* Returns
|
||||
* MIDR_EL0
|
||||
*/
|
||||
unsigned long long GetMIDR(void);
|
||||
|
||||
/*
|
||||
* unsigned long long GetMPIDR(void)
|
||||
* returns the contents of MPIDR_EL0
|
||||
*
|
||||
* Inputs
|
||||
* <none>
|
||||
*
|
||||
* Returns
|
||||
* MPIDR_EL0
|
||||
*/
|
||||
unsigned long long GetMPIDR(void);
|
||||
|
||||
/*
|
||||
* unsigned int GetCPUID(void)
|
||||
* returns the Aff0 field of MPIDR_EL0
|
||||
*
|
||||
* Inputs
|
||||
* <none>
|
||||
*
|
||||
* Returns
|
||||
* MPIDR_EL0[7:0]
|
||||
*/
|
||||
unsigned int GetCPUID(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// Defines for v8 Memory Model
|
||||
//
|
||||
// Copyright (c) 2012-2019 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
#ifndef V8_MMU_H
|
||||
#define V8_MMU_H
|
||||
|
||||
//
|
||||
// Translation Control Register fields
|
||||
//
|
||||
// RGN field encodings
|
||||
//
|
||||
#define TCR_RGN_NC 0b00
|
||||
#define TCR_RGN_WBWA 0b01
|
||||
#define TCR_RGN_WT 0b10
|
||||
#define TCR_RGN_WBRA 0b11
|
||||
|
||||
//
|
||||
// Shareability encodings
|
||||
//
|
||||
#define TCR_SHARE_NONE 0b00
|
||||
#define TCR_SHARE_OUTER 0b10
|
||||
#define TCR_SHARE_INNER 0b11
|
||||
|
||||
//
|
||||
// Granule size encodings
|
||||
//
|
||||
#define TCR_GRANULE_4K 0b00
|
||||
#define TCR_GRANULE_64K 0b01
|
||||
#define TCR_GRANULE_16K 0b10
|
||||
|
||||
//
|
||||
// Physical Address sizes
|
||||
//
|
||||
#define TCR_SIZE_4G 0b000
|
||||
#define TCR_SIZE_64G 0b001
|
||||
#define TCR_SIZE_1T 0b010
|
||||
#define TCR_SIZE_4T 0b011
|
||||
#define TCR_SIZE_16T 0b100
|
||||
#define TCR_SIZE_256T 0b101
|
||||
|
||||
//
|
||||
// Translation Control Register fields
|
||||
//
|
||||
#define TCR_EL1_T0SZ_SHIFT 0
|
||||
#define TCR_EL1_EPD0 (1 << 7)
|
||||
#define TCR_EL1_IRGN0_SHIFT 8
|
||||
#define TCR_EL1_ORGN0_SHIFT 10
|
||||
#define TCR_EL1_SH0_SHIFT 12
|
||||
#define TCR_EL1_TG0_SHIFT 14
|
||||
|
||||
#define TCR_EL1_T1SZ_SHIFT 16
|
||||
#define TCR_EL1_A1 (1 << 22)
|
||||
#define TCR_EL1_EPD1 (1 << 23)
|
||||
#define TCR_EL1_IRGN1_SHIFT 24
|
||||
#define TCR_EL1_ORGN1_SHIFT 26
|
||||
#define TCR_EL1_SH1_SHIFT 28
|
||||
#define TCR_EL1_TG1_SHIFT 30
|
||||
#define TCR_EL1_IPS_SHIFT 32
|
||||
#define TCR_EL1_AS (1 << 36)
|
||||
#define TCR_EL1_TBI0 (1 << 37)
|
||||
#define TCR_EL1_TBI1 (1 << 38)
|
||||
|
||||
//
|
||||
// Stage 1 Translation Table descriptor fields
|
||||
//
|
||||
#define TT_S1_ATTR_FAULT (0b00 << 0)
|
||||
#define TT_S1_ATTR_BLOCK (0b01 << 0) // Level 1/2
|
||||
#define TT_S1_ATTR_TABLE (0b11 << 0) // Level 0/1/2
|
||||
#define TT_S1_ATTR_PAGE (0b11 << 0) // Level 3
|
||||
|
||||
#define TT_S1_ATTR_MATTR_LSB 2
|
||||
|
||||
#define TT_S1_ATTR_NS (1 << 5)
|
||||
|
||||
#define TT_S1_ATTR_AP_RW_PL1 (0b00 << 6)
|
||||
#define TT_S1_ATTR_AP_RW_ANY (0b01 << 6)
|
||||
#define TT_S1_ATTR_AP_RO_PL1 (0b10 << 6)
|
||||
#define TT_S1_ATTR_AP_RO_ANY (0b11 << 6)
|
||||
|
||||
#define TT_S1_ATTR_SH_NONE (0b00 << 8)
|
||||
#define TT_S1_ATTR_SH_OUTER (0b10 << 8)
|
||||
#define TT_S1_ATTR_SH_INNER (0b11 << 8)
|
||||
|
||||
#define TT_S1_ATTR_AF (1 << 10)
|
||||
#define TT_S1_ATTR_nG (1 << 11)
|
||||
|
||||
// OA bits [15:12] - If Armv8.2-LPA is implemented, bits[15:12] are bits[51:48]
|
||||
// and bits[47:16] are bits[47:16] of the output address for a page of memory
|
||||
|
||||
#define TT_S1_ATTR_nT (1 << 16) // Present if Armv8.4-TTRem is implemented, otherwise RES0
|
||||
|
||||
#define TT_S1_ATTR_DBM (1 << 51) // Present if Armv8.1-TTHM is implemented, otherwise RES0
|
||||
|
||||
#define TT_S1_ATTR_CONTIG (1 << 52)
|
||||
#define TT_S1_ATTR_PXN (1 << 53)
|
||||
#define TT_S1_ATTR_UXN (1 << 54)
|
||||
|
||||
// PBHA bits[62:59] - If Armv8.2-TTPBHA is implemented, hardware can use these bits
|
||||
// for IMPLEMENTATIONDEFINED purposes, otherwise IGNORED
|
||||
|
||||
#define TT_S1_MAIR_DEV_nGnRnE 0b00000000
|
||||
#define TT_S1_MAIR_DEV_nGnRE 0b00000100
|
||||
#define TT_S1_MAIR_DEV_nGRE 0b00001000
|
||||
#define TT_S1_MAIR_DEV_GRE 0b00001100
|
||||
|
||||
//
|
||||
// Inner and Outer Normal memory attributes use the same bit patterns
|
||||
// Outer attributes just need to be shifted up
|
||||
//
|
||||
#define TT_S1_MAIR_OUTER_SHIFT 4
|
||||
|
||||
#define TT_S1_MAIR_WT_TRANS_RA 0b0010
|
||||
|
||||
#define TT_S1_MAIR_WB_TRANS_RA 0b0110
|
||||
#define TT_S1_MAIR_WB_TRANS_RWA 0b0111
|
||||
|
||||
#define TT_S1_MAIR_WT_RA 0b1010
|
||||
|
||||
#define TT_S1_MAIR_WB_RA 0b1110
|
||||
#define TT_S1_MAIR_WB_RWA 0b1111
|
||||
|
||||
#endif // V8_MMU_H
|
||||
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// Defines for v8 System Registers
|
||||
//
|
||||
// Copyright (c) 2012-2016 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
#ifndef V8_SYSTEM_H
|
||||
#define V8_SYSTEM_H
|
||||
|
||||
//
|
||||
// AArch64 SPSR
|
||||
//
|
||||
#define AARCH64_SPSR_EL3h 0b1101
|
||||
#define AARCH64_SPSR_EL3t 0b1100
|
||||
#define AARCH64_SPSR_EL2h 0b1001
|
||||
#define AARCH64_SPSR_EL2t 0b1000
|
||||
#define AARCH64_SPSR_EL1h 0b0101
|
||||
#define AARCH64_SPSR_EL1t 0b0100
|
||||
#define AARCH64_SPSR_EL0t 0b0000
|
||||
#define AARCH64_SPSR_RW (1 << 4)
|
||||
#define AARCH64_SPSR_F (1 << 6)
|
||||
#define AARCH64_SPSR_I (1 << 7)
|
||||
#define AARCH64_SPSR_A (1 << 8)
|
||||
#define AARCH64_SPSR_D (1 << 9)
|
||||
#define AARCH64_SPSR_IL (1 << 20)
|
||||
#define AARCH64_SPSR_SS (1 << 21)
|
||||
#define AARCH64_SPSR_V (1 << 28)
|
||||
#define AARCH64_SPSR_C (1 << 29)
|
||||
#define AARCH64_SPSR_Z (1 << 30)
|
||||
#define AARCH64_SPSR_N (1 << 31)
|
||||
|
||||
//
|
||||
// Multiprocessor Affinity Register
|
||||
//
|
||||
#define MPIDR_EL1_AFF3_LSB 32
|
||||
#define MPIDR_EL1_U (1 << 30)
|
||||
#define MPIDR_EL1_MT (1 << 24)
|
||||
#define MPIDR_EL1_AFF2_LSB 16
|
||||
#define MPIDR_EL1_AFF1_LSB 8
|
||||
#define MPIDR_EL1_AFF0_LSB 0
|
||||
#define MPIDR_EL1_AFF_WIDTH 8
|
||||
|
||||
//
|
||||
// Data Cache Zero ID Register
|
||||
//
|
||||
#define DCZID_EL0_BS_LSB 0
|
||||
#define DCZID_EL0_BS_WIDTH 4
|
||||
#define DCZID_EL0_DZP_LSB 5
|
||||
#define DCZID_EL0_DZP (1 << 5)
|
||||
|
||||
//
|
||||
// System Control Register
|
||||
//
|
||||
#define SCTLR_EL1_UCI (1 << 26)
|
||||
#define SCTLR_ELx_EE (1 << 25)
|
||||
#define SCTLR_EL1_E0E (1 << 24)
|
||||
#define SCTLR_ELx_WXN (1 << 19)
|
||||
#define SCTLR_EL1_nTWE (1 << 18)
|
||||
#define SCTLR_EL1_nTWI (1 << 16)
|
||||
#define SCTLR_EL1_UCT (1 << 15)
|
||||
#define SCTLR_EL1_DZE (1 << 14)
|
||||
#define SCTLR_ELx_I (1 << 12)
|
||||
#define SCTLR_EL1_UMA (1 << 9)
|
||||
#define SCTLR_EL1_SED (1 << 8)
|
||||
#define SCTLR_EL1_ITD (1 << 7)
|
||||
#define SCTLR_EL1_THEE (1 << 6)
|
||||
#define SCTLR_EL1_CP15BEN (1 << 5)
|
||||
#define SCTLR_EL1_SA0 (1 << 4)
|
||||
#define SCTLR_ELx_SA (1 << 3)
|
||||
#define SCTLR_ELx_C (1 << 2)
|
||||
#define SCTLR_ELx_A (1 << 1)
|
||||
#define SCTLR_ELx_M (1 << 0)
|
||||
|
||||
//
|
||||
// Architectural Feature Access Control Register
|
||||
//
|
||||
#define CPACR_EL1_TTA (1 << 28)
|
||||
#define CPACR_EL1_FPEN (3 << 20)
|
||||
|
||||
//
|
||||
// Architectural Feature Trap Register
|
||||
//
|
||||
#define CPTR_ELx_TCPAC (1 << 31)
|
||||
#define CPTR_ELx_TTA (1 << 20)
|
||||
#define CPTR_ELx_TFP (1 << 10)
|
||||
|
||||
//
|
||||
// Secure Configuration Register
|
||||
//
|
||||
#define SCR_EL3_TWE (1 << 13)
|
||||
#define SCR_EL3_TWI (1 << 12)
|
||||
#define SCR_EL3_ST (1 << 11)
|
||||
#define SCR_EL3_RW (1 << 10)
|
||||
#define SCR_EL3_SIF (1 << 9)
|
||||
#define SCR_EL3_HCE (1 << 8)
|
||||
#define SCR_EL3_SMD (1 << 7)
|
||||
#define SCR_EL3_EA (1 << 3)
|
||||
#define SCR_EL3_FIQ (1 << 2)
|
||||
#define SCR_EL3_IRQ (1 << 1)
|
||||
#define SCR_EL3_NS (1 << 0)
|
||||
|
||||
//
|
||||
// Hypervisor Configuration Register
|
||||
//
|
||||
#define HCR_EL2_ID (1 << 33)
|
||||
#define HCR_EL2_CD (1 << 32)
|
||||
#define HCR_EL2_RW (1 << 31)
|
||||
#define HCR_EL2_TRVM (1 << 30)
|
||||
#define HCR_EL2_HVC (1 << 29)
|
||||
#define HCR_EL2_TDZ (1 << 28)
|
||||
|
||||
#endif // V8_SYSTEM_H
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// Simple utility routines for baremetal v8 code
|
||||
//
|
||||
// Copyright (c) 2013-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
#include "v8_system.h"
|
||||
|
||||
.text
|
||||
.cfi_sections .debug_frame // put stack frame info into .debug_frame instead of .eh_frame
|
||||
|
||||
//
|
||||
// void *ZeroBlock(void *blockPtr, unsigned int nBytes)
|
||||
//
|
||||
// Zero fill a block of memory
|
||||
// Fill memory pages or similar structures with zeros.
|
||||
// The byte count must be a multiple of the block fill size (16 bytes)
|
||||
//
|
||||
// Inputs:
|
||||
// blockPtr - base address of block to fill
|
||||
// nBytes - block size, in bytes
|
||||
//
|
||||
// Returns:
|
||||
// pointer to just filled block, NULL if nBytes is
|
||||
// incompatible with block fill size
|
||||
//
|
||||
.global ZeroBlock
|
||||
.type ZeroBlock, "function"
|
||||
.cfi_startproc
|
||||
ZeroBlock:
|
||||
|
||||
//
|
||||
// we fill data by steam, 16 bytes at a time: check that
|
||||
// blocksize is a multiple of that
|
||||
//
|
||||
ubfx x2, x1, #0, #4
|
||||
cbnz x2, incompatible
|
||||
|
||||
//
|
||||
// we already have one register full of zeros, get another
|
||||
//
|
||||
mov x3, x2
|
||||
|
||||
//
|
||||
// OK, set temporary pointer and away we go
|
||||
//
|
||||
add x0, x0, x1
|
||||
|
||||
loop0:
|
||||
subs x1, x1, #16
|
||||
stp x2, x3, [x0, #-16]!
|
||||
b.ne loop0
|
||||
|
||||
//
|
||||
// that's all - x0 will be back to its start value
|
||||
//
|
||||
ret
|
||||
|
||||
//
|
||||
// parameters are incompatible with block size - return
|
||||
// an indication that this is so
|
||||
//
|
||||
incompatible:
|
||||
mov x0,#0
|
||||
ret
|
||||
.cfi_endproc
|
||||
@@ -0,0 +1,252 @@
|
||||
// ------------------------------------------------------------
|
||||
// Armv8-A Vector tables
|
||||
//
|
||||
// Copyright (c) 2014-2016 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
|
||||
.global el1_vectors
|
||||
.global el2_vectors
|
||||
.global el3_vectors
|
||||
.global c0sync1
|
||||
.global irqHandler
|
||||
.global fiqHandler
|
||||
.global irqFirstLevelHandler
|
||||
.global fiqFirstLevelHandler
|
||||
|
||||
.section EL1VECTORS, "ax"
|
||||
.align 11
|
||||
|
||||
//
|
||||
// Current EL with SP0
|
||||
//
|
||||
el1_vectors:
|
||||
c0sync1: B c0sync1
|
||||
|
||||
.balign 0x80
|
||||
c0irq1: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
c0fiq1: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
c0serr1: B c0serr1
|
||||
|
||||
//
|
||||
// Current EL with SPx
|
||||
//
|
||||
.balign 0x80
|
||||
cxsync1: B cxsync1
|
||||
|
||||
.balign 0x80
|
||||
cxirq1: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
cxfiq1: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
cxserr1: B cxserr1
|
||||
|
||||
//
|
||||
// Lower EL using AArch64
|
||||
//
|
||||
.balign 0x80
|
||||
l64sync1: B l64sync1
|
||||
|
||||
.balign 0x80
|
||||
l64irq1: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l64fiq1: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l64serr1: B l64serr1
|
||||
|
||||
//
|
||||
// Lower EL using AArch32
|
||||
//
|
||||
.balign 0x80
|
||||
l32sync1: B l32sync1
|
||||
|
||||
.balign 0x80
|
||||
l32irq1: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l32fiq1: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l32serr1: B l32serr1
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
.section EL2VECTORS, "ax"
|
||||
.align 11
|
||||
|
||||
//
|
||||
// Current EL with SP0
|
||||
//
|
||||
el2_vectors:
|
||||
c0sync2: B c0sync2
|
||||
|
||||
.balign 0x80
|
||||
c0irq2: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
c0fiq2: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
c0serr2: B c0serr2
|
||||
|
||||
//
|
||||
// Current EL with SPx
|
||||
//
|
||||
.balign 0x80
|
||||
cxsync2: B cxsync2
|
||||
|
||||
.balign 0x80
|
||||
cxirq2: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
cxfiq2: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
cxserr2: B cxserr2
|
||||
|
||||
//
|
||||
// Lower EL using AArch64
|
||||
//
|
||||
.balign 0x80
|
||||
l64sync2: B l64sync2
|
||||
|
||||
.balign 0x80
|
||||
l64irq2: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l64fiq2: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l64serr2: B l64serr2
|
||||
|
||||
//
|
||||
// Lower EL using AArch32
|
||||
//
|
||||
.balign 0x80
|
||||
l32sync2: B l32sync2
|
||||
|
||||
.balign 0x80
|
||||
l32irq2: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l32fiq2: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l32serr2: B l32serr2
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
.section EL3VECTORS, "ax"
|
||||
.align 11
|
||||
|
||||
//
|
||||
// Current EL with SP0
|
||||
//
|
||||
el3_vectors:
|
||||
c0sync3: B c0sync3
|
||||
|
||||
.balign 0x80
|
||||
c0irq3: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
c0fiq3: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
c0serr3: B c0serr3
|
||||
|
||||
//
|
||||
// Current EL with SPx
|
||||
//
|
||||
.balign 0x80
|
||||
cxsync3: B cxsync3
|
||||
|
||||
.balign 0x80
|
||||
cxirq3: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
cxfiq3: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
cxserr3: B cxserr3
|
||||
|
||||
//
|
||||
// Lower EL using AArch64
|
||||
//
|
||||
.balign 0x80
|
||||
l64sync3: B l64sync3
|
||||
|
||||
.balign 0x80
|
||||
l64irq3: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l64fiq3: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l64serr3: B l64serr3
|
||||
|
||||
//
|
||||
// Lower EL using AArch32
|
||||
//
|
||||
.balign 0x80
|
||||
l32sync3: B l32sync3
|
||||
|
||||
.balign 0x80
|
||||
l32irq3: B irqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l32fiq3: B fiqFirstLevelHandler
|
||||
|
||||
.balign 0x80
|
||||
l32serr3: B l32serr3
|
||||
|
||||
|
||||
.section InterruptHandlers, "ax"
|
||||
.balign 4
|
||||
|
||||
.type irqFirstLevelHandler, "function"
|
||||
irqFirstLevelHandler:
|
||||
MSR SPSel, 0
|
||||
STP x29, x30, [sp, #-16]!
|
||||
BL _tx_thread_context_save
|
||||
BL irqHandler
|
||||
B _tx_thread_context_restore
|
||||
|
||||
.type fiqFirstLevelHandler, "function"
|
||||
fiqFirstLevelHandler:
|
||||
STP x29, x30, [sp, #-16]!
|
||||
STP x18, x19, [sp, #-16]!
|
||||
STP x16, x17, [sp, #-16]!
|
||||
STP x14, x15, [sp, #-16]!
|
||||
STP x12, x13, [sp, #-16]!
|
||||
STP x10, x11, [sp, #-16]!
|
||||
STP x8, x9, [sp, #-16]!
|
||||
STP x6, x7, [sp, #-16]!
|
||||
STP x4, x5, [sp, #-16]!
|
||||
STP x2, x3, [sp, #-16]!
|
||||
STP x0, x1, [sp, #-16]!
|
||||
|
||||
BL fiqHandler
|
||||
|
||||
LDP x0, x1, [sp], #16
|
||||
LDP x2, x3, [sp], #16
|
||||
LDP x4, x5, [sp], #16
|
||||
LDP x6, x7, [sp], #16
|
||||
LDP x8, x9, [sp], #16
|
||||
LDP x10, x11, [sp], #16
|
||||
LDP x12, x13, [sp], #16
|
||||
LDP x14, x15, [sp], #16
|
||||
LDP x16, x17, [sp], #16
|
||||
LDP x18, x19, [sp], #16
|
||||
LDP x29, x30, [sp], #16
|
||||
ERET
|
||||
162
ports_arch/ARMv8-A/threadx/ports/gnu/example_build/tx/.cproject
Normal file
162
ports_arch/ARMv8-A/threadx/ports/gnu/example_build/tx/.cproject
Normal file
@@ -0,0 +1,162 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
|
||||
<cconfiguration id="com.arm.eclipse.build.config.v6.lib.debug.base.332565915">
|
||||
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.lib.debug.base.332565915" moduleId="org.eclipse.cdt.core.settings" name="Debug">
|
||||
|
||||
<externalSettings/>
|
||||
|
||||
<extensions>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<configuration artifactExtension="a" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.staticLib" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.staticLib,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="clean" description="" id="com.arm.eclipse.build.config.v6.lib.debug.base.332565915" name="Debug" parent="com.arm.eclipse.build.config.v6.lib.debug.base">
|
||||
|
||||
<folderInfo id="com.arm.eclipse.build.config.v6.lib.debug.base.332565915." name="/" resourcePath="">
|
||||
|
||||
<toolChain id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.toolchain.var.gcc-8.3.0-aarch64-elf.1652432530" name="GCC 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.toolchain.var.gcc-8.3.0-aarch64-elf">
|
||||
|
||||
<targetPlatform id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.toolchain.var.gcc-8.3.0-aarch64-elf.1652432530.1250098983" name=""/>
|
||||
|
||||
<builder buildPath="${workspace_loc:/tx}/Debug" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.target.builder.408478790" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.target.builder"/>
|
||||
|
||||
<tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.var.gcc-8.3.0-aarch64-elf.1755052156" name="GCC C Compiler 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.var.gcc-8.3.0-aarch64-elf">
|
||||
|
||||
<option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.cpu.281590127" name="CPU (-mcpu)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.cpu" useByScannerDiscovery="false" value="cortex-a35" valueType="string"/>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.defsym.1254489229" name="Defined symbols (-D)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.defsym" useByScannerDiscovery="false" valueType="definedSymbols">
|
||||
|
||||
<listOptionValue builtIn="false" value="STANDALONE"/>
|
||||
|
||||
<listOptionValue builtIn="false" value="ENABLE_ARM_FP"/>
|
||||
|
||||
</option>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.includepath.1541383646" name="Include paths (-I)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.includepath" useByScannerDiscovery="false" valueType="includePath">
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc_generic}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/inc_port}""/>
|
||||
|
||||
</option>
|
||||
|
||||
<option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt.379931340" name="Optimization Level" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt" useByScannerDiscovery="false" value="gnu.c.optimization.level.none" valueType="enumerated"/>
|
||||
|
||||
<inputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.input.11119542" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.compiler.var.gcc-8.3.0-aarch64-elf.1308248336" name="GCC C++ Compiler 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.compiler.var.gcc-8.3.0-aarch64-elf">
|
||||
|
||||
<option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt.842447027" name="Optimization Level" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.compiler.option.opt" useByScannerDiscovery="false" value="gnu.c.optimization.level.none" valueType="enumerated"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool command="aarch64-elf-gcc.exe" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.var.gcc-8.3.0-aarch64-elf.2113642977" name="GCC Assembler 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.var.gcc-8.3.0-aarch64-elf">
|
||||
|
||||
<option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.cpu.1603138513" name="CPU (-mcpu)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.cpu" useByScannerDiscovery="false" value="cortex-a35" valueType="string"/>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.defsym.1797095306" name="Defined symbols (-D)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.defsym" useByScannerDiscovery="false" valueType="definedSymbols">
|
||||
|
||||
<listOptionValue builtIn="false" value="EL1"/>
|
||||
|
||||
</option>
|
||||
|
||||
<option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.debug.1075418381" name="Generate debugging information (-g)" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.option.debug" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
|
||||
<inputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.input.93700751" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.assembler.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool command="aarch64-elf-ar.exe" id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.var.gcc-8.3.0-aarch64-elf.1983468481" name="GCC C Linker 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.var.gcc-8.3.0-aarch64-elf">
|
||||
|
||||
<option id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.flags.1806767239" name="Other flags" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.option.flags" useByScannerDiscovery="false" value="-r" valueType="string"/>
|
||||
|
||||
<inputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.input.1298708086" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.input">
|
||||
|
||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
||||
|
||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
||||
|
||||
</inputType>
|
||||
|
||||
<outputType id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.output.478221475" outputPrefix="lib" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.c.linker.output"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.linker.var.gcc-8.3.0-aarch64-elf.2101445430" name="GCC C++ Linker 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.cpp.linker.var.gcc-8.3.0-aarch64-elf"/>
|
||||
|
||||
<tool id="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.archiver.var.gcc-8.3.0-aarch64-elf.1756490450" name="GCC Archiver 8.3.0 [aarch64-elf]" superClass="com.arm.eclipse.cdt.managedbuild.ds5.gcc.baremetal.tool.archiver.var.gcc-8.3.0-aarch64-elf"/>
|
||||
|
||||
</toolChain>
|
||||
|
||||
</folderInfo>
|
||||
|
||||
<sourceEntries>
|
||||
|
||||
<entry excluding="src_generic/tx_misra.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
|
||||
</sourceEntries>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
|
||||
</cconfiguration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<project id="tx.com.arm.eclipse.build.project.v6.lib.1209080418" name="Static Library"/>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
|
||||
<storageModule moduleId="refreshScope" versionNumber="2">
|
||||
|
||||
<configuration configurationName="Debug">
|
||||
|
||||
<resource resourceType="PROJECT" workspacePath="/tx"/>
|
||||
|
||||
</configuration>
|
||||
|
||||
<configuration configurationName="Release">
|
||||
|
||||
<resource resourceType="PROJECT" workspacePath="/tx"/>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
|
||||
<storageModule moduleId="com.arm.projectSettings" version="6.0.0"/>
|
||||
|
||||
</cproject>
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>tx</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
<linkedResources>
|
||||
<link>
|
||||
<name>inc_generic</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common/inc</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>inc_port</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/inc</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src_generic</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-5-PROJECT_LOC%7D/common/src</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src_port</name>
|
||||
<type>2</type>
|
||||
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/src</locationURI>
|
||||
</link>
|
||||
</linkedResources>
|
||||
</projectDescription>
|
||||
@@ -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 */
|
||||
/** */
|
||||
/** Initialize */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_initialize_low_level ARMv8-A */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is responsible for any low-level processor */
|
||||
/* initialization, including setting up interrupt vectors, setting */
|
||||
/* up a periodic timer interrupt source, saving the system stack */
|
||||
/* pointer for use in ISR processing later, and finding the first */
|
||||
/* available RAM memory address for tx_application_define. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_initialize_low_level(VOID)
|
||||
// {
|
||||
.global _tx_initialize_low_level
|
||||
.type _tx_initialize_low_level, @function
|
||||
_tx_initialize_low_level:
|
||||
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
|
||||
|
||||
/* Save the system stack pointer. */
|
||||
// _tx_thread_system_stack_ptr = (VOID_PTR) (sp);
|
||||
|
||||
LDR x0, =_tx_thread_system_stack_ptr // Pickup address of system stack ptr
|
||||
MOV x1, sp // Pickup SP
|
||||
SUB x1, x1, #15 //
|
||||
BIC x1, x1, #0xF // Get 16-bit alignment
|
||||
STR x1, [x0] // Store system stack
|
||||
|
||||
/* Save the first available memory address. */
|
||||
// _tx_initialize_unused_memory = (VOID_PTR) Image$$ZI$$Limit;
|
||||
|
||||
LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr
|
||||
LDR x1, =__top_of_ram // Pickup unused memory address
|
||||
LDR x1, [x1] //
|
||||
STR x1, [x0] // Store unused memory address
|
||||
|
||||
/* Done, return to caller. */
|
||||
|
||||
RET // Return to caller
|
||||
// }
|
||||
@@ -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 */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "txm_module.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_port_dispatch Cortex-A35/AC6 */
|
||||
/* 6.1.10 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Andres Mlinar, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function dispatches the module's kernel request based upon the */
|
||||
/* ID and parameters specified in the request. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* module_instance Module pointer */
|
||||
/* kernel_request Module's kernel request */
|
||||
/* param_0 First parameter */
|
||||
/* param_1 Second parameter */
|
||||
/* param_2 Third parameter */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* status Completion status */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* Port-specific ThreadX API Calls */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _txm_module_manager_kernel_dispatch */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 01-31-2022 Andres Mlinar Initial Version 6.1.10 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
ALIGN_TYPE _txm_module_manager_port_dispatch(TXM_MODULE_INSTANCE *module_instance, ULONG kernel_request, ALIGN_TYPE param_0, ALIGN_TYPE param_1, ALIGN_TYPE param_2)
|
||||
{
|
||||
|
||||
ALIGN_TYPE return_value = TX_NOT_AVAILABLE;
|
||||
|
||||
switch(kernel_request)
|
||||
{
|
||||
default:
|
||||
{
|
||||
/* Unhandled kernel request, return an error! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(return_value);
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/** Module Manager */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _txm_module_manager_thread_stack_build Cortex-A35-SMP/AC6 */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* Andres Mlinar, 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 */
|
||||
/* function_ptr Pointer to entry function */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_thread_create Create thread service */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 01-31-2022 Andres Mlinar Initial Version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _txm_module_manager_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(TX_THREAD *, TXM_MODULE_INSTANCE *))
|
||||
// {
|
||||
.global _txm_module_manager_thread_stack_build
|
||||
.type _txm_module_manager_thread_stack_build, @function
|
||||
_txm_module_manager_thread_stack_build:
|
||||
|
||||
|
||||
/* Build an interrupt frame. On Cortex-A35 it should look like this:
|
||||
|
||||
Stack Top: SSPR Initial SSPR
|
||||
ELR Point of interrupt
|
||||
x28 Initial value for x28
|
||||
not used Not used
|
||||
x26 Initial value for x26
|
||||
x27 Initial value for x27
|
||||
x24 Initial value for x24
|
||||
x25 Initial value for x25
|
||||
x22 Initial value for x22
|
||||
x23 Initial value for x23
|
||||
x20 Initial value for x20
|
||||
x21 Initial value for x21
|
||||
x18 Initial value for x18
|
||||
x19 Initial value for x19
|
||||
x16 Initial value for x16
|
||||
x17 Initial value for x17
|
||||
x14 Initial value for x14
|
||||
x15 Initial value for x15
|
||||
x12 Initial value for x12
|
||||
x13 Initial value for x13
|
||||
x10 Initial value for x10
|
||||
x11 Initial value for x11
|
||||
x8 Initial value for x8
|
||||
x9 Initial value for x9
|
||||
x6 Initial value for x6
|
||||
x7 Initial value for x7
|
||||
x4 Initial value for x4
|
||||
x5 Initial value for x5
|
||||
x2 Initial value for x2
|
||||
x3 Initial value for x3
|
||||
x0 Initial value for x0
|
||||
x1 Initial value for x1
|
||||
x29 Initial value for x29 (frame pointer)
|
||||
x30 Initial value for x30 (link register)
|
||||
0 For stack backtracing
|
||||
|
||||
Stack Bottom: (higher memory address)
|
||||
*/
|
||||
|
||||
LDR x4, [x0, #24] // Pickup end of stack area
|
||||
BIC x4, x4, #0xF // Ensure 16-byte alignment
|
||||
|
||||
LDR x5, [x0, #8] // Pickup thread entry info pointer,which is in the stack pointer position of the thread control block.
|
||||
// It was setup in the txm_module_manager_thread_create function. It will be overwritten later in this
|
||||
// function with the actual, initial stack pointer.
|
||||
|
||||
/* Actually build the stack frame. */
|
||||
|
||||
MOV x2, #0 // Build clear value
|
||||
MOV x3, #0 //
|
||||
|
||||
STP x2, x3, [x4, #-16]! // Set backtrace to 0
|
||||
STP x2, x3, [x4, #-16]! // Set initial x29, x30
|
||||
STP x0, x5, [x4, #-16]! // Set initial x0, x1
|
||||
// x0->x0 is the thread control block pointer
|
||||
// x5->x1 is the thread entry info pointer
|
||||
STP x2, x3, [x4, #-16]! // Set initial x2, x3
|
||||
STP x2, x3, [x4, #-16]! // Set initial x4, x5
|
||||
STP x2, x3, [x4, #-16]! // Set initial x6, x7
|
||||
STP x2, x3, [x4, #-16]! // Set initial x8, x9
|
||||
STP x2, x3, [x4, #-16]! // Set initial x10, x11
|
||||
STP x2, x3, [x4, #-16]! // Set initial x12, x13
|
||||
STP x2, x3, [x4, #-16]! // Set initial x14, x15
|
||||
STP x2, x3, [x4, #-16]! // Set initial x16, x17
|
||||
STP x2, x3, [x4, #-16]! // Set initial x18, x19
|
||||
STP x2, x3, [x4, #-16]! // Set initial x20, x21
|
||||
STP x2, x3, [x4, #-16]! // Set initial x22, x23
|
||||
STP x2, x3, [x4, #-16]! // Set initial x24, x25
|
||||
STP x2, x3, [x4, #-16]! // Set initial x26, x27
|
||||
STP x2, x3, [x4, #-16]! // Set initial x28
|
||||
#ifdef EL1
|
||||
MOV x2, #0x4 // Build initial SPSR (EL1)
|
||||
#else
|
||||
#ifdef EL2
|
||||
MOV x2, #0x8 // Build initial SPSR (EL2)
|
||||
#else
|
||||
MOV x2, #0xC // Build initial SPSR (EL3)
|
||||
#endif
|
||||
#endif
|
||||
MOV x3, x1 // Build initial ELR
|
||||
STP x2, x3, [x4, #-16]! // Set initial SPSR & ELR
|
||||
|
||||
/* Setup stack pointer. */
|
||||
/* thread_ptr -> tx_thread_stack_ptr = x2; */
|
||||
|
||||
STR x4, [x0, #8] // Save stack pointer in thread's
|
||||
MOV x3, #1 // Build ready flag
|
||||
STR w3, [x0, #260] // Set ready flag
|
||||
RET // Return to caller
|
||||
|
||||
// }
|
||||
@@ -0,0 +1,393 @@
|
||||
/* This is a small demo of the high-performance ThreadX kernel. It includes examples of eight
|
||||
threads of different priorities, using a message queue, semaphore, mutex, event flags group,
|
||||
byte pool, and block pool. */
|
||||
|
||||
#include "tx_api.h"
|
||||
|
||||
|
||||
extern void init_timer(void); /* in timer_interrupts.c */
|
||||
|
||||
|
||||
#define DEMO_STACK_SIZE 1024
|
||||
#define DEMO_BYTE_POOL_SIZE 9120
|
||||
#define DEMO_BLOCK_POOL_SIZE 100
|
||||
#define DEMO_QUEUE_SIZE 100
|
||||
|
||||
|
||||
/* Define byte pool memory. */
|
||||
|
||||
UCHAR byte_pool_memory[DEMO_BYTE_POOL_SIZE];
|
||||
|
||||
|
||||
|
||||
|
||||
/* Define the ThreadX object control blocks... */
|
||||
|
||||
TX_THREAD thread_0;
|
||||
TX_THREAD thread_1;
|
||||
TX_THREAD thread_2;
|
||||
TX_THREAD thread_3;
|
||||
TX_THREAD thread_4;
|
||||
TX_THREAD thread_5;
|
||||
TX_THREAD thread_6;
|
||||
TX_THREAD thread_7;
|
||||
TX_TIMER timer_0;
|
||||
TX_QUEUE queue_0;
|
||||
TX_SEMAPHORE semaphore_0;
|
||||
TX_MUTEX mutex_0;
|
||||
TX_EVENT_FLAGS_GROUP event_flags_0;
|
||||
TX_BYTE_POOL byte_pool_0;
|
||||
TX_BLOCK_POOL block_pool_0;
|
||||
|
||||
|
||||
/* Define the counters used in the demo application... */
|
||||
|
||||
ULONG thread_0_counter;
|
||||
ULONG thread_1_counter;
|
||||
ULONG thread_1_messages_sent;
|
||||
ULONG thread_2_counter;
|
||||
ULONG thread_2_messages_received;
|
||||
ULONG thread_3_counter;
|
||||
ULONG thread_4_counter;
|
||||
ULONG thread_5_counter;
|
||||
ULONG thread_6_counter;
|
||||
ULONG thread_7_counter;
|
||||
|
||||
|
||||
/* Define thread prototypes. */
|
||||
|
||||
void thread_0_entry(ULONG thread_input);
|
||||
void thread_1_entry(ULONG thread_input);
|
||||
void thread_2_entry(ULONG thread_input);
|
||||
void thread_3_and_4_entry(ULONG thread_input);
|
||||
void thread_5_entry(ULONG thread_input);
|
||||
void thread_6_and_7_entry(ULONG thread_input);
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
UCHAR event_buffer[65536];
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define main entry point. */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
||||
/* Initialize timer. */
|
||||
init_timer();
|
||||
|
||||
/* Enter ThreadX. */
|
||||
tx_kernel_enter();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Define what the initial system looks like. */
|
||||
|
||||
void tx_application_define(void *first_unused_memory)
|
||||
{
|
||||
|
||||
CHAR *pointer = TX_NULL;
|
||||
|
||||
|
||||
#ifdef TX_ENABLE_EVENT_TRACE
|
||||
|
||||
tx_trace_enable(event_buffer, sizeof(event_buffer), 32);
|
||||
#endif
|
||||
|
||||
/* Create a byte memory pool from which to allocate the thread stacks. */
|
||||
tx_byte_pool_create(&byte_pool_0, "byte pool 0", byte_pool_memory, DEMO_BYTE_POOL_SIZE);
|
||||
|
||||
/* Allocate the stack for thread 0. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create the main thread. */
|
||||
tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 1. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create threads 1 and 2. These threads pass information through a ThreadX
|
||||
message queue. It is also interesting to note that these threads have a time
|
||||
slice. */
|
||||
tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
16, 16, 4, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 2. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
16, 16, 4, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 3. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create threads 3 and 4. These threads compete for a ThreadX counting semaphore.
|
||||
An interesting thing here is that both threads share the same instruction area. */
|
||||
tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 4. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 5. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create thread 5. This thread simply pends on an event flag which will be set
|
||||
by thread_0. */
|
||||
tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 6. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create threads 6 and 7. These threads compete for a ThreadX mutex. */
|
||||
tx_thread_create(&thread_6, "thread 6", thread_6_and_7_entry, 6,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the stack for thread 7. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);
|
||||
|
||||
tx_thread_create(&thread_7, "thread 7", thread_6_and_7_entry, 7,
|
||||
pointer, DEMO_STACK_SIZE,
|
||||
8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
|
||||
|
||||
/* Allocate the message queue. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_QUEUE_SIZE*sizeof(ULONG), TX_NO_WAIT);
|
||||
|
||||
/* Create the message queue shared by threads 1 and 2. */
|
||||
tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG));
|
||||
|
||||
/* Create the semaphore used by threads 3 and 4. */
|
||||
tx_semaphore_create(&semaphore_0, "semaphore 0", 1);
|
||||
|
||||
/* Create the event flags group used by threads 1 and 5. */
|
||||
tx_event_flags_create(&event_flags_0, "event flags 0");
|
||||
|
||||
/* Create the mutex used by thread 6 and 7 without priority inheritance. */
|
||||
tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT);
|
||||
|
||||
/* Allocate the memory for a small block pool. */
|
||||
tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_BLOCK_POOL_SIZE, TX_NO_WAIT);
|
||||
|
||||
/* Create a block memory pool to allocate a message buffer from. */
|
||||
tx_block_pool_create(&block_pool_0, "block pool 0", sizeof(ULONG), pointer, DEMO_BLOCK_POOL_SIZE);
|
||||
|
||||
/* Allocate a block and release the block memory. */
|
||||
tx_block_allocate(&block_pool_0, (VOID **) &pointer, TX_NO_WAIT);
|
||||
|
||||
/* Release the block back to the pool. */
|
||||
tx_block_release(pointer);
|
||||
}
|
||||
|
||||
|
||||
/* Define the test threads. */
|
||||
|
||||
void thread_0_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* This thread simply sits in while-forever-sleep loop. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
thread_0_counter++;
|
||||
|
||||
/* Sleep for 10 ticks. */
|
||||
tx_thread_sleep(10);
|
||||
|
||||
/* Set event flag 0 to wakeup thread 5. */
|
||||
status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_1_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* This thread simply sends messages to a queue shared by thread 2. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
thread_1_counter++;
|
||||
|
||||
/* Send message to queue 0. */
|
||||
status = tx_queue_send(&queue_0, &thread_1_messages_sent, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check completion status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Increment the message sent. */
|
||||
thread_1_messages_sent++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_2_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
ULONG received_message;
|
||||
UINT status;
|
||||
|
||||
/* This thread retrieves messages placed on the queue by thread 1. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
thread_2_counter++;
|
||||
|
||||
/* Retrieve a message from the queue. */
|
||||
status = tx_queue_receive(&queue_0, &received_message, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check completion status and make sure the message is what we
|
||||
expected. */
|
||||
if ((status != TX_SUCCESS) || (received_message != thread_2_messages_received))
|
||||
break;
|
||||
|
||||
/* Otherwise, all is okay. Increment the received message count. */
|
||||
thread_2_messages_received++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_3_and_4_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* This function is executed from thread 3 and thread 4. As the loop
|
||||
below shows, these function compete for ownership of semaphore_0. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
if (thread_input == 3)
|
||||
thread_3_counter++;
|
||||
else
|
||||
thread_4_counter++;
|
||||
|
||||
/* Get the semaphore with suspension. */
|
||||
status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Sleep for 2 ticks to hold the semaphore. */
|
||||
tx_thread_sleep(2);
|
||||
|
||||
/* Release the semaphore. */
|
||||
status = tx_semaphore_put(&semaphore_0);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_5_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
ULONG actual_flags;
|
||||
|
||||
|
||||
/* This thread simply waits for an event in a forever loop. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
thread_5_counter++;
|
||||
|
||||
/* Wait for event flag 0. */
|
||||
status = tx_event_flags_get(&event_flags_0, 0x1, TX_OR_CLEAR,
|
||||
&actual_flags, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check status. */
|
||||
if ((status != TX_SUCCESS) || (actual_flags != 0x1))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void thread_6_and_7_entry(ULONG thread_input)
|
||||
{
|
||||
|
||||
UINT status;
|
||||
|
||||
|
||||
/* This function is executed from thread 6 and thread 7. As the loop
|
||||
below shows, these function compete for ownership of mutex_0. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Increment the thread counter. */
|
||||
if (thread_input == 6)
|
||||
thread_6_counter++;
|
||||
else
|
||||
thread_7_counter++;
|
||||
|
||||
/* Get the mutex with suspension. */
|
||||
status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Get the mutex again with suspension. This shows
|
||||
that an owning thread may retrieve the mutex it
|
||||
owns multiple times. */
|
||||
status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Sleep for 2 ticks to hold the mutex. */
|
||||
tx_thread_sleep(2);
|
||||
|
||||
/* Release the mutex. */
|
||||
status = tx_mutex_put(&mutex_0);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
|
||||
/* Release the mutex again. This will actually
|
||||
release ownership since it was obtained twice. */
|
||||
status = tx_mutex_put(&mutex_0);
|
||||
|
||||
/* Check status. */
|
||||
if (status != TX_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
429
ports_arch/ARMv8-A/threadx_smp/common/inc/tx_port.h
Normal file
429
ports_arch/ARMv8-A/threadx_smp/common/inc/tx_port.h
Normal file
@@ -0,0 +1,429 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Port Specific */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* PORT SPECIFIC C INFORMATION RELEASE */
|
||||
/* */
|
||||
/* tx_port.h ARMv8-A-SMP */
|
||||
/* 6.1.10 */
|
||||
/* */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This file contains data type definitions that make the ThreadX */
|
||||
/* real-time kernel function identically on a variety of different */
|
||||
/* processor architectures. For example, the size or number of bits */
|
||||
/* in an "int" data type vary between microprocessor architectures and */
|
||||
/* even C compilers for the same microprocessor. ThreadX does not */
|
||||
/* directly use native C data types. Instead, ThreadX creates its */
|
||||
/* own special types that can be mapped to actual data types by this */
|
||||
/* file to guarantee consistency in the interface and functionality. */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Bhupendra Naphade Modified comment(s),updated */
|
||||
/* macro definition, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TX_PORT_H
|
||||
#define TX_PORT_H
|
||||
|
||||
|
||||
/************* Define ThreadX SMP constants. *************/
|
||||
|
||||
/* Define the ThreadX SMP maximum number of cores. */
|
||||
|
||||
#ifndef TX_THREAD_SMP_MAX_CORES
|
||||
#define TX_THREAD_SMP_MAX_CORES 4
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the ThreadX SMP core mask. */
|
||||
|
||||
#ifndef TX_THREAD_SMP_CORE_MASK
|
||||
#define TX_THREAD_SMP_CORE_MASK 0xF /* Where bit 0 represents Core 0, bit 1 represents Core 1, etc. */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define INLINE_DECLARE to whitespace for ARM compiler. */
|
||||
|
||||
#define INLINE_DECLARE
|
||||
|
||||
|
||||
/* Define ThreadX SMP initialization macro. */
|
||||
|
||||
#define TX_PORT_SPECIFIC_PRE_INITIALIZATION
|
||||
|
||||
|
||||
/* Define ThreadX SMP pre-scheduler initialization. */
|
||||
|
||||
#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION
|
||||
|
||||
|
||||
/* Enable the inter-core interrupt logic. */
|
||||
|
||||
#define TX_THREAD_SMP_INTER_CORE_INTERRUPT
|
||||
|
||||
|
||||
/* Determine if there is customer-specific wakeup logic needed. */
|
||||
|
||||
#ifdef TX_THREAD_SMP_WAKEUP_LOGIC
|
||||
|
||||
/* Include customer-specific wakeup code. */
|
||||
|
||||
#include "tx_thread_smp_core_wakeup.h"
|
||||
#else
|
||||
|
||||
#ifdef TX_THREAD_SMP_DEFAULT_WAKEUP_LOGIC
|
||||
|
||||
/* Default wakeup code. */
|
||||
#define TX_THREAD_SMP_WAKEUP_LOGIC
|
||||
#define TX_THREAD_SMP_WAKEUP(i) _tx_thread_smp_core_preempt(i)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Ensure that the in-line resume/suspend define is not allowed. */
|
||||
|
||||
#ifdef TX_INLINE_THREAD_RESUME_SUSPEND
|
||||
#undef TX_INLINE_THREAD_RESUME_SUSPEND
|
||||
#endif
|
||||
|
||||
|
||||
/************* End ThreadX SMP constants. *************/
|
||||
|
||||
|
||||
/* Determine if the optional ThreadX user define file should be used. */
|
||||
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
|
||||
|
||||
/* Yes, include the user defines in tx_user.h. The defines in this file may
|
||||
alternately be defined on the command line. */
|
||||
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* Define compiler library include files. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Define ThreadX basic types for this port. */
|
||||
|
||||
#define VOID void
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef int LONG;
|
||||
typedef unsigned int ULONG;
|
||||
typedef unsigned long long ULONG64;
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
#define ULONG64_DEFINED
|
||||
|
||||
/* Override the alignment type to use 64-bit alignment and storage for pointers. */
|
||||
|
||||
#define ALIGN_TYPE_DEFINED
|
||||
typedef unsigned long long ALIGN_TYPE;
|
||||
|
||||
|
||||
/* Override the free block marker for byte pools to be a 64-bit constant. */
|
||||
|
||||
#define TX_BYTE_BLOCK_FREE ((ALIGN_TYPE) 0xFFFFEEEEFFFFEEEE)
|
||||
|
||||
|
||||
/* Define the priority levels for ThreadX. Legal values range
|
||||
from 32 to 1024 and MUST be evenly divisible by 32. */
|
||||
|
||||
#ifndef TX_MAX_PRIORITIES
|
||||
#define TX_MAX_PRIORITIES 32
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
|
||||
thread creation is less than this value, the thread create call will return an error. */
|
||||
|
||||
#ifndef TX_MINIMUM_STACK
|
||||
#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the system timer thread's default stack size and priority. These are only applicable
|
||||
if TX_TIMER_PROCESS_IN_ISR is not defined. */
|
||||
|
||||
#ifndef TX_TIMER_THREAD_STACK_SIZE
|
||||
#define TX_TIMER_THREAD_STACK_SIZE 4096 /* Default timer thread stack size */
|
||||
#endif
|
||||
|
||||
#ifndef TX_TIMER_THREAD_PRIORITY
|
||||
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
|
||||
#endif
|
||||
|
||||
|
||||
/* Define various constants for the ThreadX ARM port. */
|
||||
|
||||
#define TX_INT_DISABLE 0xC0 /* Disable IRQ & FIQ interrupts */
|
||||
#define TX_INT_ENABLE 0x00 /* Enable IRQ & FIQ interrupts */
|
||||
|
||||
|
||||
/* Define the clock source for trace event entry time stamp. The following two item are port specific.
|
||||
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
|
||||
source constants would be:
|
||||
|
||||
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
|
||||
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
#define TX_TRACE_TIME_SOURCE _tx_thread_smp_time_get()
|
||||
#endif
|
||||
#else
|
||||
#ifndef TX_TRACE_TIME_SOURCE
|
||||
ULONG _tx_misra_time_stamp_get(VOID);
|
||||
#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get()
|
||||
#endif
|
||||
#endif
|
||||
#ifndef TX_TRACE_TIME_MASK
|
||||
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the port specific options for the _tx_build_options variable. This variable indicates
|
||||
how the ThreadX library was built. */
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_SUPPORT
|
||||
#define TX_FIQ_ENABLED 1
|
||||
#else
|
||||
#define TX_FIQ_ENABLED 0
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_IRQ_NESTING
|
||||
#define TX_IRQ_NESTING_ENABLED 2
|
||||
#else
|
||||
#define TX_IRQ_NESTING_ENABLED 0
|
||||
#endif
|
||||
|
||||
#ifdef TX_ENABLE_FIQ_NESTING
|
||||
#define TX_FIQ_NESTING_ENABLED 4
|
||||
#else
|
||||
#define TX_FIQ_NESTING_ENABLED 0
|
||||
#endif
|
||||
|
||||
#define TX_PORT_SPECIFIC_BUILD_OPTIONS (TX_FIQ_ENABLED | TX_IRQ_NESTING_ENABLED | TX_FIQ_NESTING_ENABLED)
|
||||
|
||||
|
||||
/* Define the in-line initialization constant so that modules with in-line
|
||||
initialization capabilities can prevent their initialization from being
|
||||
a function call. */
|
||||
|
||||
#ifdef TX_MISRA_ENABLE
|
||||
#define TX_DISABLE_INLINE
|
||||
#else
|
||||
#define TX_INLINE_INITIALIZATION
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
|
||||
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
|
||||
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
|
||||
define is negated, thereby forcing the stack fill which is necessary for the stack checking
|
||||
logic. */
|
||||
|
||||
#ifndef TX_MISRA_ENABLE
|
||||
#ifdef TX_ENABLE_STACK_CHECKING
|
||||
#undef TX_DISABLE_STACK_FILLING
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the TX_THREAD control block extensions for this port. The main reason
|
||||
for the multiple macros is so that backward compatibility can be maintained with
|
||||
existing ThreadX kernel awareness modules. */
|
||||
|
||||
#define TX_THREAD_EXTENSION_0
|
||||
#define TX_THREAD_EXTENSION_1
|
||||
#define TX_THREAD_EXTENSION_2 ULONG tx_thread_fp_enable;
|
||||
#define TX_THREAD_EXTENSION_3 VOID *tx_thread_extension_ptr;
|
||||
|
||||
|
||||
/* Define the port extensions of the remaining ThreadX objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_EXTENSION
|
||||
#define TX_BYTE_POOL_EXTENSION
|
||||
#define TX_EVENT_FLAGS_GROUP_EXTENSION
|
||||
#define TX_MUTEX_EXTENSION
|
||||
#define TX_QUEUE_EXTENSION
|
||||
#define TX_SEMAPHORE_EXTENSION
|
||||
#define TX_TIMER_EXTENSION
|
||||
|
||||
|
||||
/* Define the user extension field of the thread control block. Nothing
|
||||
additional is needed for this port so it is defined as white space. */
|
||||
|
||||
#ifndef TX_THREAD_USER_EXTENSION
|
||||
#define TX_THREAD_USER_EXTENSION
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
|
||||
tx_thread_shell_entry, and tx_thread_terminate. */
|
||||
|
||||
|
||||
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
|
||||
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
|
||||
|
||||
|
||||
/* Define the ThreadX object creation extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Define the ThreadX object deletion extensions for the remaining objects. */
|
||||
|
||||
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
|
||||
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
|
||||
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
|
||||
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
|
||||
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
|
||||
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
|
||||
|
||||
|
||||
/* Determine if the ARM architecture has the CLZ instruction. This is available on
|
||||
architectures v5 and above. If available, redefine the macro for calculating the
|
||||
lowest bit set. */
|
||||
|
||||
#ifndef TX_DISABLE_INLINE
|
||||
|
||||
#define TX_LOWEST_SET_BIT_CALCULATE(m, b) b = (UINT) __builtin_ctz((unsigned int) m);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Define the internal timer extension to also hold the thread pointer such that _tx_thread_timeout
|
||||
can figure out what thread timeout to process. */
|
||||
|
||||
#define TX_TIMER_INTERNAL_EXTENSION VOID *tx_timer_internal_extension_ptr;
|
||||
|
||||
|
||||
/* Define the thread timeout setup logic in _tx_thread_create. */
|
||||
|
||||
#define TX_THREAD_CREATE_TIMEOUT_SETUP(t) (t) -> tx_thread_timer.tx_timer_internal_timeout_function = &(_tx_thread_timeout); \
|
||||
(t) -> tx_thread_timer.tx_timer_internal_timeout_param = 0; \
|
||||
(t) -> tx_thread_timer.tx_timer_internal_extension_ptr = (VOID *) (t);
|
||||
|
||||
|
||||
/* Define the thread timeout pointer setup in _tx_thread_timeout. */
|
||||
|
||||
#define TX_THREAD_TIMEOUT_POINTER_SETUP(t) (t) = (TX_THREAD *) _tx_timer_expired_timer_ptr -> tx_timer_internal_extension_ptr;
|
||||
|
||||
|
||||
/************* Define ThreadX SMP data types and function prototypes. *************/
|
||||
|
||||
struct TX_THREAD_STRUCT;
|
||||
|
||||
|
||||
/* Define the ThreadX SMP protection structure. */
|
||||
|
||||
typedef struct TX_THREAD_SMP_PROTECT_STRUCT
|
||||
{
|
||||
ULONG tx_thread_smp_protect_in_force;
|
||||
ULONG tx_thread_smp_protect_core;
|
||||
ULONG tx_thread_smp_protect_count;
|
||||
ULONG tx_thread_smp_protect_pad_0;
|
||||
ULONG tx_thread_smp_protect_pad_1;
|
||||
ULONG tx_thread_smp_protect_pad_2;
|
||||
ULONG tx_thread_smp_protect_pad_3;
|
||||
} TX_THREAD_SMP_PROTECT;
|
||||
|
||||
|
||||
/* Define ThreadX interrupt lockout and restore macros for protection on
|
||||
access of critical kernel information. The restore interrupt macro must
|
||||
restore the interrupt posture of the running thread prior to the value
|
||||
present prior to the disable macro. In most cases, the save area macro
|
||||
is used to define a local function save area for the disable and restore
|
||||
macros. */
|
||||
|
||||
#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save;
|
||||
|
||||
#define TX_DISABLE interrupt_save = _tx_thread_smp_protect();
|
||||
#define TX_RESTORE _tx_thread_smp_unprotect(interrupt_save);
|
||||
|
||||
/************* End ThreadX SMP data type and function prototype definitions. *************/
|
||||
|
||||
|
||||
/* Define the interrupt lockout macros for each ThreadX object. */
|
||||
|
||||
#define TX_BLOCK_POOL_DISABLE TX_DISABLE
|
||||
#define TX_BYTE_POOL_DISABLE TX_DISABLE
|
||||
#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
|
||||
#define TX_MUTEX_DISABLE TX_DISABLE
|
||||
#define TX_QUEUE_DISABLE TX_DISABLE
|
||||
#define TX_SEMAPHORE_DISABLE TX_DISABLE
|
||||
|
||||
|
||||
/* Define FP extension for ARMv8. Each is assumed to be called in the context of the executing thread. */
|
||||
|
||||
#ifndef TX_SOURCE_CODE
|
||||
#define tx_thread_fp_enable _tx_thread_fp_enable
|
||||
#define tx_thread_fp_disable _tx_thread_fp_disable
|
||||
#endif
|
||||
|
||||
VOID tx_thread_fp_enable(VOID);
|
||||
VOID tx_thread_fp_disable(VOID);
|
||||
|
||||
|
||||
/* Define the version ID of ThreadX. This may be utilized by the application. */
|
||||
|
||||
#ifdef TX_THREAD_INIT
|
||||
CHAR _tx_version_id[] =
|
||||
"Copyright (c) Microsoft Corporation. All rights reserved. * ThreadX ARMv8-A-SMP Version 6.1.10 *";
|
||||
#else
|
||||
extern CHAR _tx_version_id[];
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,327 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_restore ARMv8-A-SMP */
|
||||
/* 6.x */
|
||||
/* 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 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 04-25-2022 William E. Lamie Modified comments, removed */
|
||||
/* FIFO queueing, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_context_restore(VOID)
|
||||
// {
|
||||
.global _tx_thread_context_restore
|
||||
.type _tx_thread_context_restore, @function
|
||||
_tx_thread_context_restore:
|
||||
|
||||
/* Lockout interrupts. */
|
||||
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
|
||||
#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
|
||||
|
||||
/* Pickup the CPU ID. */
|
||||
|
||||
MRS x8, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x2, x8, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x8, x8, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x2, x8, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x8, x8, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x8, x8, x2, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
|
||||
/* Determine if interrupts are nested. */
|
||||
// if (--_tx_thread_system_state)
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_thread_system_state // Pickup address of system state var
|
||||
LDR w2, [x3, x8, LSL #2] // Pickup system state
|
||||
SUB w2, w2, #1 // Decrement the counter
|
||||
STR w2, [x3, x8, LSL #2] // Store the counter
|
||||
CMP w2, #0 // Was this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_restore // If so, not a nested restore
|
||||
|
||||
/* Interrupts are nested. */
|
||||
|
||||
/* Just recover the saved registers and return to the point of
|
||||
interrupt. */
|
||||
|
||||
LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL
|
||||
#ifdef EL1
|
||||
MSR SPSR_EL1, x4 // Setup SPSR for return
|
||||
MSR ELR_EL1, x5 // Setup point of interrupt
|
||||
#else
|
||||
#ifdef EL2
|
||||
MSR SPSR_EL2, x4 // Setup SPSR for return
|
||||
MSR ELR_EL2, x5 // Setup point of interrupt
|
||||
#else
|
||||
MSR SPSR_EL3, x4 // Setup SPSR for return
|
||||
MSR ELR_EL3, x5 // Setup point of interrupt
|
||||
#endif
|
||||
#endif
|
||||
LDP x18, x19, [sp], #16 // Recover x18, x19
|
||||
LDP x16, x17, [sp], #16 // Recover x16, x17
|
||||
LDP x14, x15, [sp], #16 // Recover x14, x15
|
||||
LDP x12, x13, [sp], #16 // Recover x12, x13
|
||||
LDP x10, x11, [sp], #16 // Recover x10, x11
|
||||
LDP x8, x9, [sp], #16 // Recover x8, x9
|
||||
LDP x6, x7, [sp], #16 // Recover x6, x7
|
||||
LDP x4, x5, [sp], #16 // Recover x4, x5
|
||||
LDP x2, x3, [sp], #16 // Recover x2, x3
|
||||
LDP x0, x1, [sp], #16 // Recover x0, x1
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
ERET // 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 x1, =_tx_thread_current_ptr // Pickup address of current thread ptr
|
||||
LDR x0, [x1, x8, LSL #3] // Pickup actual current thread pointer
|
||||
CMP x0, #0 // Is it NULL?
|
||||
BEQ __tx_thread_idle_system_restore // Yes, idle system was interrupted
|
||||
LDR x3, =_tx_thread_execute_ptr // Pickup address of execute thread ptr
|
||||
LDR x2, [x3, x8, LSL #3] // Pickup actual execute thread pointer
|
||||
CMP x0, x2 // Is the same thread highest priority?
|
||||
BEQ __tx_thread_no_preempt_restore // Same thread in the execute list,
|
||||
// no preemption needs to happen
|
||||
LDR x3, =_tx_thread_smp_protection // Build address to protection structure
|
||||
LDR w3, [x3, #4] // Pickup the owning core
|
||||
CMP w3, w8 // Is it this core?
|
||||
BNE __tx_thread_preempt_restore // No, proceed to preempt thread
|
||||
|
||||
LDR x3, =_tx_thread_preempt_disable // Pickup preempt disable address
|
||||
LDR w2, [x3, #0] // Pickup actual preempt disable flag
|
||||
CMP w2, #0 // Is it set?
|
||||
BEQ __tx_thread_preempt_restore // No, okay to preempt this thread
|
||||
|
||||
__tx_thread_no_preempt_restore:
|
||||
|
||||
/* Restore interrupted thread or ISR. */
|
||||
|
||||
/* Pickup the saved stack pointer. */
|
||||
// sp = _tx_thread_current_ptr -> tx_thread_stack_ptr;
|
||||
|
||||
LDR x4, [x0, #8] // Switch to thread stack pointer
|
||||
MOV sp, x4 //
|
||||
|
||||
/* Recover the saved context and return to the point of interrupt. */
|
||||
|
||||
LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL1
|
||||
#ifdef EL1
|
||||
MSR SPSR_EL1, x4 // Setup SPSR for return
|
||||
MSR ELR_EL1, x5 // Setup point of interrupt
|
||||
#else
|
||||
#ifdef EL2
|
||||
MSR SPSR_EL2, x4 // Setup SPSR for return
|
||||
MSR ELR_EL2, x5 // Setup point of interrupt
|
||||
#else
|
||||
MSR SPSR_EL3, x4 // Setup SPSR for return
|
||||
MSR ELR_EL3, x5 // Setup point of interrupt
|
||||
#endif
|
||||
#endif
|
||||
LDP x18, x19, [sp], #16 // Recover x18, x19
|
||||
LDP x16, x17, [sp], #16 // Recover x16, x17
|
||||
LDP x14, x15, [sp], #16 // Recover x14, x15
|
||||
LDP x12, x13, [sp], #16 // Recover x12, x13
|
||||
LDP x10, x11, [sp], #16 // Recover x10, x11
|
||||
LDP x8, x9, [sp], #16 // Recover x8, x9
|
||||
LDP x6, x7, [sp], #16 // Recover x6, x7
|
||||
LDP x4, x5, [sp], #16 // Recover x4, x5
|
||||
LDP x2, x3, [sp], #16 // Recover x2, x3
|
||||
LDP x0, x1, [sp], #16 // Recover x0, x1
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
ERET // Return to point of interrupt
|
||||
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
__tx_thread_preempt_restore:
|
||||
|
||||
|
||||
LDR x4, [x0, #8] // Switch to thread stack pointer
|
||||
MOV sp, x4 //
|
||||
|
||||
LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL1
|
||||
STP x20, x21, [sp, #-16]! // Save x20, x21
|
||||
STP x22, x23, [sp, #-16]! // Save x22, x23
|
||||
STP x24, x25, [sp, #-16]! // Save x24, x25
|
||||
STP x26, x27, [sp, #-16]! // Save x26, x27
|
||||
STP x28, x29, [sp, #-16]! // Save x28, x29
|
||||
#ifdef ENABLE_ARM_FP
|
||||
LDR w3, [x0, #268] // Pickup FP enable flag
|
||||
CMP w3, #0 // Is FP enabled?
|
||||
BEQ _skip_fp_save // No, skip FP save
|
||||
STP q0, q1, [sp, #-32]! // Save q0, q1
|
||||
STP q2, q3, [sp, #-32]! // Save q2, q3
|
||||
STP q4, q5, [sp, #-32]! // Save q4, q5
|
||||
STP q6, q7, [sp, #-32]! // Save q6, q7
|
||||
STP q8, q9, [sp, #-32]! // Save q8, q9
|
||||
STP q10, q11, [sp, #-32]! // Save q10, q11
|
||||
STP q12, q13, [sp, #-32]! // Save q12, q13
|
||||
STP q14, q15, [sp, #-32]! // Save q14, q15
|
||||
STP q16, q17, [sp, #-32]! // Save q16, q17
|
||||
STP q18, q19, [sp, #-32]! // Save q18, q19
|
||||
STP q20, q21, [sp, #-32]! // Save q20, q21
|
||||
STP q22, q23, [sp, #-32]! // Save q22, q23
|
||||
STP q24, q25, [sp, #-32]! // Save q24, q25
|
||||
STP q26, q27, [sp, #-32]! // Save q26, q27
|
||||
STP q28, q29, [sp, #-32]! // Save q28, q29
|
||||
STP q30, q31, [sp, #-32]! // Save q30, q31
|
||||
MRS x2, FPSR // Pickup FPSR
|
||||
MRS x3, FPCR // Pickup FPCR
|
||||
STP x2, x3, [sp, #-16]! // Save FPSR, FPCR
|
||||
_skip_fp_save:
|
||||
#endif
|
||||
STP x4, x5, [sp, #-16]! // Save x4 (SPSR_EL3), x5 (ELR_E3)
|
||||
|
||||
MOV x3, sp // Move sp into x3
|
||||
STR x3, [x0, #8] // Save stack pointer in thread control
|
||||
// block
|
||||
LDR x3, =_tx_thread_system_stack_ptr // Pickup address of system stack
|
||||
LDR x4, [x3, x8, LSL #3] // Pickup system stack pointer
|
||||
MOV sp, x4 // Setup system stack pointer
|
||||
|
||||
|
||||
/* Save the remaining time-slice and disable it. */
|
||||
// if (_tx_timer_time_slice)
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_timer_time_slice // Pickup time-slice variable address
|
||||
LDR w2, [x3, x8, LSL #2] // Pickup time-slice
|
||||
CMP w2, #0 // Is it active?
|
||||
BEQ __tx_thread_dont_save_ts // No, don't save it
|
||||
|
||||
// _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
// _tx_timer_time_slice = 0;
|
||||
|
||||
STR w2, [x0, #36] // Save thread's time-slice
|
||||
MOV w2, #0 // Clear value
|
||||
STR w2, [x3, x8, LSL #2] // Disable global time-slice flag
|
||||
|
||||
// }
|
||||
__tx_thread_dont_save_ts:
|
||||
|
||||
|
||||
/* Clear the current task pointer. */
|
||||
// _tx_thread_current_ptr = TX_NULL;
|
||||
|
||||
MOV x2, #0 // NULL value
|
||||
STR x2, [x1, x8, LSL #3] // Clear current thread pointer
|
||||
|
||||
/* Set bit indicating this thread is ready for execution. */
|
||||
|
||||
MOV x2, #1 // Build ready flag
|
||||
STR w2, [x0, #260] // Set thread's ready flag
|
||||
DMB ISH // Ensure that accesses to shared resource have completed
|
||||
|
||||
/* Return to the scheduler. */
|
||||
// _tx_thread_schedule();
|
||||
|
||||
// }
|
||||
|
||||
__tx_thread_idle_system_restore:
|
||||
|
||||
/* Just return back to the scheduler! */
|
||||
|
||||
LDR x1, =_tx_thread_schedule // Build address for _tx_thread_schedule
|
||||
#ifdef EL1
|
||||
MSR ELR_EL1, x1 // Setup point of interrupt
|
||||
// MOV x1, #0x4 // Setup EL1 return
|
||||
// MSR spsr_el1, x1 // Move into SPSR
|
||||
#else
|
||||
#ifdef EL2
|
||||
MSR ELR_EL2, x1 // Setup point of interrupt
|
||||
// MOV x1, #0x8 // Setup EL2 return
|
||||
// MSR spsr_el2, x1 // Move into SPSR
|
||||
#else
|
||||
MSR ELR_EL3, x1 // Setup point of interrupt
|
||||
// MOV x1, #0xC // Setup EL3 return
|
||||
// MSR spsr_el3, x1 // Move into SPSR
|
||||
#endif
|
||||
#endif
|
||||
ERET // Return to scheduler
|
||||
// }
|
||||
@@ -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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_context_save ARMv8-A-SMP */
|
||||
/* 6.x */
|
||||
/* 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 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_context_save(VOID)
|
||||
// {
|
||||
.global _tx_thread_context_save
|
||||
.type _tx_thread_context_save, @function
|
||||
_tx_thread_context_save:
|
||||
|
||||
/* Upon entry to this routine, it is assumed that IRQ/FIQ interrupts are locked
|
||||
out, x29 (frame pointer), x30 (link register) are saved, we are in the proper EL,
|
||||
and all other registers are intact. */
|
||||
|
||||
/* Check for a nested interrupt condition. */
|
||||
// if (_tx_thread_system_state++)
|
||||
// {
|
||||
|
||||
STP x0, x1, [sp, #-16]! // Save x0, x1
|
||||
STP x2, x3, [sp, #-16]! // Save x2, x3
|
||||
|
||||
/* Pickup the CPU ID. */
|
||||
|
||||
MRS x1, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x2, x1, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x2, x1, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x1, x1, x2, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
|
||||
LDR x3, =_tx_thread_system_state // Pickup address of system state var
|
||||
LDR w2, [x3, x1, LSL #2] // Pickup system state
|
||||
CMP w2, #0 // Is this the first interrupt?
|
||||
BEQ __tx_thread_not_nested_save // Yes, not a nested context save
|
||||
|
||||
/* Nested interrupt condition. */
|
||||
|
||||
ADD w2, w2, #1 // Increment the nested interrupt counter
|
||||
STR w2, [x3, x1, LSL #2] // Store it back in the variable
|
||||
|
||||
/* Save the rest of the scratch registers on the stack and return to the
|
||||
calling ISR. */
|
||||
|
||||
STP x4, x5, [sp, #-16]! // Save x4, x5
|
||||
STP x6, x7, [sp, #-16]! // Save x6, x7
|
||||
STP x8, x9, [sp, #-16]! // Save x8, x9
|
||||
STP x10, x11, [sp, #-16]! // Save x10, x11
|
||||
STP x12, x13, [sp, #-16]! // Save x12, x13
|
||||
STP x14, x15, [sp, #-16]! // Save x14, x15
|
||||
STP x16, x17, [sp, #-16]! // Save x16, x17
|
||||
STP x18, x19, [sp, #-16]! // Save x18, x19
|
||||
#ifdef EL1
|
||||
MRS x0, SPSR_EL1 // Pickup SPSR
|
||||
MRS x1, ELR_EL1 // Pickup ELR (point of interrupt)
|
||||
#else
|
||||
#ifdef EL2
|
||||
MRS x0, SPSR_EL2 // Pickup SPSR
|
||||
MRS x1, ELR_EL2 // Pickup ELR (point of interrupt)
|
||||
#else
|
||||
MRS x0, SPSR_EL3 // Pickup SPSR
|
||||
MRS x1, ELR_EL3 // Pickup ELR (point of interrupt)
|
||||
#endif
|
||||
#endif
|
||||
STP x0, x1, [sp, #-16]! // Save SPSR, ELR
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
STP x29, x30, [sp, #-16]! // Save x29, x30
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
#endif
|
||||
|
||||
/* Return to the ISR. */
|
||||
|
||||
RET // Return to ISR
|
||||
|
||||
__tx_thread_not_nested_save:
|
||||
// }
|
||||
|
||||
/* Otherwise, not nested, check to see if a thread was running. */
|
||||
// else if (_tx_thread_current_ptr)
|
||||
// {
|
||||
|
||||
ADD w2, w2, #1 // Increment the interrupt counter
|
||||
STR w2, [x3, x1, LSL #2] // Store it back in the variable
|
||||
LDR x2, =_tx_thread_current_ptr // Pickup address of current thread ptr
|
||||
LDR x0, [x2, x1, LSL #3] // Pickup current thread pointer
|
||||
CMP x0, #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. */
|
||||
|
||||
STP x4, x5, [sp, #-16]! // Save x4, x5
|
||||
STP x6, x7, [sp, #-16]! // Save x6, x7
|
||||
STP x8, x9, [sp, #-16]! // Save x8, x9
|
||||
STP x10, x11, [sp, #-16]! // Save x10, x11
|
||||
STP x12, x13, [sp, #-16]! // Save x12, x13
|
||||
STP x14, x15, [sp, #-16]! // Save x14, x15
|
||||
STP x16, x17, [sp, #-16]! // Save x16, x17
|
||||
STP x18, x19, [sp, #-16]! // Save x18, x19
|
||||
#ifdef EL1
|
||||
MRS x4, SPSR_EL1 // Pickup SPSR
|
||||
MRS x5, ELR_EL1 // Pickup ELR (point of interrupt)
|
||||
#else
|
||||
#ifdef EL2
|
||||
MRS x4, SPSR_EL2 // Pickup SPSR
|
||||
MRS x5, ELR_EL2 // Pickup ELR (point of interrupt)
|
||||
#else
|
||||
MRS x4, SPSR_EL3 // Pickup SPSR
|
||||
MRS x5, ELR_EL3 // Pickup ELR (point of interrupt)
|
||||
#endif
|
||||
#endif
|
||||
STP x4, x5, [sp, #-16]! // Save SPSR, ELR
|
||||
|
||||
/* Save the current stack pointer in the thread's control block. */
|
||||
// _tx_thread_current_ptr -> tx_thread_stack_ptr = sp;
|
||||
|
||||
MOV x4, sp //
|
||||
STR x4, [x0, #8] // Save thread stack pointer
|
||||
|
||||
/* Switch to the system stack. */
|
||||
// sp = _tx_thread_system_stack_ptr;
|
||||
|
||||
LDR x3, =_tx_thread_system_stack_ptr // Pickup address of system stack
|
||||
MRS x1, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x2, x1, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x2, x1, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x1, x1, x2, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
|
||||
LDR x4, [x3, x1, LSL #3] // Pickup system stack pointer
|
||||
MOV sp, x4 // Setup system stack pointer
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
STP x29, x30, [sp, #-16]! // Save x29, x30
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
#endif
|
||||
|
||||
RET // 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. */
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
|
||||
STP x29, x30, [sp, #-16]! // Save x29, x30
|
||||
BL _tx_execution_isr_enter // Call the ISR enter function
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
#endif
|
||||
|
||||
ADD sp, sp, #48 // Recover saved registers
|
||||
RET // Continue IRQ processing
|
||||
|
||||
// }
|
||||
// }
|
||||
310
ports_arch/ARMv8-A/threadx_smp/common/src/tx_thread_schedule.S
Normal file
310
ports_arch/ARMv8-A/threadx_smp/common/src/tx_thread_schedule.S
Normal file
@@ -0,0 +1,310 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule ARMv8-A-SMP */
|
||||
/* 6.x */
|
||||
/* 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 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* added memory barrier, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_schedule(VOID)
|
||||
// {
|
||||
.global _tx_thread_schedule
|
||||
.type _tx_thread_schedule, @function
|
||||
_tx_thread_schedule:
|
||||
|
||||
/* Enable interrupts. */
|
||||
|
||||
MSR DAIFClr, 0x3 // Enable interrupts
|
||||
|
||||
/* Pickup the CPU ID. */
|
||||
|
||||
MRS x20, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x1, x20, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x20, x20, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x1, x20, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x20, x20, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x20, x20, x1, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
|
||||
/* Wait for a thread to execute. */
|
||||
// do
|
||||
// {
|
||||
|
||||
LDR x1, =_tx_thread_execute_ptr // Address of thread execute ptr
|
||||
|
||||
#ifdef TX_ENABLE_WFI
|
||||
__tx_thread_schedule_loop:
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
LDR x0, [x1, x20, LSL #3] // Pickup next thread to execute
|
||||
CMP x0, #0 // Is it NULL?
|
||||
BNE _tx_thread_schedule_thread //
|
||||
MSR DAIFClr, 0x3 // Enable interrupts
|
||||
WFI //
|
||||
B __tx_thread_schedule_loop // Keep looking for a thread
|
||||
_tx_thread_schedule_thread:
|
||||
#else
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
LDR x0, [x1, x20, LSL #3] // Pickup next thread to execute
|
||||
CMP x0, #0 // Is it NULL?
|
||||
BEQ _tx_thread_schedule // Keep looking for a thread
|
||||
#endif
|
||||
|
||||
// }
|
||||
// while(_tx_thread_execute_ptr == TX_NULL);
|
||||
|
||||
/* Get the lock for accessing the thread's ready bit. */
|
||||
|
||||
MOV w2, #280 // Build offset to the lock
|
||||
ADD x2, x0, x2 // Get the address to the lock
|
||||
LDAXR w3, [x2] // Pickup the lock value
|
||||
CMP w3, #0 // Check if it's available
|
||||
BNE _tx_thread_schedule // No, lock not available
|
||||
MOV w3, #1 // Build the lock set value
|
||||
STXR w4, w3, [x2] // Try to get the lock
|
||||
CMP w4, #0 // Check if we got the lock
|
||||
BNE _tx_thread_schedule // No, another core got it first
|
||||
DMB ISH // Ensure write to lock completes
|
||||
|
||||
/* Now make sure the thread's ready bit is set. */
|
||||
|
||||
LDR w3, [x0, #260] // Pickup the thread ready bit
|
||||
CMP w3, #0 // Is it set?
|
||||
BNE _tx_thread_ready_for_execution // Yes, schedule the thread
|
||||
|
||||
/* The ready bit isn't set. Release the lock and jump back to the scheduler. */
|
||||
|
||||
MOV w3, #0 // Build clear value
|
||||
STR w3, [x2] // Release the lock
|
||||
DMB ISH // Ensure write to lock completes
|
||||
B _tx_thread_schedule // Jump back to the scheduler
|
||||
|
||||
_tx_thread_ready_for_execution:
|
||||
|
||||
/* We have a thread to execute. */
|
||||
|
||||
/* Clear the ready bit and release the lock. */
|
||||
|
||||
MOV w3, #0 // Build clear value
|
||||
STR w3, [x0, #260] // Store it back in the thread control block
|
||||
DMB ISH
|
||||
MOV w3, #0 // Build clear value for the lock
|
||||
STR w3, [x2] // Release the lock
|
||||
DMB ISH
|
||||
|
||||
/* Setup the current thread pointer. */
|
||||
// _tx_thread_current_ptr = _tx_thread_execute_ptr;
|
||||
|
||||
LDR x2, =_tx_thread_current_ptr // Pickup address of current thread
|
||||
STR x0, [x2, x20, LSL #3] // Setup current thread pointer
|
||||
DMB ISH
|
||||
LDR x1, [x1, x20, LSL #3] // Reload the execute pointer
|
||||
CMP w0, w1 // Did it change?
|
||||
BEQ _execute_pointer_did_not_change // If not, skip handling
|
||||
|
||||
/* In the time between reading the execute pointer and assigning
|
||||
it to the current pointer, the execute pointer was changed by
|
||||
some external code. If the current pointer was still null when
|
||||
the external code checked if a core preempt was necessary, then
|
||||
it wouldn't have done it and a preemption will be missed. To
|
||||
handle this, undo some things and jump back to the scheduler so
|
||||
it can schedule the new thread. */
|
||||
|
||||
MOV w1, #0 // Build clear value
|
||||
STR x1, [x2, x20, LSL #3] // Clear current thread pointer
|
||||
|
||||
MOV w1, #1 // Build set value
|
||||
STR w1, [x0, #260] // Re-set the ready bit
|
||||
DMB ISH //
|
||||
|
||||
B _tx_thread_schedule // Jump back to the scheduler to schedule the new thread
|
||||
|
||||
_execute_pointer_did_not_change:
|
||||
/* Increment the run count for this thread. */
|
||||
// _tx_thread_current_ptr -> tx_thread_run_count++;
|
||||
|
||||
LDR w2, [x0, #4] // Pickup run counter
|
||||
LDR w3, [x0, #36] // Pickup time-slice for this thread
|
||||
ADD w2, w2, #1 // Increment thread run-counter
|
||||
STR w2, [x0, #4] // Store the new run counter
|
||||
|
||||
/* Setup time-slice, if present. */
|
||||
// _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice;
|
||||
|
||||
LDR x2, =_tx_timer_time_slice // Pickup address of time slice
|
||||
// variable
|
||||
LDR x4, [x0, #8] // Switch stack pointers
|
||||
MOV sp, x4 //
|
||||
STR w3, [x2, x20, LSL #2] // 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 x19, x0 // Save x0
|
||||
BL _tx_execution_thread_enter // Call the thread execution enter function
|
||||
MOV x0, x19 // Restore x0
|
||||
#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. */
|
||||
|
||||
LDP x4, x5, [sp], #16 // Pickup saved SPSR/DAIF and ELR_EL1
|
||||
CMP x5, #0 // Check for synchronous context switch (ELR_EL1 = NULL)
|
||||
BEQ _tx_solicited_return
|
||||
#ifdef EL1
|
||||
MSR SPSR_EL1, x4 // Setup SPSR for return
|
||||
MSR ELR_EL1, x5 // Setup point of interrupt
|
||||
#else
|
||||
#ifdef EL2
|
||||
MSR SPSR_EL2, x4 // Setup SPSR for return
|
||||
MSR ELR_EL2, x5 // Setup point of interrupt
|
||||
#else
|
||||
MSR SPSR_EL3, x4 // Setup SPSR for return
|
||||
MSR ELR_EL3, x5 // Setup point of interrupt
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ENABLE_ARM_FP
|
||||
LDR w1, [x0, #268] // Pickup FP enable flag
|
||||
CMP w1, #0 // Is FP enabled?
|
||||
BEQ _skip_interrupt_fp_restore // No, skip FP restore
|
||||
LDP x0, x1, [sp], #16 // Pickup FPSR, FPCR
|
||||
MSR FPSR, x0 // Recover FPSR
|
||||
MSR FPCR, x1 // Recover FPCR
|
||||
LDP q30, q31, [sp], #32 // Recover q30, q31
|
||||
LDP q28, q29, [sp], #32 // Recover q28, q29
|
||||
LDP q26, q27, [sp], #32 // Recover q26, q27
|
||||
LDP q24, q25, [sp], #32 // Recover q24, q25
|
||||
LDP q22, q23, [sp], #32 // Recover q22, q23
|
||||
LDP q20, q21, [sp], #32 // Recover q20, q21
|
||||
LDP q18, q19, [sp], #32 // Recover q18, q19
|
||||
LDP q16, q17, [sp], #32 // Recover q16, q17
|
||||
LDP q14, q15, [sp], #32 // Recover q14, q15
|
||||
LDP q12, q13, [sp], #32 // Recover q12, q13
|
||||
LDP q10, q11, [sp], #32 // Recover q10, q11
|
||||
LDP q8, q9, [sp], #32 // Recover q8, q9
|
||||
LDP q6, q7, [sp], #32 // Recover q6, q7
|
||||
LDP q4, q5, [sp], #32 // Recover q4, q5
|
||||
LDP q2, q3, [sp], #32 // Recover q2, q3
|
||||
LDP q0, q1, [sp], #32 // Recover q0, q1
|
||||
_skip_interrupt_fp_restore:
|
||||
#endif
|
||||
LDP x28, x29, [sp], #16 // Recover x28
|
||||
LDP x26, x27, [sp], #16 // Recover x26, x27
|
||||
LDP x24, x25, [sp], #16 // Recover x24, x25
|
||||
LDP x22, x23, [sp], #16 // Recover x22, x23
|
||||
LDP x20, x21, [sp], #16 // Recover x20, x21
|
||||
LDP x18, x19, [sp], #16 // Recover x18, x19
|
||||
LDP x16, x17, [sp], #16 // Recover x16, x17
|
||||
LDP x14, x15, [sp], #16 // Recover x14, x15
|
||||
LDP x12, x13, [sp], #16 // Recover x12, x13
|
||||
LDP x10, x11, [sp], #16 // Recover x10, x11
|
||||
LDP x8, x9, [sp], #16 // Recover x8, x9
|
||||
LDP x6, x7, [sp], #16 // Recover x6, x7
|
||||
LDP x4, x5, [sp], #16 // Recover x4, x5
|
||||
LDP x2, x3, [sp], #16 // Recover x2, x3
|
||||
LDP x0, x1, [sp], #16 // Recover x0, x1
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
ERET // Return to point of interrupt
|
||||
|
||||
_tx_solicited_return:
|
||||
|
||||
#ifdef ENABLE_ARM_FP
|
||||
LDR w1, [x0, #268] // Pickup FP enable flag
|
||||
CMP w1, #0 // Is FP enabled?
|
||||
BEQ _skip_solicited_fp_restore // No, skip FP restore
|
||||
LDP x0, x1, [sp], #16 // Pickup FPSR, FPCR
|
||||
MSR FPSR, x0 // Recover FPSR
|
||||
MSR FPCR, x1 // Recover FPCR
|
||||
LDP q14, q15, [sp], #32 // Recover q14, q15
|
||||
LDP q12, q13, [sp], #32 // Recover q12, q13
|
||||
LDP q10, q11, [sp], #32 // Recover q10, q11
|
||||
LDP q8, q9, [sp], #32 // Recover q8, q9
|
||||
_skip_solicited_fp_restore:
|
||||
#endif
|
||||
LDP x27, x28, [sp], #16 // Recover x27, x28
|
||||
LDP x25, x26, [sp], #16 // Recover x25, x26
|
||||
LDP x23, x24, [sp], #16 // Recover x23, x24
|
||||
LDP x21, x22, [sp], #16 // Recover x21, x22
|
||||
LDP x19, x20, [sp], #16 // Recover x19, x20
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
MSR DAIF, x4 // Recover DAIF
|
||||
RET // Return to caller
|
||||
// }
|
||||
@@ -0,0 +1,90 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread - Low Level SMP Support */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_smp_core_get Cortex-A35-SMP/AC6 */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function gets the currently running core number and returns it.*/
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* Core ID */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ThreadX Source */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.global _tx_thread_smp_core_get
|
||||
.type _tx_thread_smp_core_get, @function
|
||||
_tx_thread_smp_core_get:
|
||||
MRS x0, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x1, x0, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x0, x0, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x1, x0, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x0, x0, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x0, x0, x1, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
RET
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread - Low Level SMP Support */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
#define ICC_SGI1R_EL1 S3_0_C12_C11_5
|
||||
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_smp_core_preempt Cortex-A35-SMP */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function preempts the specified core in situations where the */
|
||||
/* thread corresponding to this core is no longer ready or when the */
|
||||
/* core must be used for a higher-priority thread. If the specified is */
|
||||
/* the current core, this processing is skipped since the will give up */
|
||||
/* control subsequently on its own. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* core The core to preempt */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ThreadX Source */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.global _tx_thread_smp_core_preempt
|
||||
.type _tx_thread_smp_core_preempt, @function
|
||||
_tx_thread_smp_core_preempt:
|
||||
DSB ISH
|
||||
#ifdef TX_ARMV8_2
|
||||
MOV x2, #0x1 // Build the target list field
|
||||
LSL x3, x0, #16 // Build the affinity1 field
|
||||
ORR x2, x2, x3 // Combine the fields
|
||||
#else
|
||||
MOV x2, #0x1 //
|
||||
LSL x2, x2, x0 // Shift by the core ID
|
||||
#endif
|
||||
MSR ICC_SGI1R_EL1, x2 // Issue inter-core interrupt
|
||||
RET
|
||||
@@ -0,0 +1,95 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 - Low Level SMP Support */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_smp_current_state_get Cortex-A35-SMP/AC6 */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is gets the current state of the calling core. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ThreadX Components */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.global _tx_thread_smp_current_state_get
|
||||
.type _tx_thread_smp_current_state_get, @function
|
||||
_tx_thread_smp_current_state_get:
|
||||
|
||||
MRS x1, DAIF // Pickup current interrupt posture
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
MRS x2, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x3, x2, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x2, x2, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x3, x2, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x2, x2, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x2, x2, x3, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
LDR x3, =_tx_thread_system_state // Pickup the base of the current system state array
|
||||
LDR w0, [x3, x2, LSL #2] // Pickup the current system state for this core
|
||||
MSR DAIF, x1 // Restore interrupt posture
|
||||
RET
|
||||
@@ -0,0 +1,95 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 - Low Level SMP Support */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_smp_current_thread_get Cortex-A35-SMP/AC6 */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is gets the current thread of the calling core. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ThreadX Components */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.global _tx_thread_smp_current_thread_get
|
||||
.type _tx_thread_smp_current_thread_get, @function
|
||||
_tx_thread_smp_current_thread_get:
|
||||
|
||||
MRS x1, DAIF // Pickup current interrupt posture
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
MRS x2, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x3, x2, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x2, x2, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x3, x2, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x2, x2, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x2, x2, x3, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
LDR x3, =_tx_thread_current_ptr // Pickup the base of the current thread pointer array
|
||||
LDR x0, [x3, x2, LSL #3] // Pickup the current thread pointer for this core
|
||||
MSR DAIF, x1 // Restore interrupt posture
|
||||
RET
|
||||
@@ -0,0 +1,144 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 - Low Level SMP Support */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_smp_initialize_wait Cortex-A35-SMP/AC6 */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function is the place where additional cores wait until */
|
||||
/* initialization is complete before they enter the thread scheduling */
|
||||
/* loop. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_thread_schedule Thread scheduling loop */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* Hardware */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.global _tx_thread_smp_initialize_wait
|
||||
.type _tx_thread_smp_initialize_wait, @function
|
||||
_tx_thread_smp_initialize_wait:
|
||||
|
||||
/* Lockout interrupts. */
|
||||
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
|
||||
/* Pickup the Core ID. */
|
||||
|
||||
MRS x2, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x3, x2, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x2, x2, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x3, x2, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x2, x2, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x2, x2, x3, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
|
||||
/* Make sure the system state for this core is TX_INITIALIZE_IN_PROGRESS before we check the release
|
||||
flag. */
|
||||
|
||||
LDR w1, =0xF0F0F0F0 // Build TX_INITIALIZE_IN_PROGRESS flag
|
||||
LDR x3, =_tx_thread_system_state // Pickup the base of the current system state array
|
||||
wait_for_initialize:
|
||||
LDR w0, [x3, x2, LSL #2] // Pickup the current system state for this core
|
||||
CMP w0, w1 // Make sure the TX_INITIALIZE_IN_PROGRESS flag is set
|
||||
BNE wait_for_initialize // Not equal, just spin here
|
||||
|
||||
/* Save the system stack pointer for this core. */
|
||||
|
||||
LDR x0, =_tx_thread_system_stack_ptr // Pickup address of system stack ptr
|
||||
MOV x1, sp // Pickup SP
|
||||
SUB x1, x1, #15 //
|
||||
BIC x1, x1, #0xF // Get 16-bit alignment
|
||||
STR x1, [x0, x2, LSL #3] // Store system stack pointer
|
||||
|
||||
|
||||
/* Pickup the release cores flag. */
|
||||
|
||||
LDR x4, =_tx_thread_smp_release_cores_flag // Build address of release cores flag
|
||||
wait_for_release:
|
||||
LDR w0, [x4, #0] // Pickup the flag
|
||||
CMP w0, #0 // Is it set?
|
||||
BEQ wait_for_release // Wait for the flag to be set
|
||||
|
||||
/* Core 0 has released this core. */
|
||||
|
||||
/* Clear this core's system state variable. */
|
||||
|
||||
MOV x0, #0 // Build clear value
|
||||
STR w0, [x3, x2, LSL #2] // Set the current system state for this core to zero
|
||||
|
||||
/* Now wait for core 0 to finish it's initialization. */
|
||||
|
||||
core_0_wait_loop:
|
||||
LDR w0, [x3, #0] // Pickup the current system state for core 0
|
||||
CMP w0, #0 // Is it 0?
|
||||
BNE core_0_wait_loop // No, keep waiting for core 0 to finish its initialization
|
||||
|
||||
/* Initialization is complete, enter the scheduling loop! */
|
||||
|
||||
B _tx_thread_schedule // Enter the scheduling loop for this core
|
||||
|
||||
RET
|
||||
@@ -0,0 +1,75 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread - Low Level SMP Support */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_smp_low_level_initialize Cortex-A35-SMP/AC6 */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function performs low-level initialization of the booting */
|
||||
/* core. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* number_of_cores Number of cores */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_high_level ThreadX high-level init */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.global _tx_thread_smp_low_level_initialize
|
||||
.type _tx_thread_smp_low_level_initialize, @function
|
||||
_tx_thread_smp_low_level_initialize:
|
||||
|
||||
RET
|
||||
@@ -0,0 +1,137 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 - Low Level SMP Support */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
/* Include macros for modifying the wait list. */
|
||||
#include "tx_thread_smp_protection_wait_list_macros.h"
|
||||
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_smp_protect Cortex-A35-SMP/AC6 */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function gets protection for running inside the ThreadX */
|
||||
/* source. This is acomplished by a combination of a test-and-set */
|
||||
/* flag and periodically disabling interrupts. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* Previous Status Register */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ThreadX Source */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* improved SMP code, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 04-25-2022 William E. Lamie Modified comments, removed */
|
||||
/* FIFO queueing, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.global _tx_thread_smp_protect
|
||||
.type _tx_thread_smp_protect, @function
|
||||
_tx_thread_smp_protect:
|
||||
|
||||
/* Disable interrupts so we don't get preempted. */
|
||||
|
||||
MRS x0, DAIF // Pickup current interrupt posture
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
|
||||
/* Pickup the CPU ID. */
|
||||
|
||||
MRS x2, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x7, x2, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x2, x2, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x7, x2, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x2, x2, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x2, x2, x7, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
|
||||
LDR x1, =_tx_thread_smp_protection // Build address to protection structure
|
||||
LDR w3, [x1, #4] // Pickup the owning core
|
||||
CMP w3, w2 // Is it this core?
|
||||
BEQ _owned // Yes, the protection is already owned
|
||||
|
||||
LDAXR w4, [x1, #0] // Pickup the protection flag
|
||||
CBZ w4, _get_protection // Yes, get the protection
|
||||
MSR DAIF, x0 // Restore interrupts
|
||||
ISB //
|
||||
#ifdef TX_ENABLE_WFE
|
||||
WFE // Go into standby
|
||||
#endif
|
||||
B _tx_thread_smp_protect // On waking, restart the protection attempt
|
||||
|
||||
_get_protection:
|
||||
MOV x4, #1 // Build lock value
|
||||
STXR w5, w4, [x1] // Attempt to get the protection
|
||||
CBZ w5, _got_protection // Did it succeed? w5 = 0 means success!
|
||||
MSR DAIF, x0 // Restore interrupts
|
||||
B _tx_thread_smp_protect // Restart the protection attempt
|
||||
|
||||
_got_protection:
|
||||
DMB ISH //
|
||||
STR w2, [x1, #4] // Save owning core
|
||||
_owned:
|
||||
LDR w5, [x1, #8] // Pickup ownership count
|
||||
ADD w5, w5, #1 // Increment ownership count
|
||||
STR w5, [x1, #8] // Store ownership count
|
||||
DMB ISH //
|
||||
RET
|
||||
@@ -0,0 +1,302 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 - Low Level SMP Support */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
.macro _tx_thread_smp_protect_lock_got
|
||||
|
||||
/* Set the currently owned core. */
|
||||
// _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core;
|
||||
|
||||
STR w1, [x2, #4] // Store this core
|
||||
|
||||
/* Increment the protection count. */
|
||||
// _tx_thread_smp_protection.tx_thread_smp_protect_count++;
|
||||
|
||||
LDR w3, [x2, #8] // Pickup ownership count
|
||||
ADD w3, w3, #1 // Increment ownership count
|
||||
STR w3, [x2, #8] // Store ownership count
|
||||
DMB ISH
|
||||
|
||||
.endm
|
||||
|
||||
.macro _tx_thread_smp_protect_remove_from_front_of_list
|
||||
|
||||
/* Remove ourselves from the list. */
|
||||
// _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head++] = 0xFFFFFFFF;
|
||||
|
||||
MOV w3, #0xFFFFFFFF // Build the invalid core value
|
||||
LDR x4, =_tx_thread_smp_protect_wait_list_head // Get the address of the head
|
||||
LDR w5, [x4] // Get the value of the head
|
||||
LDR x6, =_tx_thread_smp_protect_wait_list // Get the address of the list
|
||||
STR w3, [x6, x5, LSL #2] // Store the invalid core value
|
||||
ADD w5, w5, #1 // Increment the head
|
||||
|
||||
/* Did we wrap? */
|
||||
// if (_tx_thread_smp_protect_wait_list_head == TX_THREAD_SMP_MAX_CORES + 1)
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_list_size // Load address of core list size
|
||||
LDR w3, [x3] // Load the max cores value
|
||||
CMP w5, w3 // Compare the head to it
|
||||
BNE _store_new_head\@ // Are we at the max?
|
||||
|
||||
// _tx_thread_smp_protect_wait_list_head = 0;
|
||||
|
||||
EOR w5, w5, w5 // We're at the max. Set it to zero
|
||||
|
||||
// }
|
||||
|
||||
_store_new_head\@:
|
||||
|
||||
STR w5, [x4] // Store the new head
|
||||
|
||||
/* We have the lock! */
|
||||
DMB ISH // Ensure write to protection finishes
|
||||
|
||||
// return;
|
||||
|
||||
.endm
|
||||
|
||||
|
||||
.macro _tx_thread_smp_protect_wait_list_lock_get
|
||||
// VOID _tx_thread_smp_protect_wait_list_lock_get()
|
||||
// {
|
||||
/* We do this until we have the lock. */
|
||||
// while (1)
|
||||
// {
|
||||
|
||||
_tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@:
|
||||
|
||||
// Is the list lock available? */
|
||||
// _tx_thread_smp_protect_wait_list_lock_protect_in_force = load_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force);
|
||||
|
||||
LDR x1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force
|
||||
LDAXR w2, [x1] // Pickup the protection flag
|
||||
|
||||
// if (protect_in_force == 0)
|
||||
// {
|
||||
|
||||
CMP w2, #0
|
||||
BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ // No, protection not available
|
||||
|
||||
/* Try to get the list. */
|
||||
// int status = store_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force, 1);
|
||||
|
||||
MOV w2, #1 // Build lock value
|
||||
STXR w3, w2, [x1] // Attempt to get the protection
|
||||
|
||||
/* if (status == SUCCESS) */
|
||||
|
||||
CMP w3, #0
|
||||
BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ // Did it fail? If so, try again.
|
||||
|
||||
/* We have the lock! */
|
||||
// return;
|
||||
|
||||
.endm
|
||||
|
||||
|
||||
.macro _tx_thread_smp_protect_wait_list_add
|
||||
// VOID _tx_thread_smp_protect_wait_list_add(UINT new_core)
|
||||
// {
|
||||
|
||||
/* We're about to modify the list, so get the list lock. */
|
||||
// _tx_thread_smp_protect_wait_list_lock_get();
|
||||
|
||||
STP x1, x2, [sp, #-16]! // Save registers we'll be using
|
||||
|
||||
_tx_thread_smp_protect_wait_list_lock_get
|
||||
|
||||
LDP x1, x2, [sp], #16
|
||||
|
||||
/* Add this core. */
|
||||
// _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_tail++] = new_core;
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_list_tail // Get the address of the tail
|
||||
LDR w4, [x3] // Get the value of tail
|
||||
LDR x5, =_tx_thread_smp_protect_wait_list // Get the address of the list
|
||||
STR w1, [x5, x4, LSL #2] // Store the new core value
|
||||
ADD w4, w4, #1 // Increment the tail
|
||||
|
||||
/* Did we wrap? */
|
||||
// if (_tx_thread_smp_protect_wait_list_tail == _tx_thread_smp_protect_wait_list_size)
|
||||
// {
|
||||
|
||||
LDR x5, =_tx_thread_smp_protect_wait_list_size // Load max cores address
|
||||
LDR w5, [x5] // Load max cores value
|
||||
CMP w4, w5 // Compare max cores to tail
|
||||
BNE _tx_thread_smp_protect_wait_list_add__no_wrap\@ // Did we wrap?
|
||||
|
||||
// _tx_thread_smp_protect_wait_list_tail = 0;
|
||||
|
||||
MOV w4, #0
|
||||
|
||||
// }
|
||||
|
||||
_tx_thread_smp_protect_wait_list_add__no_wrap\@:
|
||||
|
||||
STR w4, [x3] // Store the new tail value.
|
||||
DMB ISH // Ensure that accesses to shared resource have completed
|
||||
|
||||
/* Release the list lock. */
|
||||
// _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0;
|
||||
|
||||
MOV w3, #0 // Build lock value
|
||||
LDR x4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force
|
||||
STR w3, [x4] // Store the new value
|
||||
DMB ISH // Ensure write to protection finishes
|
||||
|
||||
.endm
|
||||
|
||||
|
||||
.macro _tx_thread_smp_protect_wait_list_remove
|
||||
// VOID _tx_thread_smp_protect_wait_list_remove(UINT core)
|
||||
// {
|
||||
|
||||
/* Get the core index. */
|
||||
// UINT core_index;
|
||||
// for (core_index = 0;; core_index++)
|
||||
|
||||
EOR w4, w4, w4 // Clear for 'core_index'
|
||||
LDR x2, =_tx_thread_smp_protect_wait_list // Get the address of the list
|
||||
|
||||
// {
|
||||
|
||||
_tx_thread_smp_protect_wait_list_remove__check_cur_core\@:
|
||||
|
||||
/* Is this the core? */
|
||||
// if (_tx_thread_smp_protect_wait_list[core_index] == core)
|
||||
// {
|
||||
// break;
|
||||
|
||||
LDR w3, [x2, x4, LSL #2] // Get the value at the current index
|
||||
CMP w3, w8 // Did we find the core?
|
||||
BEQ _tx_thread_smp_protect_wait_list_remove__found_core\@
|
||||
|
||||
// }
|
||||
|
||||
ADD w4, w4, #1 // Increment cur index
|
||||
B _tx_thread_smp_protect_wait_list_remove__check_cur_core\@ // Restart the loop
|
||||
|
||||
// }
|
||||
|
||||
_tx_thread_smp_protect_wait_list_remove__found_core\@:
|
||||
|
||||
/* We're about to modify the list. Get the lock. We need the lock because another
|
||||
core could be simultaneously adding (a core is simultaneously trying to get
|
||||
the inter-core lock) or removing (a core is simultaneously being preempted,
|
||||
like what is currently happening). */
|
||||
// _tx_thread_smp_protect_wait_list_lock_get();
|
||||
|
||||
MOV x6, x1
|
||||
_tx_thread_smp_protect_wait_list_lock_get
|
||||
MOV x1, x6
|
||||
|
||||
/* We remove by shifting. */
|
||||
// while (core_index != _tx_thread_smp_protect_wait_list_tail)
|
||||
// {
|
||||
|
||||
_tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@:
|
||||
|
||||
LDR x2, =_tx_thread_smp_protect_wait_list_tail // Load tail address
|
||||
LDR w2, [x2] // Load tail value
|
||||
CMP w4, w2 // Compare cur index and tail
|
||||
BEQ _tx_thread_smp_protect_wait_list_remove__removed\@
|
||||
|
||||
// UINT next_index = core_index + 1;
|
||||
|
||||
MOV w2, w4 // Move current index to next index register
|
||||
ADD w2, w2, #1 // Add 1
|
||||
|
||||
// if (next_index == _tx_thread_smp_protect_wait_list_size)
|
||||
// {
|
||||
|
||||
LDR x3, =_tx_thread_smp_protect_wait_list_size
|
||||
LDR w3, [x3]
|
||||
CMP w2, w3
|
||||
BNE _tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@
|
||||
|
||||
// next_index = 0;
|
||||
|
||||
MOV w2, #0
|
||||
|
||||
// }
|
||||
|
||||
_tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@:
|
||||
|
||||
// list_cores[core_index] = list_cores[next_index];
|
||||
|
||||
LDR x5, =_tx_thread_smp_protect_wait_list // Get the address of the list
|
||||
LDR w3, [x5, x2, LSL #2] // Get the value at the next index
|
||||
STR w3, [x5, x4, LSL #2] // Store the value at the current index
|
||||
|
||||
// core_index = next_index;
|
||||
|
||||
MOV w4, w2
|
||||
|
||||
B _tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@
|
||||
|
||||
// }
|
||||
|
||||
_tx_thread_smp_protect_wait_list_remove__removed\@:
|
||||
|
||||
/* Now update the tail. */
|
||||
// if (_tx_thread_smp_protect_wait_list_tail == 0)
|
||||
// {
|
||||
|
||||
LDR x5, =_tx_thread_smp_protect_wait_list_tail // Load tail address
|
||||
LDR w4, [x5] // Load tail value
|
||||
CMP w4, #0
|
||||
BNE _tx_thread_smp_protect_wait_list_remove__tail_not_zero\@
|
||||
|
||||
// _tx_thread_smp_protect_wait_list_tail = _tx_thread_smp_protect_wait_list_size;
|
||||
|
||||
LDR x2, =_tx_thread_smp_protect_wait_list_size
|
||||
LDR w4, [x2]
|
||||
|
||||
// }
|
||||
|
||||
_tx_thread_smp_protect_wait_list_remove__tail_not_zero\@:
|
||||
|
||||
// _tx_thread_smp_protect_wait_list_tail--;
|
||||
|
||||
SUB w4, w4, #1
|
||||
STR w4, [x5] // Store new tail value
|
||||
DMB ISH // Ensure that accesses to shared resource have completed
|
||||
|
||||
/* Release the list lock. */
|
||||
// _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0;
|
||||
|
||||
MOV w2, #0 // Build lock value
|
||||
LDR x4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force // Load lock address
|
||||
STR w2, [x4] // Store the new value
|
||||
DMB ISH // Ensure write to protection finishes
|
||||
|
||||
/* We're no longer waiting. Note that this should be zero since, again,
|
||||
this function is only called when a thread preemption is occurring. */
|
||||
// _tx_thread_smp_protect_wait_counts[core]--;
|
||||
LDR x4, =_tx_thread_smp_protect_wait_counts // Load wait list counts
|
||||
LDR w2, [x4, x8, LSL #2] // Load waiting value
|
||||
SUB w2, w2, #1 // Subtract 1
|
||||
STR w2, [x4, x8, LSL #2] // Store new waiting value
|
||||
|
||||
.endm
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread - Low Level SMP Support */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_smp_time_get Cortex-A35-SMP/AC6 */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function gets the global time value that is used for debug */
|
||||
/* information and event tracing. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* 32-bit time stamp */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ThreadX Source */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.global _tx_thread_smp_time_get
|
||||
.type _tx_thread_smp_time_get, @function
|
||||
_tx_thread_smp_time_get:
|
||||
MOV x0, #0 // FIXME: Get timer
|
||||
RET
|
||||
@@ -0,0 +1,129 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 - Low Level SMP Support */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_smp_unprotect Cortex-A35-SMP/AC6 */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function releases previously obtained protection. The supplied */
|
||||
/* previous SR is restored. If the value of _tx_thread_system_state */
|
||||
/* and _tx_thread_preempt_disable are both zero, then multithreading */
|
||||
/* is enabled as well. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* Previous Status Register */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* ThreadX Source */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* 04-25-2022 William E. Lamie Modified comments, removed */
|
||||
/* FIFO queueing, */
|
||||
/* resulting in version 6.1.11 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
.global _tx_thread_smp_unprotect
|
||||
.type _tx_thread_smp_unprotect, @function
|
||||
_tx_thread_smp_unprotect:
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
|
||||
MRS x1, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x2, x1, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x2, x1, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x1, x1, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x1, x1, x2, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
|
||||
LDR x2,=_tx_thread_smp_protection // Build address of protection structure
|
||||
LDR w3, [x2, #4] // Pickup the owning core
|
||||
CMP w1, w3 // Is it this core?
|
||||
BNE _still_protected // If this is not the owning core, protection is in force elsewhere
|
||||
|
||||
LDR w3, [x2, #8] // Pickup the protection count
|
||||
CMP w3, #0 // Check to see if the protection is still active
|
||||
BEQ _still_protected // If the protection count is zero, protection has already been cleared
|
||||
|
||||
SUB w3, w3, #1 // Decrement the protection count
|
||||
STR w3, [x2, #8] // Store the new count back
|
||||
CMP w3, #0 // Check to see if the protection is still active
|
||||
BNE _still_protected // If the protection count is non-zero, protection is still in force
|
||||
LDR x2,=_tx_thread_preempt_disable // Build address of preempt disable flag
|
||||
LDR w3, [x2] // Pickup preempt disable flag
|
||||
CMP w3, #0 // Is the preempt disable flag set?
|
||||
BNE _still_protected // Yes, skip the protection release
|
||||
|
||||
LDR x2,=_tx_thread_smp_protection // Build address of protection structure
|
||||
MOV w3, #0xFFFFFFFF // Build invalid value
|
||||
STR w3, [x2, #4] // Mark the protected core as invalid
|
||||
DMB ISH // Ensure that accesses to shared resource have completed
|
||||
MOV w3, #0 // Build release protection value
|
||||
STR w3, [x2, #0] // Release the protection
|
||||
DSB ISH // To ensure update of the protection occurs before other CPUs awake
|
||||
|
||||
_still_protected:
|
||||
#ifdef TX_ENABLE_WFE
|
||||
SEV // Send event to other CPUs, wakes anyone waiting on the protection (using WFE)
|
||||
#endif
|
||||
MSR DAIF, x0 // Restore interrupt posture
|
||||
RET
|
||||
@@ -0,0 +1,165 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_stack_build ARMv8-A-SMP */
|
||||
/* 6.x */
|
||||
/* 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 */
|
||||
/* function_ptr Pointer to entry 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 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
|
||||
// {
|
||||
.global _tx_thread_stack_build
|
||||
.type _tx_thread_stack_build, @function
|
||||
_tx_thread_stack_build:
|
||||
|
||||
|
||||
/* Build an interrupt frame. On Cortex-A35 it should look like this:
|
||||
|
||||
Stack Top: SSPR Initial SSPR
|
||||
ELR Point of interrupt
|
||||
x28 Initial value for x28
|
||||
not used Not used
|
||||
x26 Initial value for x26
|
||||
x27 Initial value for x27
|
||||
x24 Initial value for x24
|
||||
x25 Initial value for x25
|
||||
x22 Initial value for x22
|
||||
x23 Initial value for x23
|
||||
x20 Initial value for x20
|
||||
x21 Initial value for x21
|
||||
x18 Initial value for x18
|
||||
x19 Initial value for x19
|
||||
x16 Initial value for x16
|
||||
x17 Initial value for x17
|
||||
x14 Initial value for x14
|
||||
x15 Initial value for x15
|
||||
x12 Initial value for x12
|
||||
x13 Initial value for x13
|
||||
x10 Initial value for x10
|
||||
x11 Initial value for x11
|
||||
x8 Initial value for x8
|
||||
x9 Initial value for x9
|
||||
x6 Initial value for x6
|
||||
x7 Initial value for x7
|
||||
x4 Initial value for x4
|
||||
x5 Initial value for x5
|
||||
x2 Initial value for x2
|
||||
x3 Initial value for x3
|
||||
x0 Initial value for x0
|
||||
x1 Initial value for x1
|
||||
x29 Initial value for x29 (frame pointer)
|
||||
x30 Initial value for x30 (link register)
|
||||
0 For stack backtracing
|
||||
|
||||
Stack Bottom: (higher memory address) */
|
||||
|
||||
LDR x4, [x0, #24] // Pickup end of stack area
|
||||
BIC x4, x4, #0xF // Ensure 16-byte alignment
|
||||
|
||||
/* Actually build the stack frame. */
|
||||
|
||||
MOV x2, #0 // Build clear value
|
||||
MOV x3, #0 //
|
||||
|
||||
STP x2, x3, [x4, #-16]! // Set backtrace to 0
|
||||
STP x2, x3, [x4, #-16]! // Set initial x29, x30
|
||||
STP x2, x3, [x4, #-16]! // Set initial x0, x1
|
||||
STP x2, x3, [x4, #-16]! // Set initial x2, x3
|
||||
STP x2, x3, [x4, #-16]! // Set initial x4, x5
|
||||
STP x2, x3, [x4, #-16]! // Set initial x6, x7
|
||||
STP x2, x3, [x4, #-16]! // Set initial x8, x9
|
||||
STP x2, x3, [x4, #-16]! // Set initial x10, x11
|
||||
STP x2, x3, [x4, #-16]! // Set initial x12, x13
|
||||
STP x2, x3, [x4, #-16]! // Set initial x14, x15
|
||||
STP x2, x3, [x4, #-16]! // Set initial x16, x17
|
||||
STP x2, x3, [x4, #-16]! // Set initial x18, x19
|
||||
STP x2, x3, [x4, #-16]! // Set initial x20, x21
|
||||
STP x2, x3, [x4, #-16]! // Set initial x22, x23
|
||||
STP x2, x3, [x4, #-16]! // Set initial x24, x25
|
||||
STP x2, x3, [x4, #-16]! // Set initial x26, x27
|
||||
STP x2, x3, [x4, #-16]! // Set initial x28
|
||||
#ifdef EL1
|
||||
MOV x2, #0x4 // Build initial SPSR (EL1)
|
||||
#else
|
||||
#ifdef EL2
|
||||
MOV x2, #0x8 // Build initial SPSR (EL2)
|
||||
#else
|
||||
MOV x2, #0xC // Build initial SPSR (EL3)
|
||||
#endif
|
||||
#endif
|
||||
MOV x3, x1 // Build initial ELR
|
||||
STP x2, x3, [x4, #-16]! // Set initial SPSR & ELR
|
||||
|
||||
/* Setup stack pointer. */
|
||||
// thread_ptr -> tx_thread_stack_ptr = x2;
|
||||
|
||||
STR x4, [x0, #8] // Save stack pointer in thread's
|
||||
MOV x3, #1 // Build ready flag
|
||||
STR w3, [x0, #260] // Set ready flag
|
||||
RET // Return to caller
|
||||
|
||||
// }
|
||||
@@ -0,0 +1,194 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_system_return ARMv8-A-SMP */
|
||||
/* 6.x */
|
||||
/* 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 */
|
||||
/* 01-31-2022 Andres Mlinar Updated comments, */
|
||||
/* added ARMv8.2-A support, */
|
||||
/* resulting in version 6.1.10 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_thread_system_return(VOID)
|
||||
// {
|
||||
.global _tx_thread_system_return
|
||||
.type _tx_thread_system_return, @function
|
||||
_tx_thread_system_return:
|
||||
|
||||
/* Save minimal context on the stack. */
|
||||
|
||||
MRS x0, DAIF // Pickup DAIF
|
||||
MSR DAIFSet, 0x3 // Lockout interrupts
|
||||
STP x29, x30, [sp, #-16]! // Save x29 (frame pointer), x30 (link register)
|
||||
STP x19, x20, [sp, #-16]! // Save x19, x20
|
||||
STP x21, x22, [sp, #-16]! // Save x21, x22
|
||||
STP x23, x24, [sp, #-16]! // Save x23, x24
|
||||
STP x25, x26, [sp, #-16]! // Save x25, x26
|
||||
STP x27, x28, [sp, #-16]! // Save x27, x28
|
||||
MRS x8, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x3, x8, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x8, x8, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x3, x8, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x8, x8, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x8, x8, x3, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
LDR x5, =_tx_thread_current_ptr // Pickup address of current ptr
|
||||
LDR x6, [x5, x8, LSL #3] // Pickup current thread pointer
|
||||
|
||||
#ifdef ENABLE_ARM_FP
|
||||
LDR w7, [x6, #268] // Pickup FP enable flag
|
||||
CMP w7, #0 // Is FP enabled?
|
||||
BEQ _skip_fp_save // No, skip FP save
|
||||
STP q8, q9, [sp, #-32]! // Save q8, q9
|
||||
STP q10, q11, [sp, #-32]! // Save q10, q11
|
||||
STP q12, q13, [sp, #-32]! // Save q12, q13
|
||||
STP q14, q15, [sp, #-32]! // Save q14, q15
|
||||
MRS x2, FPSR // Pickup FPSR
|
||||
MRS x3, FPCR // Pickup FPCR
|
||||
STP x2, x3, [sp, #-16]! // Save FPSR, FPCR
|
||||
_skip_fp_save:
|
||||
#endif
|
||||
|
||||
MOV x1, #0 // Clear x1
|
||||
STP x0, x1, [sp, #-16]! // Save DAIF and clear value for ELR_EK1
|
||||
|
||||
#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. */
|
||||
|
||||
MOV x19, x5 // Save x5
|
||||
MOV x20, x6 // Save x6
|
||||
MOV x21, x8 // Save x2
|
||||
BL _tx_execution_thread_exit // Call the thread exit function
|
||||
MOV x8, x21 // Restore x2
|
||||
MOV x5, x19 // Restore x5
|
||||
MOV x6, x20 // Restore x6
|
||||
#endif
|
||||
|
||||
LDR x2, =_tx_timer_time_slice // Pickup address of time slice
|
||||
LDR w1, [x2, x8, LSL #2] // Pickup current time slice
|
||||
|
||||
/* Save current stack and switch to system stack. */
|
||||
// _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp;
|
||||
// sp = _tx_thread_system_stack_ptr[core];
|
||||
|
||||
MOV x4, sp //
|
||||
STR x4, [x6, #8] // Save thread stack pointer
|
||||
LDR x3, =_tx_thread_system_stack_ptr // Pickup address of system stack
|
||||
LDR x4, [x3, x8, LSL #3] // Pickup system stack pointer
|
||||
MOV sp, x4 // Setup system stack pointer
|
||||
|
||||
/* Determine if the time-slice is active. */
|
||||
// if (_tx_timer_time_slice[core])
|
||||
// {
|
||||
|
||||
MOV x4, #0 // Build clear value
|
||||
CMP w1, #0 // Is a time-slice active?
|
||||
BEQ __tx_thread_dont_save_ts // No, don't save the time-slice
|
||||
|
||||
/* Save the current remaining time-slice. */
|
||||
// _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice;
|
||||
// _tx_timer_time_slice = 0;
|
||||
|
||||
STR w4, [x2, x8, LSL #2] // Clear time-slice
|
||||
STR w1, [x6, #36] // Store current time-slice
|
||||
|
||||
// }
|
||||
__tx_thread_dont_save_ts:
|
||||
|
||||
/* Clear the current thread pointer. */
|
||||
// _tx_thread_current_ptr = TX_NULL;
|
||||
|
||||
STR x4, [x5, x8, LSL #3] // Clear current thread pointer
|
||||
|
||||
/* Set ready bit in thread control block. */
|
||||
|
||||
MOV x3, #1 // Build ready value
|
||||
STR w3, [x6, #260] // Make the thread ready
|
||||
DMB ISH //
|
||||
|
||||
/* Now clear protection. It is assumed that protection is in force whenever this routine is called. */
|
||||
|
||||
LDR x3, =_tx_thread_smp_protection // Pickup address of protection structure
|
||||
LDR x1, =_tx_thread_preempt_disable // Build address to preempt disable flag
|
||||
STR w4, [x1, #0] // Clear preempt disable flag
|
||||
STR w4, [x3, #8] // Cear protection count
|
||||
MOV x1, #0xFFFFFFFF // Build invalid value
|
||||
STR w1, [x3, #4] // Set core to an invalid value
|
||||
DMB ISH // Ensure that accesses to shared resource have completed
|
||||
STR w4, [x3, #0] // Clear protection
|
||||
DSB ISH // To ensure update of the shared resource occurs before other CPUs awake
|
||||
SEV // Send event to other CPUs, wakes anyone waiting on a mutex (using WFE)
|
||||
B _tx_thread_schedule // Jump to scheduler!
|
||||
|
||||
// }
|
||||
198
ports_arch/ARMv8-A/threadx_smp/common/src/tx_timer_interrupt.S
Normal file
198
ports_arch/ARMv8-A/threadx_smp/common/src/tx_timer_interrupt.S
Normal file
@@ -0,0 +1,198 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* 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 */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
#ifdef TX_INCLUDE_USER_DEFINE_FILE
|
||||
#include "tx_user.h"
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 3
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_timer_interrupt ARMv8-A-SMP */
|
||||
/* 6.x */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function processes the hardware timer interrupt. This */
|
||||
/* processing includes incrementing the system clock and checking for */
|
||||
/* time slice and/or timer expiration. If either is found, the */
|
||||
/* interrupt context save/restore functions are called along with the */
|
||||
/* expiration functions. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* _tx_timer_expiration_process Timer expiration processing */
|
||||
/* _tx_thread_time_slice Time slice interrupted thread */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* interrupt vector */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
||||
/* xx-xx-xxxx Tiejun Zhou Modified comment(s), added */
|
||||
/* #include tx_user.h, */
|
||||
/* resulting in version 6.x */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
// VOID _tx_timer_interrupt(VOID)
|
||||
// {
|
||||
.global _tx_timer_interrupt
|
||||
.type _tx_timer_interrupt, @function
|
||||
_tx_timer_interrupt:
|
||||
|
||||
MRS x2, MPIDR_EL1 // Pickup the core ID
|
||||
#ifdef TX_ARMV8_2
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x3, x2, #16, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x2, x2, #8, #8 // Isolate core ID
|
||||
#else
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
UBFX x3, x2, #8, #8 // Isolate cluster ID
|
||||
#endif
|
||||
UBFX x2, x2, #0, #8 // Isolate core ID
|
||||
#endif
|
||||
#if TX_THREAD_SMP_CLUSTERS > 1
|
||||
ADDS x2, x2, x3, LSL #2 // Calculate CPU ID
|
||||
#endif
|
||||
CMP x2, #0 // Is this core 0?
|
||||
BEQ __tx_process_timer // If desired core, continue processing
|
||||
RET // Simply return if different core
|
||||
__tx_process_timer:
|
||||
|
||||
/* 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. */
|
||||
|
||||
STP x27, x28, [sp, #-16]! // Save x27, x28
|
||||
STP x29, x30, [sp, #-16]! // Save x29 (frame pointer), x30 (link register)
|
||||
|
||||
/* Get inter-core protection. */
|
||||
|
||||
BL _tx_thread_smp_protect // Get inter-core protection
|
||||
MOV x28, x0 // Save the return value in preserved register
|
||||
|
||||
/* Increment the system clock. */
|
||||
// _tx_timer_system_clock++;
|
||||
|
||||
LDR x1, =_tx_timer_system_clock // Pickup address of system clock
|
||||
LDR w0, [x1, #0] // Pickup system clock
|
||||
ADD w0, w0, #1 // Increment system clock
|
||||
STR w0, [x1, #0] // Store new system clock
|
||||
|
||||
/* Test for timer expiration. */
|
||||
// if (*_tx_timer_current_ptr)
|
||||
// {
|
||||
|
||||
LDR x1, =_tx_timer_current_ptr // Pickup current timer pointer addr
|
||||
LDR x0, [x1, #0] // Pickup current timer
|
||||
LDR x2, [x0, #0] // Pickup timer list entry
|
||||
CMP x2, #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 x3, =_tx_timer_expired // Pickup expiration flag address
|
||||
MOV w2, #1 // Build expired value
|
||||
STR w2, [x3, #0] // Set expired flag
|
||||
B __tx_timer_done // Finished timer processing
|
||||
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
__tx_timer_no_timer:
|
||||
|
||||
/* No timer expired, increment the timer pointer. */
|
||||
// _tx_timer_current_ptr++;
|
||||
|
||||
ADD x0, x0, #8 // Move to next timer
|
||||
|
||||
/* Check for wrap-around. */
|
||||
// if (_tx_timer_current_ptr == _tx_timer_list_end)
|
||||
|
||||
LDR x3, =_tx_timer_list_end // Pickup addr of timer list end
|
||||
LDR x2, [x3, #0] // Pickup list end
|
||||
CMP x0, x2 // 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 x3, =_tx_timer_list_start // Pickup addr of timer list start
|
||||
LDR x0, [x3, #0] // Set current pointer to list start
|
||||
|
||||
__tx_timer_skip_wrap:
|
||||
|
||||
STR x0, [x1, #0] // Store new current timer pointer
|
||||
// }
|
||||
|
||||
__tx_timer_done:
|
||||
|
||||
/* Did a timer expire? */
|
||||
// if (_tx_timer_expired)
|
||||
// {
|
||||
|
||||
LDR x1, =_tx_timer_expired // Pickup addr of expired flag
|
||||
LDR w0, [x1, #0] // Pickup timer expired flag
|
||||
CMP w0, #0 // Check for timer expiration
|
||||
BEQ __tx_timer_dont_activate // If not set, skip timer activation
|
||||
|
||||
/* Process timer expiration. */
|
||||
// _tx_timer_expiration_process();
|
||||
|
||||
BL _tx_timer_expiration_process // Call the timer expiration handling routine
|
||||
|
||||
// }
|
||||
__tx_timer_dont_activate:
|
||||
|
||||
/* Call time-slice processing. */
|
||||
// _tx_thread_time_slice();
|
||||
BL _tx_thread_time_slice // Call time-slice processing
|
||||
|
||||
/* Release inter-core protection. */
|
||||
|
||||
MOV x0, x28 // Pass the previous status register back
|
||||
BL _tx_thread_smp_unprotect // Release protection
|
||||
|
||||
LDP x29, x30, [sp], #16 // Recover x29, x30
|
||||
LDP x27, x28, [sp], #16 // Recover x27, x28
|
||||
RET // Return to caller
|
||||
|
||||
// }
|
||||
@@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
|
||||
<cconfiguration id="com.arm.eclipse.build.config.v6.exe.debug.base.var.arm_compiler_6-6.4.1908576142">
|
||||
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.arm.eclipse.build.config.v6.exe.debug.base.var.arm_compiler_6-6.4.1908576142" moduleId="org.eclipse.cdt.core.settings" name="Debug">
|
||||
|
||||
<externalSettings/>
|
||||
|
||||
<extensions>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="com.arm.eclipse.builder.armcc.error" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<configuration artifactExtension="axf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="clean" description="" errorParsers="org.eclipse.cdt.core.GmakeErrorParser;com.arm.eclipse.builder.armcc.error;org.eclipse.cdt.core.CWDLocator" id="com.arm.eclipse.build.config.v6.exe.debug.base.var.arm_compiler_6-6.4.1908576142" name="Debug" parent="com.arm.eclipse.build.config.v6.exe.debug.base.var.arm_compiler_6-6.4.1908576142" postannouncebuildStep="" postbuildStep="" preannouncebuildStep="" prebuildStep="">
|
||||
|
||||
<folderInfo id="com.arm.eclipse.build.config.v6.exe.debug.base.var.arm_compiler_6-6.4.1908576142." name="/" resourcePath="">
|
||||
|
||||
<toolChain id="com.arm.toolchain.v6.base.var.arm_compiler_6-6.1592753597" name="Arm Compiler 6" superClass="com.arm.toolchain.v6.base.var.arm_compiler_6-6">
|
||||
|
||||
<option id="com.arm.toolchain.v6.base.options.target.cpu_fpu.1337922098" superClass="com.arm.toolchain.v6.base.options.target.cpu_fpu" useByScannerDiscovery="false" value="Cortex-A35.AArch64.ARMv8.Neon.Crypto" valueType="string"/>
|
||||
|
||||
<targetPlatform id="com.arm.toolchain.v6.base.var.arm_compiler_6-6.1592753597.2060144338" name=""/>
|
||||
|
||||
<builder autoBuildTarget="all" buildPath="${workspace_loc:/sample_threadx}/Debug" cleanBuildTarget="clean" enableAutoBuild="false" enableCleanBuild="true" enabledIncrementalBuild="true" id="com.arm.toolchain.v6.builder.930180945" incrementalBuildTarget="all" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="8" superClass="com.arm.toolchain.v6.builder"/>
|
||||
|
||||
<tool id="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6.1851739731" name="Arm C Compiler 6" superClass="com.arm.tool.c.compiler.v6.base.var.arm_compiler_6-6">
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.tool.c.compiler.v6.base.option.incpath.1469609164" name="Include path (-I)" superClass="com.arm.tool.c.compiler.v6.base.option.incpath" useByScannerDiscovery="false" valueType="includePath">
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/tx/inc_generic}""/>
|
||||
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/tx/inc_port}""/>
|
||||
|
||||
</option>
|
||||
|
||||
<option id="com.arm.tool.c.compiler.v6.base.options.debug.level.1747478037" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.options.debug.level.std" valueType="enumerated"/>
|
||||
|
||||
<option id="com.arm.tool.c.compiler.v6.base.option.cpu.1133188329" name="CPU (-mcpu)" superClass="com.arm.tool.c.compiler.v6.base.option.cpu" useByScannerDiscovery="true" value="cortex-a35" valueType="string"/>
|
||||
|
||||
<inputType id="com.arm.tool.c.compiler.v6.base.input.2103612806" superClass="com.arm.tool.c.compiler.v6.base.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.tool.cpp.compiler.v6.base.var.arm_compiler_6-6.1922332235" name="Arm C++ Compiler 6" superClass="com.arm.tool.cpp.compiler.v6.base.var.arm_compiler_6-6">
|
||||
|
||||
<option id="com.arm.tool.c.compiler.v6.base.options.debug.level.1099998393" name="Debug Level" superClass="com.arm.tool.c.compiler.v6.base.options.debug.level" useByScannerDiscovery="true" value="com.arm.tool.c.compiler.v6.base.options.debug.level.std" valueType="enumerated"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.tool.assembler.v6.base.var.arm_compiler_6-6.2087802691" name="Arm Assembler 6" superClass="com.arm.tool.assembler.v6.base.var.arm_compiler_6-6">
|
||||
|
||||
<option id="com.arm.tool.assembler.v6.base.options.debug.level.2040227767" name="Debug Level" superClass="com.arm.tool.assembler.v6.base.options.debug.level" useByScannerDiscovery="false" value="com.arm.tool.assembler.v6.base.options.debug.level.std" valueType="enumerated"/>
|
||||
|
||||
<option id="com.arm.tool.assembler.v6.base.option.cpu.143750331" name="CPU (-mcpu)" superClass="com.arm.tool.assembler.v6.base.option.cpu" useByScannerDiscovery="false" value="cortex-a35" valueType="string"/>
|
||||
|
||||
<inputType id="com.arm.tool.assembler.v6.base.input.1316842528" superClass="com.arm.tool.assembler.v6.base.input"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.tool.c.linker.v6.base.var.arm_compiler_6-6.171988073" name="Arm Linker 6" superClass="com.arm.tool.c.linker.v6.base.var.arm_compiler_6-6">
|
||||
|
||||
<option id="com.arm.tool.c.linker.option.entry.1473530747" name="Image entry point (--entry)" superClass="com.arm.tool.c.linker.option.entry" useByScannerDiscovery="false" value="start64" valueType="string"/>
|
||||
|
||||
<option id="com.arm.tool.c.linker.option.scatter.1215444221" name="Scatter file (--scatter)" superClass="com.arm.tool.c.linker.option.scatter" useByScannerDiscovery="false" value="..\sample_threadx.scat" valueType="string"/>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.tool.c.linker.libs.473662930" name="User library files" superClass="com.arm.tool.c.linker.libs" useByScannerDiscovery="false" valueType="libs">
|
||||
|
||||
<listOptionValue builtIn="false" value="..\..\tx\Debug\tx.a"/>
|
||||
|
||||
</option>
|
||||
|
||||
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.arm.tool.c.linker.option.keep.112664581" name="Keep specific sections (--keep)" superClass="com.arm.tool.c.linker.option.keep" useByScannerDiscovery="false" valueType="stringList">
|
||||
|
||||
<listOptionValue builtIn="false" value=""vectors.o(*)""/>
|
||||
|
||||
</option>
|
||||
|
||||
<option id="com.arm.tool.c.linker.option.imagemap.1230779259" name="Generate image map (--map)" superClass="com.arm.tool.c.linker.option.imagemap" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
|
||||
<option id="com.arm.tool.c.linker.option.redirectoutput.2060747663" name="Redirect diagnostics output to file (--list)" superClass="com.arm.tool.c.linker.option.redirectoutput" useByScannerDiscovery="false" value="sample_threadx.map" valueType="string"/>
|
||||
|
||||
</tool>
|
||||
|
||||
<tool id="com.arm.tool.librarian.v6.base.var.arm_compiler_6-6.1794035726" name="Arm Librarian 6" superClass="com.arm.tool.librarian.v6.base.var.arm_compiler_6-6"/>
|
||||
|
||||
</toolChain>
|
||||
|
||||
</folderInfo>
|
||||
|
||||
<sourceEntries>
|
||||
|
||||
<entry excluding="intrinsics.h|handlers.c|fvp.S|fvp.h|fvp_defs.h|xtables.S|xtables.h|retarget.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
|
||||
</sourceEntries>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
|
||||
</cconfiguration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
|
||||
<project id="sample_threadx.com.arm.eclipse.build.project.v6.exe.base.var.arm_compiler_6-6.4.1786842207" name="Executable"/>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
|
||||
<storageModule moduleId="refreshScope" versionNumber="2">
|
||||
|
||||
<configuration configurationName="Debug">
|
||||
|
||||
<resource resourceType="PROJECT" workspacePath="/sample_threadx"/>
|
||||
|
||||
</configuration>
|
||||
|
||||
</storageModule>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
|
||||
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
|
||||
|
||||
<storageModule moduleId="com.arm.projectSettings" version="6.0.0"/>
|
||||
|
||||
</cproject>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>sample_threadx</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,561 @@
|
||||
/*
|
||||
* GICv3.h - data types and function prototypes for GICv3 utility routines
|
||||
*
|
||||
* Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#ifndef GICV3_h
|
||||
#define GICV3_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* extra flags for GICD enable
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
gicdctlr_EnableGrp0 = (1 << 0),
|
||||
gicdctlr_EnableGrp1NS = (1 << 1),
|
||||
gicdctlr_EnableGrp1A = (1 << 1),
|
||||
gicdctlr_EnableGrp1S = (1 << 2),
|
||||
gicdctlr_EnableAll = (1 << 2) | (1 << 1) | (1 << 0),
|
||||
gicdctlr_ARE_S = (1 << 4), /* Enable Secure state affinity routing */
|
||||
gicdctlr_ARE_NS = (1 << 5), /* Enable Non-Secure state affinity routing */
|
||||
gicdctlr_DS = (1 << 6), /* Disable Security support */
|
||||
gicdctlr_E1NWF = (1 << 7) /* Enable "1-of-N" wakeup model */
|
||||
} GICDCTLRFlags_t;
|
||||
|
||||
/*
|
||||
* modes for SPI routing
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
gicdirouter_ModeSpecific = 0,
|
||||
gicdirouter_ModeAny = (1 << 31)
|
||||
} GICDIROUTERBits_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
gicdicfgr_Level = 0,
|
||||
gicdicfgr_Edge = (1 << 1)
|
||||
} GICDICFGRBits_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
gicigroupr_G0S = 0,
|
||||
gicigroupr_G1NS = (1 << 0),
|
||||
gicigroupr_G1S = (1 << 2)
|
||||
} GICIGROUPRBits_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
gicrwaker_ProcessorSleep = (1 << 1),
|
||||
gicrwaker_ChildrenAsleep = (1 << 2)
|
||||
} GICRWAKERBits_t;
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* Utility macros & functions
|
||||
*/
|
||||
#define RANGE_LIMIT(x) ((sizeof(x) / sizeof((x)[0])) - 1)
|
||||
|
||||
static inline uint64_t gicv3PackAffinity(uint32_t aff3, uint32_t aff2,
|
||||
uint32_t aff1, uint32_t aff0)
|
||||
{
|
||||
/*
|
||||
* only need to cast aff3 to get type promotion for all affinities
|
||||
*/
|
||||
return ((((uint64_t)aff3 & 0xff) << 32) |
|
||||
((aff2 & 0xff) << 16) |
|
||||
((aff1 & 0xff) << 8) | aff0);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* GIC Distributor Function Prototypes
|
||||
*/
|
||||
|
||||
/*
|
||||
* ConfigGICD - configure GIC Distributor prior to enabling it
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* control - control flags
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* ConfigGICD() will set an absolute flags value, whereas
|
||||
* {En,Dis}ableGICD() will only {set,clear} the flag bits
|
||||
* passed as a parameter
|
||||
*/
|
||||
void ConfigGICD(GICDCTLRFlags_t flags);
|
||||
|
||||
/*
|
||||
* EnableGICD - top-level enable for GIC Distributor
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* flags - new control flags to set
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* ConfigGICD() will set an absolute flags value, whereas
|
||||
* {En,Dis}ableGICD() will only {set,clear} the flag bits
|
||||
* passed as a parameter
|
||||
*/
|
||||
void EnableGICD(GICDCTLRFlags_t flags);
|
||||
|
||||
/*
|
||||
* DisableGICD - top-level disable for GIC Distributor
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* flags - control flags to clear
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* ConfigGICD() will set an absolute flags value, whereas
|
||||
* {En,Dis}ableGICD() will only {set,clear} the flag bits
|
||||
* passed as a parameter
|
||||
*/
|
||||
void DisableGICD(GICDCTLRFlags_t flags);
|
||||
|
||||
/*
|
||||
* SyncAREinGICD - synchronise GICD Address Routing Enable bits
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* flags - absolute flag bits to set in GIC Distributor
|
||||
*
|
||||
* dosync - flag whether to wait for ARE bits to match passed
|
||||
* flag field (dosync = true), or whether to set absolute
|
||||
* flag bits (dosync = false)
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* This function is used to resolve a race in an MP system whereby secondary
|
||||
* CPUs cannot reliably program all Redistributor registers until the
|
||||
* primary CPU has enabled Address Routing. The primary CPU will call this
|
||||
* function with dosync = false, while the secondaries will call it with
|
||||
* dosync = true.
|
||||
*/
|
||||
void SyncAREinGICD(GICDCTLRFlags_t flags, uint32_t dosync);
|
||||
|
||||
/*
|
||||
* EnableSPI - enable a specific shared peripheral interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - which interrupt to enable
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void EnableSPI(uint32_t id);
|
||||
|
||||
/*
|
||||
* DisableSPI - disable a specific shared peripheral interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - which interrupt to disable
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void DisableSPI(uint32_t id);
|
||||
|
||||
/*
|
||||
* SetSPIPriority - configure the priority for a shared peripheral interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* priority - 8-bit priority to program (see note below)
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* The GICv3 architecture makes this function sensitive to the Security
|
||||
* context in terms of what effect it has on the programmed priority: no
|
||||
* attempt is made to adjust for the reduced priority range available
|
||||
* when making Non-Secure accesses to the GIC
|
||||
*/
|
||||
void SetSPIPriority(uint32_t id, uint32_t priority);
|
||||
|
||||
/*
|
||||
* GetSPIPriority - determine the priority for a shared peripheral interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* interrupt priority in the range 0 - 0xff
|
||||
*/
|
||||
uint32_t GetSPIPriority(uint32_t id);
|
||||
|
||||
/*
|
||||
* SetSPIRoute - specify interrupt routing when gicdctlr_ARE is enabled
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* affinity - prepacked "dotted quad" affinity routing. NOTE: use the
|
||||
* gicv3PackAffinity() helper routine to generate this input
|
||||
*
|
||||
* mode - select routing mode (specific affinity, or any recipient)
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPIRoute(uint32_t id, uint64_t affinity, GICDIROUTERBits_t mode);
|
||||
|
||||
/*
|
||||
* GetSPIRoute - read ARE-enabled interrupt routing information
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* routing configuration
|
||||
*/
|
||||
uint64_t GetSPIRoute(uint32_t id);
|
||||
|
||||
/*
|
||||
* SetSPITarget - configure the set of processor targets for an interrupt
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* target - 8-bit target bitmap
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPITarget(uint32_t id, uint32_t target);
|
||||
|
||||
/*
|
||||
* GetSPITarget - read the set of processor targets for an interrupt
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* 8-bit target bitmap
|
||||
*/
|
||||
uint32_t GetSPITarget(uint32_t id);
|
||||
|
||||
/*
|
||||
* ConfigureSPI - setup an interrupt as edge- or level-triggered
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* config - desired configuration
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void ConfigureSPI(uint32_t id, GICDICFGRBits_t config);
|
||||
|
||||
/*
|
||||
* SetSPIPending - mark an interrupt as pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPIPending(uint32_t id);
|
||||
|
||||
/*
|
||||
* ClearSPIPending - mark an interrupt as not pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void ClearSPIPending(uint32_t id);
|
||||
|
||||
/*
|
||||
* GetSPIPending - query whether an interrupt is pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* pending status
|
||||
*/
|
||||
uint32_t GetSPIPending(uint32_t id);
|
||||
|
||||
/*
|
||||
* SetSPISecurity - mark a shared peripheral interrupt as
|
||||
* security <group>
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* id - which interrupt to mark
|
||||
*
|
||||
* group - the group for the interrupt
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPISecurity(uint32_t id, GICIGROUPRBits_t group);
|
||||
|
||||
/*
|
||||
* SetSPISecurityBlock - mark a block of 32 shared peripheral
|
||||
* interrupts as security <group>
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* block - which block to mark (e.g. 1 = Ints 32-63)
|
||||
*
|
||||
* group - the group for the interrupts
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPISecurityBlock(uint32_t block, GICIGROUPRBits_t group);
|
||||
|
||||
/*
|
||||
* SetSPISecurityAll - mark all shared peripheral interrupts
|
||||
* as security <group>
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* group - the group for the interrupts
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetSPISecurityAll(GICIGROUPRBits_t group);
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* GIC Re-Distributor Function Prototypes
|
||||
*
|
||||
* The model for calling Redistributor functions is that, rather than
|
||||
* identifying the target redistributor with every function call, the
|
||||
* SelectRedistributor() function is used to identify which redistributor
|
||||
* is to be used for all functions until a different redistributor is
|
||||
* explicitly selected
|
||||
*/
|
||||
|
||||
/*
|
||||
* WakeupGICR - wake up a Redistributor
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to wakeup
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void WakeupGICR(uint32_t gicr);
|
||||
|
||||
/*
|
||||
* EnablePrivateInt - enable a private (SGI/PPI) interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - which interrupt to enable
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void EnablePrivateInt(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* DisablePrivateInt - disable a private (SGI/PPI) interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - which interrupt to disable
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void DisablePrivateInt(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* SetPrivateIntPriority - configure the priority for a private
|
||||
* (SGI/PPI) interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* priority - 8-bit priority to program (see note below)
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*
|
||||
* Note:
|
||||
*
|
||||
* The GICv3 architecture makes this function sensitive to the Security
|
||||
* context in terms of what effect it has on the programmed priority: no
|
||||
* attempt is made to adjust for the reduced priority range available
|
||||
* when making Non-Secure accesses to the GIC
|
||||
*/
|
||||
void SetPrivateIntPriority(uint32_t gicr, uint32_t id, uint32_t priority);
|
||||
|
||||
/*
|
||||
* GetPrivateIntPriority - configure the priority for a private
|
||||
* (SGI/PPI) interrupt
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Int priority
|
||||
*/
|
||||
uint32_t GetPrivateIntPriority(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* SetPrivateIntPending - mark a private (SGI/PPI) interrupt as pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetPrivateIntPending(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* ClearPrivateIntPending - mark a private (SGI/PPI) interrupt as not pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void ClearPrivateIntPending(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* GetPrivateIntPending - query whether a private (SGI/PPI) interrupt is pending
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - interrupt identifier
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* pending status
|
||||
*/
|
||||
uint32_t GetPrivateIntPending(uint32_t gicr, uint32_t id);
|
||||
|
||||
/*
|
||||
* SetPrivateIntSecurity - mark a private (SGI/PPI) interrupt as
|
||||
* security <group>
|
||||
*
|
||||
* Inputs
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* id - which interrupt to mark
|
||||
*
|
||||
* group - the group for the interrupt
|
||||
*
|
||||
* Returns
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetPrivateIntSecurity(uint32_t gicr, uint32_t id, GICIGROUPRBits_t group);
|
||||
|
||||
/*
|
||||
* SetPrivateIntSecurityBlock - mark all 32 private (SGI/PPI)
|
||||
* interrupts as security <group>
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* gicr - which Redistributor to program
|
||||
*
|
||||
* group - the group for the interrupt
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* <nothing>
|
||||
*/
|
||||
void SetPrivateIntSecurityBlock(uint32_t gicr, GICIGROUPRBits_t group);
|
||||
|
||||
#endif /* ndef GICV3_h */
|
||||
|
||||
/* EOF GICv3.h */
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Aliases for GICv3 registers
|
||||
//
|
||||
// Copyright (c) 2016-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
#ifndef GICV3_ALIASES_H
|
||||
#define GICV3_ALIASES_H
|
||||
|
||||
#ifndef __clang__
|
||||
|
||||
/*
|
||||
* Mapping of MSR and MRS to physical and virtual CPU interface registers
|
||||
*
|
||||
* Arm Generic Interrupt Controller Architecture Specification
|
||||
* GIC architecture version 3.0 and version 4.0
|
||||
* Table 8-5
|
||||
*/
|
||||
#define ICC_AP0R0_EL1 S3_0_C12_C8_4
|
||||
#define ICC_AP0R1_EL1 S3_0_C12_C8_5
|
||||
#define ICC_AP0R2_EL1 S3_0_C12_C8_6
|
||||
#define ICC_AP0R3_EL1 S3_0_C12_C8_7
|
||||
|
||||
#define ICC_AP1R0_EL1 S3_0_C12_C9_0
|
||||
#define ICC_AP1R1_EL1 S3_0_C12_C9_1
|
||||
#define ICC_AP1R2_EL1 S3_0_C12_C9_2
|
||||
#define ICC_AP1R3_EL1 S3_0_C12_C9_3
|
||||
|
||||
#define ICC_ASGI1R_EL1 S3_0_C12_C11_6
|
||||
|
||||
#define ICC_BPR0_EL1 S3_0_C12_C8_3
|
||||
#define ICC_BPR1_EL1 S3_0_C12_C12_3
|
||||
|
||||
#define ICC_CTLR_EL1 S3_0_C12_C12_4
|
||||
#define ICC_CTLR_EL3 S3_6_C12_C12_4
|
||||
|
||||
#define ICC_DIR_EL1 S3_0_C12_C11_1
|
||||
|
||||
#define ICC_EOIR0_EL1 S3_0_C12_C8_1
|
||||
#define ICC_EOIR1_EL1 S3_0_C12_C12_1
|
||||
|
||||
#define ICC_HPPIR0_EL1 S3_0_C12_C8_2
|
||||
#define ICC_HPPIR1_EL1 S3_0_C12_C12_2
|
||||
|
||||
#define ICC_IAR0_EL1 S3_0_C12_C8_0
|
||||
#define ICC_IAR1_EL1 S3_0_C12_C12_0
|
||||
|
||||
#define ICC_IGRPEN0_EL1 S3_0_C12_C12_6
|
||||
#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7
|
||||
#define ICC_IGRPEN1_EL3 S3_6_C12_C12_7
|
||||
|
||||
#define ICC_PMR_EL1 S3_0_C4_C6_0
|
||||
#define ICC_RPR_EL1 S3_0_C12_C11_3
|
||||
|
||||
#define ICC_SGI0R_EL1 S3_0_C12_C11_7
|
||||
#define ICC_SGI1R_EL1 S3_0_C12_C11_5
|
||||
|
||||
#define ICC_SRE_EL1 S3_0_C12_C12_5
|
||||
#define ICC_SRE_EL2 S3_4_C12_C9_5
|
||||
#define ICC_SRE_EL3 S3_6_C12_C12_5
|
||||
|
||||
/*
|
||||
* Mapping of MSR and MRS to virtual interface control registers
|
||||
*
|
||||
* Arm Generic Interrupt Controller Architecture Specification
|
||||
* GIC architecture version 3.0 and version 4.0
|
||||
* Table 8-6
|
||||
*/
|
||||
#define ICH_AP0R0_EL2 S3_4_C12_C8_0
|
||||
#define ICH_AP0R1_EL2 S3_4_C12_C8_1
|
||||
#define ICH_AP0R2_EL2 S3_4_C12_C8_2
|
||||
#define ICH_AP0R3_EL2 S3_4_C12_C8_3
|
||||
|
||||
#define ICH_AP1R0_EL2 S3_4_C12_C9_0
|
||||
#define ICH_AP1R1_EL2 S3_4_C12_C9_1
|
||||
#define ICH_AP1R2_EL2 S3_4_C12_C9_2
|
||||
#define ICH_AP1R3_EL2 S3_4_C12_C9_3
|
||||
|
||||
#define ICH_HCR_EL2 S3_4_C12_C11_0
|
||||
|
||||
#define ICH_VTR_EL2 S3_4_C12_C11_1
|
||||
|
||||
#define ICH_MISR_EL2 S3_4_C12_C11_2
|
||||
|
||||
#define ICH_EISR_EL2 S3_4_C12_C11_3
|
||||
|
||||
#define ICH_ELRSR_EL2 S3_4_C12_C11_5
|
||||
|
||||
#define ICH_VMCR_EL2 S3_4_C12_C11_7
|
||||
|
||||
#define ICH_LR0_EL2 S3_4_C12_C12_0
|
||||
#define ICH_LR1_EL2 S3_4_C12_C12_1
|
||||
#define ICH_LR2_EL2 S3_4_C12_C12_2
|
||||
#define ICH_LR3_EL2 S3_4_C12_C12_3
|
||||
#define ICH_LR4_EL2 S3_4_C12_C12_4
|
||||
#define ICH_LR5_EL2 S3_4_C12_C12_5
|
||||
#define ICH_LR6_EL2 S3_4_C12_C12_6
|
||||
#define ICH_LR7_EL2 S3_4_C12_C12_7
|
||||
#define ICH_LR8_EL2 S3_4_C12_C13_0
|
||||
#define ICH_LR9_EL2 S3_4_C12_C13_1
|
||||
#define ICH_LR10_EL2 S3_4_C12_C13_2
|
||||
#define ICH_LR11_EL2 S3_4_C12_C13_3
|
||||
#define ICH_LR12_EL2 S3_4_C12_C13_4
|
||||
#define ICH_LR13_EL2 S3_4_C12_C13_5
|
||||
#define ICH_LR14_EL2 S3_4_C12_C13_6
|
||||
#define ICH_LR15_EL2 S3_4_C12_C13_7
|
||||
|
||||
#endif /* not __clang__ */
|
||||
|
||||
#endif /* GICV3_ALIASES */
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* GICv3_gicc.h - prototypes and inline functions for GICC system register operations
|
||||
*
|
||||
* Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#ifndef GICV3_gicc_h
|
||||
#define GICV3_gicc_h
|
||||
|
||||
#include "GICv3_aliases.h"
|
||||
|
||||
#define stringify_no_expansion(x) #x
|
||||
#define stringify(x) stringify_no_expansion(x)
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sreSRE = (1 << 0),
|
||||
sreDFB = (1 << 1),
|
||||
sreDIB = (1 << 2),
|
||||
sreEnable = (1 << 3)
|
||||
} ICC_SREBits_t;
|
||||
|
||||
static inline void setICC_SRE_EL1(ICC_SREBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_SRE_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_SRE_EL1(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_SRE_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline void setICC_SRE_EL2(ICC_SREBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_SRE_EL2)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_SRE_EL2(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_SRE_EL2)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline void setICC_SRE_EL3(ICC_SREBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_SRE_EL3)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_SRE_EL3(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_SRE_EL3)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
igrpEnable = (1 << 0),
|
||||
igrpEnableGrp1NS = (1 << 0),
|
||||
igrpEnableGrp1S = (1 << 2)
|
||||
} ICC_IGRPBits_t;
|
||||
|
||||
static inline void setICC_IGRPEN0_EL1(ICC_IGRPBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_IGRPEN0_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline void setICC_IGRPEN1_EL1(ICC_IGRPBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_IGRPEN1_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline void setICC_IGRPEN1_EL3(ICC_IGRPBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_IGRPEN1_EL3)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ctlrCBPR = (1 << 0),
|
||||
ctlrCBPR_EL1S = (1 << 0),
|
||||
ctlrEOImode = (1 << 1),
|
||||
ctlrCBPR_EL1NS = (1 << 1),
|
||||
ctlrEOImode_EL3 = (1 << 2),
|
||||
ctlrEOImode_EL1S = (1 << 3),
|
||||
ctlrEOImode_EL1NS = (1 << 4),
|
||||
ctlrRM = (1 << 5),
|
||||
ctlrPMHE = (1 << 6)
|
||||
} ICC_CTLRBits_t;
|
||||
|
||||
static inline void setICC_CTLR_EL1(ICC_CTLRBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_CTLR_EL1)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_CTLR_EL1(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_CTLR_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline void setICC_CTLR_EL3(ICC_CTLRBits_t mode)
|
||||
{
|
||||
asm("msr "stringify(ICC_CTLR_EL3)", %0\n; isb" :: "r" ((uint64_t)mode));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_CTLR_EL3(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_CTLR_EL3)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static inline uint64_t getICC_IAR0(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_IAR0_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_IAR1(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_IAR1_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline void setICC_EOIR0(uint32_t interrupt)
|
||||
{
|
||||
asm("msr "stringify(ICC_EOIR0_EL1)", %0\n; isb" :: "r" ((uint64_t)interrupt));
|
||||
}
|
||||
|
||||
static inline void setICC_EOIR1(uint32_t interrupt)
|
||||
{
|
||||
asm("msr "stringify(ICC_EOIR1_EL1)", %0\n; isb" :: "r" ((uint64_t)interrupt));
|
||||
}
|
||||
|
||||
static inline void setICC_DIR(uint32_t interrupt)
|
||||
{
|
||||
asm("msr "stringify(ICC_DIR_EL1)", %0\n; isb" :: "r" ((uint64_t)interrupt));
|
||||
}
|
||||
|
||||
static inline void setICC_PMR(uint32_t priority)
|
||||
{
|
||||
asm("msr "stringify(ICC_PMR_EL1)", %0\n; isb" :: "r" ((uint64_t)priority));
|
||||
}
|
||||
|
||||
static inline void setICC_BPR0(uint32_t binarypoint)
|
||||
{
|
||||
asm("msr "stringify(ICC_BPR0_EL1)", %0\n; isb" :: "r" ((uint64_t)binarypoint));
|
||||
}
|
||||
|
||||
static inline void setICC_BPR1(uint32_t binarypoint)
|
||||
{
|
||||
asm("msr "stringify(ICC_BPR1_EL1)", %0\n; isb" :: "r" ((uint64_t)binarypoint));
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_BPR0(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_BPR0_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_BPR1(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_BPR1_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
static inline uint64_t getICC_RPR(void)
|
||||
{
|
||||
uint64_t retc;
|
||||
|
||||
asm("mrs %0, "stringify(ICC_RPR_EL1)"\n" : "=r" (retc));
|
||||
|
||||
return retc;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sgirIRMTarget = 0,
|
||||
sgirIRMAll = (1ull << 40)
|
||||
} ICC_SGIRBits_t;
|
||||
|
||||
static inline void setICC_SGI0R(uint8_t aff3, uint8_t aff2,
|
||||
uint8_t aff1, ICC_SGIRBits_t irm,
|
||||
uint16_t targetlist, uint8_t intid)
|
||||
{
|
||||
uint64_t packedbits = (((uint64_t)aff3 << 48) | ((uint64_t)aff2 << 32) | \
|
||||
((uint64_t)aff1 << 16) | irm | targetlist | \
|
||||
((uint64_t)(intid & 0x0f) << 24));
|
||||
|
||||
asm("msr "stringify(ICC_SGI0R_EL1)", %0\n; isb" :: "r" (packedbits));
|
||||
}
|
||||
|
||||
static inline void setICC_SGI1R(uint8_t aff3, uint8_t aff2,
|
||||
uint8_t aff1, ICC_SGIRBits_t irm,
|
||||
uint16_t targetlist, uint8_t intid)
|
||||
{
|
||||
uint64_t packedbits = (((uint64_t)aff3 << 48) | ((uint64_t)aff2 << 32) | \
|
||||
((uint64_t)aff1 << 16) | irm | targetlist | \
|
||||
((uint64_t)(intid & 0x0f) << 24));
|
||||
|
||||
asm("msr "stringify(ICC_SGI1R_EL1)", %0\n; isb" :: "r" (packedbits));
|
||||
}
|
||||
|
||||
static inline void setICC_ASGI1R(uint8_t aff3, uint8_t aff2,
|
||||
uint8_t aff1, ICC_SGIRBits_t irm,
|
||||
uint16_t targetlist, uint8_t intid)
|
||||
{
|
||||
uint64_t packedbits = (((uint64_t)aff3 << 48) | ((uint64_t)aff2 << 32) | \
|
||||
((uint64_t)aff1 << 16) | irm | targetlist | \
|
||||
((uint64_t)(intid & 0x0f) << 24));
|
||||
|
||||
asm("msr "stringify(ICC_ASGI1R_EL1)", %0\n; isb" :: "r" (packedbits));
|
||||
}
|
||||
|
||||
#endif /* ndef GICV3_gicc_h */
|
||||
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* GICv3_gicd.c - generic driver code for GICv3 distributor
|
||||
*
|
||||
* Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#include "GICv3.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t GICD_CTLR; // +0x0000
|
||||
const volatile uint32_t GICD_TYPER; // +0x0004
|
||||
const volatile uint32_t GICD_IIDR; // +0x0008
|
||||
|
||||
const volatile uint32_t padding0; // +0x000c
|
||||
|
||||
volatile uint32_t GICD_STATUSR; // +0x0010
|
||||
|
||||
const volatile uint32_t padding1[3]; // +0x0014
|
||||
|
||||
volatile uint32_t IMP_DEF[8]; // +0x0020
|
||||
|
||||
volatile uint32_t GICD_SETSPI_NSR; // +0x0040
|
||||
const volatile uint32_t padding2; // +0x0044
|
||||
volatile uint32_t GICD_CLRSPI_NSR; // +0x0048
|
||||
const volatile uint32_t padding3; // +0x004c
|
||||
volatile uint32_t GICD_SETSPI_SR; // +0x0050
|
||||
const volatile uint32_t padding4; // +0x0054
|
||||
volatile uint32_t GICD_CLRSPI_SR; // +0x0058
|
||||
|
||||
const volatile uint32_t padding5[3]; // +0x005c
|
||||
|
||||
volatile uint32_t GICD_SEIR; // +0x0068
|
||||
|
||||
const volatile uint32_t padding6[5]; // +0x006c
|
||||
|
||||
volatile uint32_t GICD_IGROUPR[32]; // +0x0080
|
||||
|
||||
volatile uint32_t GICD_ISENABLER[32]; // +0x0100
|
||||
volatile uint32_t GICD_ICENABLER[32]; // +0x0180
|
||||
volatile uint32_t GICD_ISPENDR[32]; // +0x0200
|
||||
volatile uint32_t GICD_ICPENDR[32]; // +0x0280
|
||||
volatile uint32_t GICD_ISACTIVER[32]; // +0x0300
|
||||
volatile uint32_t GICD_ICACTIVER[32]; // +0x0380
|
||||
|
||||
volatile uint8_t GICD_IPRIORITYR[1024]; // +0x0400
|
||||
volatile uint8_t GICD_ITARGETSR[1024]; // +0x0800
|
||||
volatile uint32_t GICD_ICFGR[64]; // +0x0c00
|
||||
volatile uint32_t GICD_IGRPMODR[32]; // +0x0d00
|
||||
const volatile uint32_t padding7[32]; // +0x0d80
|
||||
volatile uint32_t GICD_NSACR[64]; // +0x0e00
|
||||
|
||||
volatile uint32_t GICD_SGIR; // +0x0f00
|
||||
|
||||
const volatile uint32_t padding8[3]; // +0x0f04
|
||||
|
||||
volatile uint32_t GICD_CPENDSGIR[4]; // +0x0f10
|
||||
volatile uint32_t GICD_SPENDSGIR[4]; // +0x0f20
|
||||
|
||||
const volatile uint32_t padding9[52]; // +0x0f30
|
||||
const volatile uint32_t padding10[5120]; // +0x1000
|
||||
|
||||
volatile uint64_t GICD_IROUTER[1024]; // +0x6000
|
||||
} GICv3_distributor;
|
||||
|
||||
/*
|
||||
* use the scatter file to place GICD
|
||||
*/
|
||||
static GICv3_distributor __attribute__((section(".bss.distributor"))) gicd;
|
||||
|
||||
void ConfigGICD(GICDCTLRFlags_t flags)
|
||||
{
|
||||
gicd.GICD_CTLR = flags;
|
||||
}
|
||||
|
||||
void EnableGICD(GICDCTLRFlags_t flags)
|
||||
{
|
||||
gicd.GICD_CTLR |= flags;
|
||||
}
|
||||
|
||||
void DisableGICD(GICDCTLRFlags_t flags)
|
||||
{
|
||||
gicd.GICD_CTLR &= ~flags;
|
||||
}
|
||||
|
||||
void SyncAREinGICD(GICDCTLRFlags_t flags, uint32_t dosync)
|
||||
{
|
||||
if (dosync)
|
||||
{
|
||||
const uint32_t tmask = gicdctlr_ARE_S | gicdctlr_ARE_NS;
|
||||
const uint32_t tval = flags & tmask;
|
||||
|
||||
while ((gicd.GICD_CTLR & tmask) != tval)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
gicd.GICD_CTLR = flags;
|
||||
}
|
||||
|
||||
void EnableSPI(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ISENABLER has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ISENABLER);
|
||||
id &= 32 - 1;
|
||||
|
||||
gicd.GICD_ISENABLER[bank] = 1 << id;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DisableSPI(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ISENABLER has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ICENABLER);
|
||||
id &= 32 - 1;
|
||||
|
||||
gicd.GICD_ICENABLER[bank] = 1 << id;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void SetSPIPriority(uint32_t id, uint32_t priority)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_IPRIORITYR has one byte-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_IPRIORITYR);
|
||||
|
||||
gicd.GICD_IPRIORITYR[bank] = priority;
|
||||
}
|
||||
|
||||
uint32_t GetSPIPriority(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_IPRIORITYR has one byte-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_IPRIORITYR);
|
||||
|
||||
return (uint32_t)(gicd.GICD_IPRIORITYR[bank]);
|
||||
}
|
||||
|
||||
void SetSPIRoute(uint32_t id, uint64_t affinity, GICDIROUTERBits_t mode)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_IROUTER has one doubleword-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_IROUTER);
|
||||
|
||||
gicd.GICD_IROUTER[bank] = affinity | (uint64_t)mode;
|
||||
}
|
||||
|
||||
uint64_t GetSPIRoute(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_IROUTER has one doubleword-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_IROUTER);
|
||||
|
||||
return gicd.GICD_IROUTER[bank];
|
||||
}
|
||||
|
||||
void SetSPITarget(uint32_t id, uint32_t target)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ITARGETSR has one byte-wide entry per interrupt
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_ITARGETSR);
|
||||
|
||||
gicd.GICD_ITARGETSR[bank] = target;
|
||||
}
|
||||
|
||||
uint32_t GetSPITarget(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ITARGETSR has one byte-wide entry per interrupt
|
||||
*/
|
||||
/*
|
||||
* GICD_ITARGETSR has 4 interrupts per register, i.e. 8-bits of
|
||||
* target bitmap per register
|
||||
*/
|
||||
bank = id & RANGE_LIMIT(gicd.GICD_ITARGETSR);
|
||||
|
||||
return (uint32_t)(gicd.GICD_ITARGETSR[bank]);
|
||||
}
|
||||
|
||||
void ConfigureSPI(uint32_t id, GICDICFGRBits_t config)
|
||||
{
|
||||
uint32_t bank, tmp;
|
||||
|
||||
/*
|
||||
* GICD_ICFGR has 16 interrupts per register, i.e. 2-bits of
|
||||
* configuration per register
|
||||
*/
|
||||
bank = (id >> 4) & RANGE_LIMIT(gicd.GICD_ICFGR);
|
||||
config &= 3;
|
||||
|
||||
id = (id & 0xf) << 1;
|
||||
|
||||
tmp = gicd.GICD_ICFGR[bank];
|
||||
tmp &= ~(3 << id);
|
||||
tmp |= config << id;
|
||||
gicd.GICD_ICFGR[bank] = tmp;
|
||||
}
|
||||
|
||||
void SetSPIPending(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ISPENDR has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ISPENDR);
|
||||
id &= 0x1f;
|
||||
|
||||
gicd.GICD_ISPENDR[bank] = 1 << id;
|
||||
}
|
||||
|
||||
void ClearSPIPending(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ICPENDR has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ICPENDR);
|
||||
id &= 0x1f;
|
||||
|
||||
gicd.GICD_ICPENDR[bank] = 1 << id;
|
||||
}
|
||||
|
||||
uint32_t GetSPIPending(uint32_t id)
|
||||
{
|
||||
uint32_t bank;
|
||||
|
||||
/*
|
||||
* GICD_ICPENDR has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_ICPENDR);
|
||||
id &= 0x1f;
|
||||
|
||||
return (gicd.GICD_ICPENDR[bank] >> id) & 1;
|
||||
}
|
||||
|
||||
void SetSPISecurity(uint32_t id, GICIGROUPRBits_t group)
|
||||
{
|
||||
uint32_t bank, groupmod;
|
||||
|
||||
/*
|
||||
* GICD_IGROUPR has 32 interrupts per register
|
||||
*/
|
||||
bank = (id >> 5) & RANGE_LIMIT(gicd.GICD_IGROUPR);
|
||||
id &= 0x1f;
|
||||
|
||||
/*
|
||||
* the single group argument is split into two separate
|
||||
* registers, so filter out and remove the (new to gicv3)
|
||||
* group modifier bit
|
||||
*/
|
||||
groupmod = (group >> 1) & 1;
|
||||
group &= 1;
|
||||
|
||||
/*
|
||||
* either set or clear the Group bit for the interrupt as appropriate
|
||||
*/
|
||||
if (group)
|
||||
gicd.GICD_IGROUPR[bank] |= 1 << id;
|
||||
else
|
||||
gicd.GICD_IGROUPR[bank] &= ~(1 << id);
|
||||
|
||||
/*
|
||||
* now deal with groupmod
|
||||
*/
|
||||
if (groupmod)
|
||||
gicd.GICD_IGRPMODR[bank] |= 1 << id;
|
||||
else
|
||||
gicd.GICD_IGRPMODR[bank] &= ~(1 << id);
|
||||
}
|
||||
|
||||
void SetSPISecurityBlock(uint32_t block, GICIGROUPRBits_t group)
|
||||
{
|
||||
uint32_t groupmod;
|
||||
const uint32_t nbits = (sizeof group * 8) - 1;
|
||||
|
||||
/*
|
||||
* GICD_IGROUPR has 32 interrupts per register
|
||||
*/
|
||||
block &= RANGE_LIMIT(gicd.GICD_IGROUPR);
|
||||
|
||||
/*
|
||||
* get each bit of group config duplicated over all 32-bits in a word
|
||||
*/
|
||||
groupmod = (uint32_t)(((int32_t)group << (nbits - 1)) >> 31);
|
||||
group = (uint32_t)(((int32_t)group << nbits) >> 31);
|
||||
|
||||
/*
|
||||
* set the security state for this block of SPIs
|
||||
*/
|
||||
gicd.GICD_IGROUPR[block] = group;
|
||||
gicd.GICD_IGRPMODR[block] = groupmod;
|
||||
}
|
||||
|
||||
void SetSPISecurityAll(GICIGROUPRBits_t group)
|
||||
{
|
||||
uint32_t block;
|
||||
|
||||
/*
|
||||
* GICD_TYPER.ITLinesNumber gives (No. SPIS / 32) - 1, and we
|
||||
* want to iterate over all blocks excluding 0 (which are the
|
||||
* SGI/PPI interrupts, and not relevant here)
|
||||
*/
|
||||
for (block = (gicd.GICD_TYPER & ((1 << 5) - 1)); block > 0; --block)
|
||||
SetSPISecurityBlock(block, group);
|
||||
}
|
||||
|
||||
/* EOF GICv3_gicd.c */
|
||||
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* GICv3_gicr.c - generic driver code for GICv3 redistributor
|
||||
*
|
||||
* Copyright (c) 2014-2019 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#include "GICv3.h"
|
||||
|
||||
/*
|
||||
* physical LPI Redistributor register map
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t GICR_CTLR; // +0x0000 - RW - Redistributor Control Register
|
||||
const volatile uint32_t GICR_IIDR; // +0x0004 - RO - Implementer Identification Register
|
||||
const volatile uint32_t GICR_TYPER[2]; // +0x0008 - RO - Redistributor Type Register
|
||||
volatile uint32_t GICR_STATUSR; // +0x0010 - RW - Error Reporting Status Register, optional
|
||||
volatile uint32_t GICR_WAKER; // +0x0014 - RW - Redistributor Wake Register
|
||||
const volatile uint32_t padding1[2]; // +0x0018 - RESERVED
|
||||
#ifndef USE_GIC600
|
||||
volatile uint32_t IMPDEF1[8]; // +0x0020 - ?? - IMPLEMENTATION DEFINED
|
||||
#else
|
||||
volatile uint32_t GICR_FCTLR; // +0x0020 - RW - Function Control Register
|
||||
volatile uint32_t GICR_PWRR; // +0x0024 - RW - Power Management Control Register
|
||||
volatile uint32_t GICR_CLASS; // +0x0028 - RW - Class Register
|
||||
const volatile uint32_t padding2[5]; // +0x002C - RESERVED
|
||||
#endif
|
||||
volatile uint64_t GICR_SETLPIR; // +0x0040 - WO - Set LPI Pending Register
|
||||
volatile uint64_t GICR_CLRLPIR; // +0x0048 - WO - Clear LPI Pending Register
|
||||
const volatile uint32_t padding3[8]; // +0x0050 - RESERVED
|
||||
volatile uint64_t GICR_PROPBASER; // +0x0070 - RW - Redistributor Properties Base Address Register
|
||||
volatile uint64_t GICR_PENDBASER; // +0x0078 - RW - Redistributor LPI Pending Table Base Address Register
|
||||
const volatile uint32_t padding4[8]; // +0x0080 - RESERVED
|
||||
volatile uint64_t GICR_INVLPIR; // +0x00A0 - WO - Redistributor Invalidate LPI Register
|
||||
const volatile uint32_t padding5[2]; // +0x00A8 - RESERVED
|
||||
volatile uint64_t GICR_INVALLR; // +0x00B0 - WO - Redistributor Invalidate All Register
|
||||
const volatile uint32_t padding6[2]; // +0x00B8 - RESERVED
|
||||
volatile uint64_t GICR_SYNCR; // +0x00C0 - RO - Redistributor Synchronize Register
|
||||
const volatile uint32_t padding7[2]; // +0x00C8 - RESERVED
|
||||
const volatile uint32_t padding8[12]; // +0x00D0 - RESERVED
|
||||
volatile uint64_t IMPDEF2; // +0x0100 - WO - IMPLEMENTATION DEFINED
|
||||
const volatile uint32_t padding9[2]; // +0x0108 - RESERVED
|
||||
volatile uint64_t IMPDEF3; // +0x0110 - WO - IMPLEMENTATION DEFINED
|
||||
const volatile uint32_t padding10[2]; // +0x0118 - RESERVED
|
||||
} GICv3_redistributor_RD;
|
||||
|
||||
/*
|
||||
* SGI and PPI Redistributor register map
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const volatile uint32_t padding1[32]; // +0x0000 - RESERVED
|
||||
volatile uint32_t GICR_IGROUPR0; // +0x0080 - RW - Interrupt Group Registers (Security Registers in GICv1)
|
||||
const volatile uint32_t padding2[31]; // +0x0084 - RESERVED
|
||||
volatile uint32_t GICR_ISENABLER; // +0x0100 - RW - Interrupt Set-Enable Registers
|
||||
const volatile uint32_t padding3[31]; // +0x0104 - RESERVED
|
||||
volatile uint32_t GICR_ICENABLER; // +0x0180 - RW - Interrupt Clear-Enable Registers
|
||||
const volatile uint32_t padding4[31]; // +0x0184 - RESERVED
|
||||
volatile uint32_t GICR_ISPENDR; // +0x0200 - RW - Interrupt Set-Pending Registers
|
||||
const volatile uint32_t padding5[31]; // +0x0204 - RESERVED
|
||||
volatile uint32_t GICR_ICPENDR; // +0x0280 - RW - Interrupt Clear-Pending Registers
|
||||
const volatile uint32_t padding6[31]; // +0x0284 - RESERVED
|
||||
volatile uint32_t GICR_ISACTIVER; // +0x0300 - RW - Interrupt Set-Active Register
|
||||
const volatile uint32_t padding7[31]; // +0x0304 - RESERVED
|
||||
volatile uint32_t GICR_ICACTIVER; // +0x0380 - RW - Interrupt Clear-Active Register
|
||||
const volatile uint32_t padding8[31]; // +0x0184 - RESERVED
|
||||
volatile uint8_t GICR_IPRIORITYR[32]; // +0x0400 - RW - Interrupt Priority Registers
|
||||
const volatile uint32_t padding9[504]; // +0x0420 - RESERVED
|
||||
volatile uint32_t GICR_ICnoFGR[2]; // +0x0C00 - RW - Interrupt Configuration Registers
|
||||
const volatile uint32_t padding10[62]; // +0x0C08 - RESERVED
|
||||
volatile uint32_t GICR_IGRPMODR0; // +0x0D00 - RW - ????
|
||||
const volatile uint32_t padding11[63]; // +0x0D04 - RESERVED
|
||||
volatile uint32_t GICR_NSACR; // +0x0E00 - RW - Non-Secure Access Control Register
|
||||
} GICv3_redistributor_SGI;
|
||||
|
||||
/*
|
||||
* We have a multiplicity of GIC Redistributors; on the GIC-AEM and
|
||||
* GIC-500 they are arranged as one 128KB region per redistributor: one
|
||||
* 64KB page of GICR LPI registers, and one 64KB page of GICR Private
|
||||
* Int registers
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
GICv3_redistributor_RD RD_base;
|
||||
uint8_t padding[64 * 1024];
|
||||
} RDblock;
|
||||
|
||||
union
|
||||
{
|
||||
GICv3_redistributor_SGI SGI_base;
|
||||
uint8_t padding[64 * 1024];
|
||||
} SGIblock;
|
||||
} GICv3_GICR;
|
||||
|
||||
/*
|
||||
* use the scatter file to place GIC Redistributor base address
|
||||
*
|
||||
* although this code doesn't know how many Redistributor banks
|
||||
* a particular system will have, we declare gicrbase as an array
|
||||
* to avoid unwanted compiler optimisations when calculating the
|
||||
* base of a particular Redistributor bank
|
||||
*/
|
||||
static const GICv3_GICR gicrbase[2] __attribute__((section (".bss.redistributor")));
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* utility functions to calculate base of a particular
|
||||
* Redistributor bank
|
||||
*/
|
||||
|
||||
static inline GICv3_redistributor_RD *const getgicrRD(uint32_t gicr)
|
||||
{
|
||||
GICv3_GICR *const arraybase = (GICv3_GICR *const)&gicrbase;
|
||||
|
||||
return &((arraybase + gicr)->RDblock.RD_base);
|
||||
}
|
||||
|
||||
static inline GICv3_redistributor_SGI *const getgicrSGI(uint32_t gicr)
|
||||
{
|
||||
GICv3_GICR *arraybase = (GICv3_GICR *)(&gicrbase);
|
||||
|
||||
return &(arraybase[gicr].SGIblock.SGI_base);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
// This function walks a block of RDs to find one with the matching affinity
|
||||
uint32_t GetGICR(uint32_t affinity)
|
||||
{
|
||||
GICv3_redistributor_RD* gicr;
|
||||
uint32_t index = 0;
|
||||
|
||||
do
|
||||
{
|
||||
gicr = getgicrRD(index);
|
||||
if (gicr->GICR_TYPER[1] == affinity)
|
||||
return index;
|
||||
|
||||
index++;
|
||||
}
|
||||
while((gicr->GICR_TYPER[0] & (1<<4)) == 0); // Keep looking until GICR_TYPER.Last reports no more RDs in block
|
||||
|
||||
return 0xFFFFFFFF; // return -1 to signal not RD found
|
||||
}
|
||||
|
||||
void WakeupGICR(uint32_t gicr)
|
||||
{
|
||||
GICv3_redistributor_RD *const gicrRD = getgicrRD(gicr);
|
||||
#ifdef USE_GIC600
|
||||
//Power up Re-distributor for GIC-600
|
||||
gicrRD->GICR_PWRR = 0x2;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* step 1 - ensure GICR_WAKER.ProcessorSleep is off
|
||||
*/
|
||||
gicrRD->GICR_WAKER &= ~gicrwaker_ProcessorSleep;
|
||||
|
||||
/*
|
||||
* step 2 - wait for children asleep to be cleared
|
||||
*/
|
||||
while ((gicrRD->GICR_WAKER & gicrwaker_ChildrenAsleep) != 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* OK, GICR is go
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
void EnablePrivateInt(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
id &= 0x1f;
|
||||
|
||||
gicrSGI->GICR_ISENABLER = 1 << id;
|
||||
}
|
||||
|
||||
void DisablePrivateInt(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
id &= 0x1f;
|
||||
|
||||
gicrSGI->GICR_ICENABLER = 1 << id;
|
||||
}
|
||||
|
||||
void SetPrivateIntPriority(uint32_t gicr, uint32_t id, uint32_t priority)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICD_IPRIORITYR has one byte-wide entry per interrupt
|
||||
*/
|
||||
id &= RANGE_LIMIT(gicrSGI->GICR_IPRIORITYR);
|
||||
|
||||
gicrSGI->GICR_IPRIORITYR[id] = priority;
|
||||
}
|
||||
|
||||
uint32_t GetPrivateIntPriority(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICD_IPRIORITYR has one byte-wide entry per interrupt
|
||||
*/
|
||||
id &= RANGE_LIMIT(gicrSGI->GICR_IPRIORITYR);
|
||||
|
||||
return (uint32_t)(gicrSGI->GICR_IPRIORITYR[id]);
|
||||
}
|
||||
|
||||
void SetPrivateIntPending(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICR_ISPENDR is one 32-bit register
|
||||
*/
|
||||
id &= 0x1f;
|
||||
|
||||
gicrSGI->GICR_ISPENDR = 1 << id;
|
||||
}
|
||||
|
||||
void ClearPrivateIntPending(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICR_ICPENDR is one 32-bit register
|
||||
*/
|
||||
id &= 0x1f;
|
||||
|
||||
gicrSGI->GICR_ICPENDR = 1 << id;
|
||||
}
|
||||
|
||||
uint32_t GetPrivateIntPending(uint32_t gicr, uint32_t id)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
|
||||
/*
|
||||
* GICR_ISPENDR is one 32-bit register
|
||||
*/
|
||||
id &= 0x1f;
|
||||
|
||||
return (gicrSGI->GICR_ISPENDR >> id) & 0x01;
|
||||
}
|
||||
|
||||
void SetPrivateIntSecurity(uint32_t gicr, uint32_t id, GICIGROUPRBits_t group)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
uint32_t groupmod;
|
||||
|
||||
/*
|
||||
* GICR_IGROUPR0 is one 32-bit register
|
||||
*/
|
||||
id &= 0x1f;
|
||||
|
||||
/*
|
||||
* the single group argument is split into two separate
|
||||
* registers, so filter out and remove the (new to gicv3)
|
||||
* group modifier bit
|
||||
*/
|
||||
groupmod = (group >> 1) & 1;
|
||||
group &= 1;
|
||||
|
||||
/*
|
||||
* either set or clear the Group bit for the interrupt as appropriate
|
||||
*/
|
||||
if (group)
|
||||
gicrSGI->GICR_IGROUPR0 |= 1 << id;
|
||||
else
|
||||
gicrSGI->GICR_IGROUPR0 &= ~(1 << id);
|
||||
|
||||
/*
|
||||
* now deal with groupmod
|
||||
*/
|
||||
if (groupmod)
|
||||
gicrSGI->GICR_IGRPMODR0 |= 1 << id;
|
||||
else
|
||||
gicrSGI->GICR_IGRPMODR0 &= ~(1 << id);
|
||||
}
|
||||
|
||||
void SetPrivateIntSecurityBlock(uint32_t gicr, GICIGROUPRBits_t group)
|
||||
{
|
||||
GICv3_redistributor_SGI *const gicrSGI = getgicrSGI(gicr);
|
||||
const uint32_t nbits = (sizeof group * 8) - 1;
|
||||
uint32_t groupmod;
|
||||
|
||||
/*
|
||||
* get each bit of group config duplicated over all 32-bits
|
||||
*/
|
||||
groupmod = (uint32_t)(((int32_t)group << (nbits - 1)) >> 31);
|
||||
group = (uint32_t)(((int32_t)group << nbits) >> 31);
|
||||
|
||||
/*
|
||||
* set the security state for this block of SPIs
|
||||
*/
|
||||
gicrSGI->GICR_IGROUPR0 = group;
|
||||
gicrSGI->GICR_IGRPMODR0 = groupmod;
|
||||
}
|
||||
|
||||
/* EOF GICv3_gicr.c */
|
||||
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// Armv8-A AArch64 - Basic Mutex Example
|
||||
// Includes the option (USE_LSE_ATOMIC) to use Large System Extension (LSE) atomics introduced in Armv8.1-A
|
||||
//
|
||||
// Copyright (c) 2012-2019 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
|
||||
.text
|
||||
.cfi_sections .debug_frame // put stack frame info into .debug_frame instead of .eh_frame
|
||||
|
||||
|
||||
.global _mutex_initialize
|
||||
.global _mutex_acquire
|
||||
.global _mutex_release
|
||||
|
||||
//
|
||||
// These routines implement the mutex management functions required for running
|
||||
// the Arm C library in a multi-threaded environment.
|
||||
//
|
||||
// They use a value of 0 to represent an unlocked mutex, and 1 for a locked mutex
|
||||
//
|
||||
// **********************************************************************
|
||||
//
|
||||
|
||||
.type _mutex_initialize, "function"
|
||||
.cfi_startproc
|
||||
_mutex_initialize:
|
||||
|
||||
//
|
||||
// mark the mutex as unlocked
|
||||
//
|
||||
mov w1, #0
|
||||
str w1, [x0]
|
||||
|
||||
//
|
||||
// we are running multi-threaded, so set a non-zero return
|
||||
// value (function prototype says use 1)
|
||||
//
|
||||
mov w0, #1
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
#if !defined(USE_LSE_ATOMIC)
|
||||
|
||||
.type _mutex_acquire, "function"
|
||||
.cfi_startproc
|
||||
_mutex_acquire:
|
||||
|
||||
//
|
||||
// send ourselves an event, so we don't stick on the wfe at the
|
||||
// top of the loop
|
||||
//
|
||||
sevl
|
||||
|
||||
//
|
||||
// wait until the mutex is available
|
||||
//
|
||||
loop:
|
||||
wfe
|
||||
ldaxr w1, [x0]
|
||||
cbnz w1, loop
|
||||
|
||||
//
|
||||
// mutex is (at least, it was) available - try to claim it
|
||||
//
|
||||
mov w1, #1
|
||||
stxr w2, w1, [x0]
|
||||
cbnz w2, loop
|
||||
|
||||
//
|
||||
// OK, we have the mutex, our work is done here
|
||||
//
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
.type _mutex_release, "function"
|
||||
.cfi_startproc
|
||||
_mutex_release:
|
||||
|
||||
mov w1, #0
|
||||
stlr w1, [x0]
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
#else // LSE version
|
||||
|
||||
.type _mutex_acquire, "function"
|
||||
.cfi_startproc
|
||||
_mutex_acquire:
|
||||
// This uses a "ticket lock". The lock is stored as a 32-bit value:
|
||||
// - the upper 16-bits record the thread's ticket number ("take a ticket")
|
||||
// - the lower 16-bits record the ticket being served ("now serving")
|
||||
|
||||
// atomically load then increment the thread's ticket number ("take a ticket")
|
||||
mov w3, #(1 << 16)
|
||||
ldadda w3, w1, [x0]
|
||||
|
||||
// is the ticket now being served?
|
||||
eor w2, w1, w1, ror #16
|
||||
cbz w2, loop_exit
|
||||
|
||||
// no, so wait for the ticket to be served
|
||||
|
||||
// send a local event to avoid missing an unlock before the exclusive load
|
||||
sevl
|
||||
|
||||
loop:
|
||||
wfe
|
||||
ldaxrh w3, [x0]
|
||||
eor w2, w3, w1, lsr #16
|
||||
cbnz w2, loop
|
||||
|
||||
//
|
||||
// OK, we have the mutex, our work is done here
|
||||
//
|
||||
loop_exit:
|
||||
ret
|
||||
.cfi_endproc
|
||||
|
||||
|
||||
.type _mutex_release, "function"
|
||||
.cfi_startproc
|
||||
_mutex_release:
|
||||
mov w1, #1
|
||||
staddlh w1, [x0]
|
||||
ret
|
||||
.cfi_endproc
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Armv8-A AArch64 - Basic Mutex Example
|
||||
*
|
||||
* Copyright (c) 2012-2014 Arm Limited (or its affiliates). All rights reserved.
|
||||
* Use, modification and redistribution of this file is subject to your possession of a
|
||||
* valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
* and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
*/
|
||||
#ifndef MP_MUTEX_H
|
||||
#define MP_MUTEX_H
|
||||
|
||||
/*
|
||||
* The Arm C library calls-out to these functions to manage multithreading.
|
||||
* They can also be called by user application code.
|
||||
*
|
||||
* Mutex type is specified by the Arm C library
|
||||
*
|
||||
* Declare function prototypes for libc mutex routines
|
||||
*/
|
||||
typedef signed int *mutex;
|
||||
|
||||
/*
|
||||
* int _mutex_initialize(mutex *m)
|
||||
*
|
||||
* Inputs
|
||||
* mutex *m - pointer to the 32-bit word associated with the mutex
|
||||
*
|
||||
* Returns
|
||||
* 0 - application is non-threaded
|
||||
* 1 - application is threaded
|
||||
* The C library uses the return result to indicate whether it is being used in a multithreaded environment.
|
||||
*/
|
||||
int _mutex_initialize(mutex *m);
|
||||
|
||||
/*
|
||||
* void _mutex_acquire(mutex *m)
|
||||
*
|
||||
* Inputs
|
||||
* mutex *m - pointer to the 32-bit word associated with the mutex
|
||||
*
|
||||
* Returns
|
||||
* <nothing>
|
||||
*
|
||||
* Side Effects
|
||||
* Routine does not return until the mutex has been claimed. A load-acquire
|
||||
* is used to guarantee that the mutex claim is properly ordered with
|
||||
* respect to any accesses to the resource protected by the mutex
|
||||
*/
|
||||
void _mutex_acquire(mutex *m);
|
||||
|
||||
/*
|
||||
* void _mutex_release(mutex *m)
|
||||
*
|
||||
* Inputs
|
||||
* mutex *m - pointer to the 32-bit word associated with the mutex
|
||||
*
|
||||
* Returns
|
||||
* <nothing>
|
||||
*
|
||||
* Side Effects
|
||||
* A store-release is used to guarantee that the mutex release is properly
|
||||
* ordered with respect any accesses to the resource protected by the mutex
|
||||
*/
|
||||
void _mutex_release(mutex *m);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// Private Peripheral Map for the v8 Architecture Envelope Model
|
||||
//
|
||||
// Copyright (c) 2012-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
//
|
||||
|
||||
#ifndef PPM_AEM_H
|
||||
#define PPM_AEM_H
|
||||
|
||||
//
|
||||
// Distributor layout
|
||||
//
|
||||
#define GICD_CTLR 0x0000
|
||||
#define GICD_TYPER 0x0004
|
||||
#define GICD_IIDR 0x0008
|
||||
#define GICD_IGROUP 0x0080
|
||||
#define GICD_ISENABLE 0x0100
|
||||
#define GICD_ICENABLE 0x0180
|
||||
#define GICD_ISPEND 0x0200
|
||||
#define GICD_ICPEND 0x0280
|
||||
#define GICD_ISACTIVE 0x0300
|
||||
#define GICD_ICACTIVE 0x0380
|
||||
#define GICD_IPRIORITY 0x0400
|
||||
#define GICD_ITARGETS 0x0800
|
||||
#define GICD_ICFG 0x0c00
|
||||
#define GICD_PPISR 0x0d00
|
||||
#define GICD_SPISR 0x0d04
|
||||
#define GICD_SGIR 0x0f00
|
||||
#define GICD_CPENDSGI 0x0f10
|
||||
#define GICD_SPENDSGI 0x0f20
|
||||
#define GICD_PIDR4 0x0fd0
|
||||
#define GICD_PIDR5 0x0fd4
|
||||
#define GICD_PIDR6 0x0fd8
|
||||
#define GICD_PIDR7 0x0fdc
|
||||
#define GICD_PIDR0 0x0fe0
|
||||
#define GICD_PIDR1 0x0fe4
|
||||
#define GICD_PIDR2 0x0fe8
|
||||
#define GICD_PIDR3 0x0fec
|
||||
#define GICD_CIDR0 0x0ff0
|
||||
#define GICD_CIDR1 0x0ff4
|
||||
#define GICD_CIDR2 0x0ff8
|
||||
#define GICD_CIDR3 0x0ffc
|
||||
|
||||
//
|
||||
// CPU Interface layout
|
||||
//
|
||||
#define GICC_CTLR 0x0000
|
||||
#define GICC_PMR 0x0004
|
||||
#define GICC_BPR 0x0008
|
||||
#define GICC_IAR 0x000c
|
||||
#define GICC_EOIR 0x0010
|
||||
#define GICC_RPR 0x0014
|
||||
#define GICC_HPPIR 0x0018
|
||||
#define GICC_ABPR 0x001c
|
||||
#define GICC_AIAR 0x0020
|
||||
#define GICC_AEOIR 0x0024
|
||||
#define GICC_AHPPIR 0x0028
|
||||
#define GICC_APR0 0x00d0
|
||||
#define GICC_NSAPR0 0x00e0
|
||||
#define GICC_IIDR 0x00fc
|
||||
#define GICC_DIR 0x1000
|
||||
|
||||
#endif // PPM_AEM_H
|
||||
@@ -0,0 +1,413 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="com.arm.debugger.launcher2">
|
||||
<stringAttribute key="ANDROID_ACTIVITY_NAME" value=""/>
|
||||
<stringAttribute key="ANDROID_APPLICATION" value=""/>
|
||||
<stringAttribute key="ANDROID_APP_DIR" value=""/>
|
||||
<stringAttribute key="ANDROID_PROCESS_NAME" value=""/>
|
||||
<mapAttribute key="AverageDurationTracker">
|
||||
<mapEntry key="*Fetching Data" value="34126331"/>
|
||||
<mapEntry key="*Fetching Data Model" value="1887986"/>
|
||||
<mapEntry key="*FunctionLoader" value="137168653"/>
|
||||
<mapEntry key="*list global low level symbols" value="3163826"/>
|
||||
<mapEntry key="*loading memory from target" value="2367919"/>
|
||||
<mapEntry key="*loading values from target" value="8665557"/>
|
||||
<mapEntry key="*trace" value="1527238"/>
|
||||
<mapEntry key="*updating expressions" value="25251903"/>
|
||||
<mapEntry key="*updating local_variables" value="836905"/>
|
||||
<mapEntry key="*updating registers" value="97090462"/>
|
||||
<mapEntry key="*updating variables" value="877039"/>
|
||||
<mapEntry key="AddEventObserver" value="5292071"/>
|
||||
<mapEntry key="Evaluate" value="1689813"/>
|
||||
<mapEntry key="ResumeToHere" value="20159012"/>
|
||||
<mapEntry key="Retrieving globals list" value="21298708"/>
|
||||
<mapEntry key="areCachesAvailable" value="474743"/>
|
||||
<mapEntry key="backtrace" value="21505977"/>
|
||||
<mapEntry key="break" value="9764564"/>
|
||||
<mapEntry key="checking tracepoints" value="372731"/>
|
||||
<mapEntry key="compute execution mode" value="835755"/>
|
||||
<mapEntry key="console" value="11946310"/>
|
||||
<mapEntry key="continue" value="21247618"/>
|
||||
<mapEntry key="core" value="5451456"/>
|
||||
<mapEntry key="directory" value="4479981"/>
|
||||
<mapEntry key="disable" value="2444670"/>
|
||||
<mapEntry key="disassemble" value="64135505"/>
|
||||
<mapEntry key="enable" value="5445745"/>
|
||||
<mapEntry key="evaluate" value="5333036"/>
|
||||
<mapEntry key="evaluate address" value="1056014"/>
|
||||
<mapEntry key="finish" value="20115248"/>
|
||||
<mapEntry key="get byte order" value="633302"/>
|
||||
<mapEntry key="get capabilities" value="382078"/>
|
||||
<mapEntry key="get execution addresss" value="403253"/>
|
||||
<mapEntry key="get source lines" value="951928"/>
|
||||
<mapEntry key="get substitute paths" value="523052"/>
|
||||
<mapEntry key="getValidEncodings" value="1202320"/>
|
||||
<mapEntry key="initialize command help" value="63855085"/>
|
||||
<mapEntry key="interrupt" value="11210435"/>
|
||||
<mapEntry key="list breakpoint options" value="2030851"/>
|
||||
<mapEntry key="list breakpoints" value="1627224"/>
|
||||
<mapEntry key="list instruction sets" value="1847125"/>
|
||||
<mapEntry key="list signals" value="1953020"/>
|
||||
<mapEntry key="list source files" value="573423"/>
|
||||
<mapEntry key="list watchpoint options" value="6057468"/>
|
||||
<mapEntry key="list watchpoints" value="970059"/>
|
||||
<mapEntry key="loadfile" value="386648009"/>
|
||||
<mapEntry key="next" value="24266800"/>
|
||||
<mapEntry key="query supports threads" value="215433"/>
|
||||
<mapEntry key="remove" value="7663692"/>
|
||||
<mapEntry key="run script" value="44460661"/>
|
||||
<mapEntry key="set CWD" value="5180571"/>
|
||||
<mapEntry key="set breakpoint properties" value="10666013"/>
|
||||
<mapEntry key="set debug-from" value="1157012"/>
|
||||
<mapEntry key="set substitute-path" value="27245163"/>
|
||||
<mapEntry key="source use_model_semihosting.ds" value="8849881"/>
|
||||
<mapEntry key="start" value="50528177"/>
|
||||
<mapEntry key="step" value="26461127"/>
|
||||
<mapEntry key="stepi" value="29574773"/>
|
||||
<mapEntry key="synchronizing trace ranges" value="21582"/>
|
||||
<mapEntry key="target reset" value="32992642"/>
|
||||
<mapEntry key="toggleBreakpoint" value="19462208"/>
|
||||
<mapEntry key="updateBreakpointLocation" value="1868000"/>
|
||||
<mapEntry key="waitForTargetToStop" value="52570549"/>
|
||||
<mapEntry key="write expression" value="21220700"/>
|
||||
</mapAttribute>
|
||||
<stringAttribute key="CLOCK_SPEED" value="Auto"/>
|
||||
<listAttribute key="DEBUG_TAB."/>
|
||||
<stringAttribute key="DEBUG_TAB..RESOURCES.0.TYPE" value="SOURCE_DIR"/>
|
||||
<stringAttribute key="DEBUG_TAB..RESOURCES.0.VALUE" value="${workspace_loc:/sample_threadx}"/>
|
||||
<stringAttribute key="DEBUG_TAB..RESOURCES.1.TYPE" value="SOURCE_DIR"/>
|
||||
<stringAttribute key="DEBUG_TAB..RESOURCES.1.VALUE" value="${workspace_loc:/tx}"/>
|
||||
<intAttribute key="DEBUG_TAB..RESOURCES.COUNT" value="2"/>
|
||||
<booleanAttribute key="EVENT_VIEWER_ENABLED" value="false"/>
|
||||
<stringAttribute key="EVENT_VIEWER_MAX_DEPTH" value="1Mb"/>
|
||||
<stringAttribute key="EVENT_VIEWER_MAX_DEPTH_NUMBER" value="1048576"/>
|
||||
<booleanAttribute key="EVENT_VIEWER_STM_ENABLED" value="false"/>
|
||||
<stringAttribute key="EVENT_VIEWER_STM_MAX_DEPTH" value=""/>
|
||||
<stringAttribute key="EVENT_VIEWER_STM_MAX_DEPTH_NUMBER" value="0"/>
|
||||
<intAttribute key="FILES.CONNECT_TO_GDB_SERVER.RESOURCES.COUNT" value="0"/>
|
||||
<intAttribute key="FILES.DEBUG_EXISTING_ANDROID.RESOURCES.COUNT" value="0"/>
|
||||
<listAttribute key="FILES.DEBUG_RESIDENT_ANDROID"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.0.TYPE" value="TARGET_WORKING_DIR"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.0.VALUE" value=""/>
|
||||
<intAttribute key="FILES.DEBUG_RESIDENT_ANDROID.RESOURCES.COUNT" value="1"/>
|
||||
<listAttribute key="FILES.DEBUG_RESIDENT_APP"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.0.TYPE" value="APPLICATION_ON_TARGET"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.0.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.1.TYPE" value="TARGET_WORKING_DIR"/>
|
||||
<stringAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.1.VALUE" value=""/>
|
||||
<intAttribute key="FILES.DEBUG_RESIDENT_APP.RESOURCES.COUNT" value="2"/>
|
||||
<listAttribute key="FILES.DOWNLOAD_AND_DEBUG"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="false"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.TYPE" value="TARGET_DOWNLOAD_DIR"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.0.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.OPTION.ALSO_LOAD_SYMBOLS" value="false"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.1.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.OPTION.ALSO_LOAD_SYMBOLS" value="false"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.TYPE" value="TARGET_WORKING_DIR"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.2.VALUE" value=""/>
|
||||
<intAttribute key="FILES.DOWNLOAD_AND_DEBUG.RESOURCES.COUNT" value="3"/>
|
||||
<listAttribute key="FILES.DOWNLOAD_DEBUG"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="false"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.TYPE" value="TARGET_DOWNLOAD_DIR"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.0.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.OPTION.ALSO_LOAD_SYMBOLS" value="false"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.1.VALUE" value=""/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.OPTION.ALSO_LOAD_SYMBOLS" value="false"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.TYPE" value="TARGET_WORKING_DIR"/>
|
||||
<stringAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.2.VALUE" value=""/>
|
||||
<intAttribute key="FILES.DOWNLOAD_DEBUG.RESOURCES.COUNT" value="3"/>
|
||||
<intAttribute key="FILES.DOWNLOAD_DEBUG_ANDROID.RESOURCES.COUNT" value="0"/>
|
||||
<listAttribute key="FILES.ICE_DEBUG">
|
||||
<listEntry value="ON_DEMAND_LOAD"/>
|
||||
<listEntry value="ALSO_LOAD_SYMBOLS"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG.RESOURCES.0.VALUE" value="${workspace_loc:/sample_threadx/Debug/sample_threadx.axf}"/>
|
||||
<intAttribute key="FILES.ICE_DEBUG.RESOURCES.COUNT" value="1"/>
|
||||
<listAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE">
|
||||
<listEntry value="ON_DEMAND_LOAD"/>
|
||||
<listEntry value="ALSO_LOAD_SYMBOLS"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="false"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.0.VALUE" value=""/>
|
||||
<intAttribute key="FILES.ICE_DEBUG_WITH_ETB_TRACE.RESOURCES.COUNT" value="1"/>
|
||||
<listAttribute key="FILES.ICE_DEBUG_WITH_TRACE">
|
||||
<listEntry value="ON_DEMAND_LOAD"/>
|
||||
<listEntry value="ALSO_LOAD_SYMBOLS"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.OPTION.ALSO_LOAD_SYMBOLS" value="false"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.OPTION.ON_DEMAND_LOAD" value="true"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.TYPE" value="APP_ON_HOST_TO_DOWNLOAD"/>
|
||||
<stringAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.0.VALUE" value=""/>
|
||||
<intAttribute key="FILES.ICE_DEBUG_WITH_TRACE.RESOURCES.COUNT" value="1"/>
|
||||
<stringAttribute key="FILES.SELECTED_DEBUG_OPEATION" value="ICE_DEBUG"/>
|
||||
<stringAttribute key="HOST_WORKING_DIR" value="${workspace_loc}"/>
|
||||
<booleanAttribute key="HOST_WORKING_DIR_USE_DEFAULT" value="true"/>
|
||||
<listAttribute key="ITM_CHANNEL_LIST"/>
|
||||
<booleanAttribute key="KEY_COMMANDS_AFTER_CONNECT" value="true"/>
|
||||
<stringAttribute key="KEY_COMMANDS_AFTER_CONNECT_TEXT" value="add-symbol-file "${workspace_loc:/sample_threadx/Debug/sample_threadx.axf}" EL1N:0 "/>
|
||||
<booleanAttribute key="KEY_COMMANDS_AS_CONNECT" value="false"/>
|
||||
<intAttribute key="Messages.POST_TRIGGER_CAPTURE_SIZE.getLocalisedValue().FMTrace" value="50"/>
|
||||
<booleanAttribute key="Messages.STOP_ON_TRIGGER.getLocalisedValue().FMTrace" value="false"/>
|
||||
<intAttribute key="POST_TRIGGER_CAPTURE_SIZE" value="50"/>
|
||||
<booleanAttribute key="RSE_USE_HOSTNAME" value="true"/>
|
||||
<booleanAttribute key="STOP_ON_TRIGGER" value="false"/>
|
||||
<booleanAttribute key="SWD" value="false"/>
|
||||
<booleanAttribute key="SWJ" value="true"/>
|
||||
<stringAttribute key="TCP_DISABLE_EXTENDED_MODE" value="true"/>
|
||||
<booleanAttribute key="TCP_KILL_ON_EXIT" value="false"/>
|
||||
<listAttribute key="TREE_NODE_PROPERTIES:debugger.view.ExpressionsView">
|
||||
<listEntry value="NODE CACHE VERSION 1"/>
|
||||
<listEntry value="VALUE:error_status"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
<listEntry value="VALUE:_tx_thread_system_stack_ptr"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="element formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
<listEntry value="EXPRESSION_GROUP:Expressions:VALUE:byte_pool_0:VALUE:(byte_pool_0).tx_byte_pool_available"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
<listEntry value="EXPRESSION_GROUP:Expressions:VALUE:byte_pool_0:VALUE:(byte_pool_0).tx_byte_pool_size"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
<listEntry value="EXPRESSION_GROUP:Expressions:VALUE:byte_pool_0:VALUE:(byte_pool_0).tx_byte_pool_list"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
<listEntry value="EXPRESSION_GROUP:Expressions:VALUE:byte_pool_0:VALUE:(byte_pool_0).tx_byte_pool_search"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
<listEntry value="EXPRESSION_GROUP:Expressions:VALUE:byte_pool_0:VALUE:(byte_pool_0).tx_byte_pool_start"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
<listEntry value="EXPRESSION_GROUP:Expressions:VALUE:_tx_thread_current_ptr"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="element formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
<listEntry value="EXPRESSION_GROUP:Expressions:VALUE:_tx_thread_execute_ptr"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="element formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
<listEntry value="VALUE:_tx_thread_current_ptr"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="element formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
<listEntry value="VALUE:_tx_thread_execute_ptr"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="element formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="TREE_NODE_PROPERTIES:debugger.view.VariableTreeView">
|
||||
<listEntry value="NODE CACHE VERSION 1"/>
|
||||
<listEntry value="LOCALS:Locals:VALUE:B:/support/broadcom/tx58cortexa53arm/release/threadx/tx/tx_thread_system_suspend.c::_tx_thread_system_suspend::possible_cores"/>
|
||||
<listEntry value="1"/>
|
||||
<listEntry value="formatter"/>
|
||||
<listEntry value="Hexadecimal"/>
|
||||
</listAttribute>
|
||||
<booleanAttribute key="VFS_ENABLED" value="true"/>
|
||||
<stringAttribute key="VFS_LOCAL_DIR" value="${workspace_loc}"/>
|
||||
<stringAttribute key="VFS_REMOTE_MOUNT" value="/writeable"/>
|
||||
<stringAttribute key="breakpoints" value="<?xml version="1.0" encoding="UTF-8"?> <breakpoints order="ALPHA"> 	<breakpoint ignorecount="0" threadenabled="no" core_list="" continue="no" verboseBreakpoints="yes" kind="SOURCEPOSITION"> 		<master_location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="0" enabled="true" version="2" address="EL3:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 		<location index="1" enabled="true" version="2" address="EL1N:0x000000008000B64C" debugFile="C:/Users/andrejm/work/git/AzureRTOS/threadx_andrejm_armv8a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.c" hostFile="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\sample_threadx.c" line="212" function="thread_0_entry"/> 	</breakpoint> </breakpoints> "/>
|
||||
<listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.addresses">
|
||||
<listEntry value=""/>
|
||||
<listEntry value="<Next Instruction>"/>
|
||||
<listEntry value="$pc"/>
|
||||
<listEntry value="0x8000986c"/>
|
||||
<listEntry value="$pc"/>
|
||||
<listEntry value="_tx_thread_system_suspend"/>
|
||||
<listEntry value="_tx_thread_system_suspend"/>
|
||||
<listEntry value="_tx_thread_schedule"/>
|
||||
<listEntry value="EL1N:_tx_thread_context_restore"/>
|
||||
<listEntry value="_tx_thread_context_restore"/>
|
||||
<listEntry value="thread_0_entry"/>
|
||||
<listEntry value="0x8000c2f8"/>
|
||||
<listEntry value="$pc"/>
|
||||
<listEntry value="0x80000000"/>
|
||||
<listEntry value="0x80000000"/>
|
||||
<listEntry value="0x80000000"/>
|
||||
<listEntry value="thread_1_entry"/>
|
||||
<listEntry value="EL1N:_tx_thread_schedule"/>
|
||||
<listEntry value="_tx_initialize_kernel_enter"/>
|
||||
<listEntry value="EL1N:thread_2_entry"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.DisassemblyView.ranges">
|
||||
<listEntry value=""/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="1000"/>
|
||||
<listEntry value="1000"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="300"/>
|
||||
<listEntry value="300"/>
|
||||
<listEntry value="256"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
<listEntry value="100"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.MemoryView.addresses">
|
||||
<listEntry value=""/>
|
||||
<listEntry value="0x2F000000"/>
|
||||
<listEntry value="0x8000fb00"/>
|
||||
<listEntry value="0x80030fb0"/>
|
||||
<listEntry value="0x80030f00"/>
|
||||
<listEntry value="$sp-256"/>
|
||||
<listEntry value="$sp"/>
|
||||
<listEntry value="0x8000fe00"/>
|
||||
<listEntry value="0x80011900"/>
|
||||
<listEntry value="0x8002f700"/>
|
||||
<listEntry value="&memory_area"/>
|
||||
<listEntry value="memory_area"/>
|
||||
<listEntry value="0x1c110000"/>
|
||||
<listEntry value="0x8000f800"/>
|
||||
<listEntry value="0x80000ed0"/>
|
||||
<listEntry value="0x80000ed4"/>
|
||||
<listEntry value="0x80000ec0"/>
|
||||
<listEntry value="0x80000ecc"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debug.views.common.AddressTracker.debugger.view.MemoryView.ranges">
|
||||
<listEntry value=""/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
<listEntry value="1024"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="com.arm.debug.views.debugConsole.DebugCommandLine.History" value="stepi;break -p EL1N:0x80000a14;break -p EL1N:0x80000790;break -p EL1N:__user_setup_stackheap;break -p EL1N:0x80000200;break -p EL1N:0x000000008000363C;break -p EL1N:0x0000000080003640;break -p EL1N:0x8000363c;break -p EL1N:0x8000bf7c;break -p EL1N:l64_fiq;break -p EL1N:0x80000500;break -p EL2N:0x800009f8;break - p EL1:0x800061a0;break -p EL1:0x800061a0;break -p EL1N:0x800061a0;break -p EL1N:0x8000bf10;break -p EL1N:0x8000bfc8;break -p EL1N:_tx_thread_context_restore+8;break -p EL1N:_tx_thread_schedule;break -p EL1N:0x0000000080000D84;break -p EL1S:0x0000000080000D84;break -p EL2N:0x0000000080000D84;break -p EL3N:0x0000000080000D84;break -p EL3:0x0000000080000D84;add-symbol-file sample_threadx.axf EL1N:0;add-symbol-file Debug\sample_threadx.axf EL1N:0;add-symbol-file sample_threadx\Debug\sample_threadx.axf EL1N:0;break -p EL1N:0x80009854;add-symbol-file sample_threadx\Debug\sample_threadx.axf EL1N:0"/>
|
||||
<listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.addresses">
|
||||
<listEntry value="<Next Instruction>"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="com.arm.debugger.views.common.AddressTracker.debugger.view.DisassemblyView.ranges">
|
||||
<listEntry value="100"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="config_db_activity_name" value="Cortex-A35x4 SMP"/>
|
||||
<stringAttribute key="config_db_connection_keys" value="dtsl_config dtsl_tracecapture_option connect_existing_model dtsl_config_script model_params model_iris config_file model_connection_address setup TCP_KILL_ON_EXIT TCP_DISABLE_EXTENDED_MODE"/>
|
||||
<stringAttribute key="config_db_connection_type" value="Bare Metal Debug"/>
|
||||
<stringAttribute key="config_db_platform_name" value="Arm FVP - Base_A35x4"/>
|
||||
<stringAttribute key="config_db_project_type" value="Bare Metal Debug"/>
|
||||
<stringAttribute key="config_db_project_type_id" value="BARE_METAL"/>
|
||||
<stringAttribute key="config_db_taxonomy_id" value="/platform/armfvp/base_a35x4"/>
|
||||
<stringAttribute key="config_file" value="CDB://iris_config.xml"/>
|
||||
<booleanAttribute key="connectOnly" value="false"/>
|
||||
<stringAttribute key="connect_existing_model" value="false"/>
|
||||
<stringAttribute key="debugger.view.DataView.os:DataView" value="rO0ABXNyACtjb20uYXJtLmRlYnVnLnZpZXdzLmRhdGEuRGF0YVZpZXdQcm9wZXJ0aWVzAAAAAAAAAAECAAB4cgAlY29tLmFybS5kZWJ1Zy52aWV3cy5kYXRhLlByb3BlcnR5VHJlZQAAAAAAAAABAwABTAAFbURhdGF0ABNMamF2YS91dGlsL0hhc2hNYXA7eHB3BAAAAAJ0ABJkYXRhYmFzZVByb3BlcnRpZXNzcQB+AAF3BAAAAAF0AAd0aHJlYWR4c3IAK2NvbS5hcm0uZGVidWcudmlld3MuZGF0YS5EYXRhYmFzZVByb3BlcnRpZXMAAAAAAAAAAQIAAHhxAH4AAXcEAAAAAnQAAmlkcQB+AAZ0AAxjdXJyZW50VGFibGV0AAd0aHJlYWRzeHh0AA9jdXJyZW50RGF0YWJhc2V0AAd0aHJlYWR4eA=="/>
|
||||
<listAttribute key="debugger.view.DisassemblyView:current">
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
</listAttribute>
|
||||
<listAttribute key="debugger.view.DisassemblyView:current:133102083840333696.viewid=2">
|
||||
<listEntry value="<Next Instruction>"/>
|
||||
<listEntry value="100"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="debugger.view.ExpressionsView">
|
||||
<listEntry value="thread_0_counter"/>
|
||||
<listEntry value="thread_1_counter"/>
|
||||
<listEntry value="thread_2_counter"/>
|
||||
<listEntry value="thread_3_counter"/>
|
||||
<listEntry value="thread_4_counter"/>
|
||||
<listEntry value="thread_5_counter"/>
|
||||
<listEntry value="thread_6_counter"/>
|
||||
<listEntry value="thread_7_counter"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="debugger.view.ExpressionsView.ExpressionTypes">
|
||||
<listEntry value="EXPRESSION_ERROR"/>
|
||||
<listEntry value="EXPRESSION_ERROR"/>
|
||||
<listEntry value="EXPRESSION_ERROR"/>
|
||||
<listEntry value="EXPRESSION_ERROR"/>
|
||||
<listEntry value="EXPRESSION_ERROR"/>
|
||||
<listEntry value="EXPRESSION_ERROR"/>
|
||||
<listEntry value="EXPRESSION_ERROR"/>
|
||||
<listEntry value="EXPRESSION_ERROR"/>
|
||||
<listEntry value=""/>
|
||||
</listAttribute>
|
||||
<mapAttribute key="debugger.view.ExpressionsView.ExpressionsData">
|
||||
<mapEntry key="0" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="1" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="2" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="3" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="4" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="5" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="6" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
<mapEntry key="7" value="NODE_TRANSFER_ELEMENT_COUNT,0;NODE_TRANSFER_ELEMENT_SIZE_IN_BYTES,4;NODE_TYPE,VALUE;FORMATTER,Unsigned Decimal"/>
|
||||
</mapAttribute>
|
||||
<stringAttribute key="debugger.view.ExpressionsView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	255	-1	true	1	false	true	127	-1	true	2	true	true	159	-1	true	3	true	true	75	-1	true	4	true	true	65	-1	true	5	true	true	48	-1	true	6	true	true	241	-1	true	7	true	true	69	-1	true"/>
|
||||
<stringAttribute key="debugger.view.MemoryView" value="<?xml version="1.0" encoding="UTF-8"?> <page> 	<memoryView/> </page> "/>
|
||||
<listAttribute key="debugger.view.MemoryView:current">
|
||||
<listEntry value=""/>
|
||||
<listEntry value=""/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="debugger.view.NewRegisterView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	49	-1	true	1	false	true	90	-1	true	2	true	true	45	-1	true	3	false	true	42	-1	true	4	false	true	50	-1	true	5	true	true	37	-1	true	6	false	true	62	-1	true	7	true	true	53	-1	true"/>
|
||||
<stringAttribute key="debugger.view.NewRegisterView:_selectedRegisterSet" value="All registers"/>
|
||||
<mapAttribute key="debugger.view.NewRegisterView_registerSets"/>
|
||||
<stringAttribute key="debugger.view.StackView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	49	-1	true	1	false	true	90	-1	true	2	true	true	45	-1	true	3	true	true	42	-1	true	4	true	true	50	-1	true	5	true	true	37	-1	true	6	true	true	62	-1	true	7	true	true	53	-1	true"/>
|
||||
<listAttribute key="debugger.view.TraceView:TRACE_EXPORT_FILTERS"/>
|
||||
<stringAttribute key="debugger.view.VariableTreeView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	149	-1	true	1	false	true	90	-1	true	2	true	true	95	-1	true	3	true	true	42	-1	true	4	true	true	50	-1	true	5	true	true	37	-1	true	6	true	true	62	-1	true	7	true	true	53	-1	true"/>
|
||||
<listAttribute key="debugger.view.VariableTreeView:USER_ADDED_FILE_STATICS"/>
|
||||
<listAttribute key="debugger.view.VariableTreeView:USER_ADDED_GLOBALS"/>
|
||||
<booleanAttribute key="debugger.view.expression.DrawAsHex" value="false"/>
|
||||
<booleanAttribute key="debugger.view.register.DrawAsHex" value="false"/>
|
||||
<stringAttribute key="debugger.view.symbols.FunctionsView:DebugOutlineColumnState" value="OutlineConfig1	8	0	true	true	53	-1	true	1	false	true	103	-1	true	2	false	true	90	-1	true	3	true	true	90	-1	true	4	true	true	86	-1	true	5	false	true	41	-1	true	6	true	true	112	-1	true	7	true	true	54	-1	true"/>
|
||||
<booleanAttribute key="debugger.view.variable.DrawAsHex" value="false"/>
|
||||
<stringAttribute key="dtsl_config" value="DtslScript"/>
|
||||
<stringAttribute key="dtsl_config_script" value="CDB://dtsl_config_script.py"/>
|
||||
<stringAttribute key="dtsl_options_file" value="default"/>
|
||||
<stringAttribute key="dtsl_tracecapture_option" value="options.trace.traceCapture"/>
|
||||
<booleanAttribute key="linuxOS" value="false"/>
|
||||
<stringAttribute key="model_connection_address" value="127.0.0.1:7100"/>
|
||||
<stringAttribute key="model_iris" value="1"/>
|
||||
<stringAttribute key="model_params" value="-C bp.secure_memory=false -C cache_state_modelled=0"/>
|
||||
<stringAttribute key="os_extension_id" value="com.arm.debug.os.threadx"/>
|
||||
<booleanAttribute key="runAfterConnect" value="false"/>
|
||||
<stringAttribute key="runTargetInitializationScript" value="${workspace_loc:/sample_threadx/use_model_semihosting.ds}"/>
|
||||
<mapAttribute key="scripts_view_script_links">
|
||||
<mapEntry key="B:\support\broadcom\a53smp_el1_clean_mar25\sample_threadx\use_model_semihosting.ds" value=""/>
|
||||
<mapEntry key="B:\support\broadcom\tx58cortexa53arm\release\threadx\sample_threadx\use_model_semihosting.ds" value=""/>
|
||||
<mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_andrejm_armv8a\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/>
|
||||
<mapEntry key="C:\Users\andrejm\work\git\AzureRTOS\threadx_other\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/>
|
||||
<mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx\ports_smp\cortex_a35_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/>
|
||||
<mapEntry key="C:\Users\nisohack\Documents\work\x-ware_libs\threadx_github\ports\cortex_a5x_smp\ac6\example_build\sample_threadx\use_model_semihosting.ds" value=""/>
|
||||
</mapAttribute>
|
||||
<listAttribute key="setup">
|
||||
<listEntry value="CDB://Scripts/rtsm_launcher.py"/>
|
||||
<listEntry value=""FVP_Base_Cortex-A35x4""/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="stopAtExpression" value="*$ENTRYPOINT"/>
|
||||
<stringAttribute key="substitutePath" value="<?xml version="1.0" encoding="UTF-8"?> <tuplelist> 	<tuple> 		<ta>C:/release/threadx/sample_threadx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> 	<tuple> 		<ta>C:/release/threadx/tx</ta> 		<tb>C:\release\threadx\sample_threadx\</tb> 	</tuple> </tuplelist> "/>
|
||||
<stringAttribute key="watchpoints" value="<?xml version="1.0" encoding="UTF-8"?> <watchpoints> </watchpoints> "/>
|
||||
</launchConfiguration>
|
||||
@@ -0,0 +1,262 @@
|
||||
;********************************************************
|
||||
; Scatter file for Armv8-A Startup code on FVP Base model
|
||||
; Copyright (c) 2014-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
; Use, modification and redistribution of this file is subject to your
|
||||
; possession of a valid DS-5 end user licence agreement and your compliance
|
||||
; with all applicable terms and conditions of such licence agreement.
|
||||
;********************************************************
|
||||
|
||||
LOAD 0x80000000
|
||||
{
|
||||
EXEC +0
|
||||
{
|
||||
startup.o (StartUp, +FIRST)
|
||||
* (+RO, +RW, +ZI)
|
||||
|
||||
}
|
||||
;XTABLES +0 ALIGN 0x1000
|
||||
;{
|
||||
; xtables.o (*)
|
||||
;}
|
||||
|
||||
SYS_STACK +0 ALIGN 8 EMPTY 0x1000
|
||||
{
|
||||
}
|
||||
|
||||
;
|
||||
; Separate heap - import symbol __use_two_region_memory
|
||||
; in source code for this to work correctly
|
||||
;
|
||||
ARM_LIB_HEAP +0 ALIGN 64 EMPTY 0xA0000 {}
|
||||
|
||||
;
|
||||
; App stacks for all CPUs
|
||||
; All stacks and heap are aligned to a cache-line boundary
|
||||
;
|
||||
ARM_LIB_STACK +0 ALIGN 64 EMPTY 4 * 0x4000 {}
|
||||
|
||||
;
|
||||
; Handler stacks for all CPUs
|
||||
; All stacks and heap are aligned to a cache-line boundary
|
||||
;
|
||||
HANDLER_STACK +0 ALIGN 64 EMPTY 4 * 0x4000 {}
|
||||
|
||||
;
|
||||
; Stacks for EL3
|
||||
;
|
||||
EL3_STACKS +0 ALIGN 64 EMPTY 4 * 0x1000 {}
|
||||
;
|
||||
; Strictly speaking, the L1 tables don't need to
|
||||
; be so strongly aligned, but no matter
|
||||
;
|
||||
TTB0_L1 +0 ALIGN 4096 EMPTY 0x1000 {}
|
||||
|
||||
;
|
||||
; Various sets of L2 tables
|
||||
;
|
||||
; Alignment is 4KB, since the code uses a 4K page
|
||||
; granularity - larger granularities would require
|
||||
; correspondingly stricter alignment
|
||||
;
|
||||
TTB0_L2_RAM +0 ALIGN 4096 EMPTY 0x1000 {}
|
||||
|
||||
TTB0_L2_PRIVATE +0 ALIGN 4096 EMPTY 0x1000 {}
|
||||
|
||||
TTB0_L2_PERIPH +0 ALIGN 4096 EMPTY 0x1000 {}
|
||||
|
||||
;
|
||||
; The startup code uses the end of this region to calculate
|
||||
; the top of memory - don't place any RAM regions after it
|
||||
;
|
||||
TOP_OF_RAM +0 EMPTY 4 {}
|
||||
|
||||
;
|
||||
; CS3 Peripherals is a 64MB region from 0x1c000000
|
||||
; that includes the following:
|
||||
; System Registers at 0x1C010000
|
||||
; UART0 (PL011) at 0x1C090000
|
||||
; Color LCD Controller (PL111) at 0x1C1F0000
|
||||
; plus a number of others.
|
||||
; CS3_PERIPHERALS is used by the startup code for page-table generation
|
||||
; This region is not truly empty, but we have no
|
||||
; predefined objects that live within it
|
||||
;
|
||||
CS3_PERIPHERALS 0x1c000000 EMPTY 0x90000 {}
|
||||
|
||||
;
|
||||
; Place the UART peripheral registers data structure
|
||||
; This is only really needed if USE_SERIAL_PORT is defined, but
|
||||
; the linker will remove unused sections if not needed
|
||||
; PL011 0x1c090000 UNINIT 0x1000
|
||||
; {
|
||||
; uart.o (+ZI)
|
||||
; }
|
||||
; Note that some other CS3_PERIPHERALS follow this
|
||||
|
||||
;
|
||||
; GICv3 distributor
|
||||
;
|
||||
GICD 0x2f000000 UNINIT 0x8000
|
||||
{
|
||||
GICv3_gicd.o (.bss.distributor)
|
||||
}
|
||||
|
||||
;
|
||||
; GICv3 redistributors
|
||||
; 128KB for each redistributor in the system
|
||||
;
|
||||
GICR 0x2f100000 UNINIT 0x80000
|
||||
{
|
||||
GICv3_gicr.o (.bss.redistributor)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions are met:
|
||||
;
|
||||
; Redistributions of source code must retain the above copyright notice, this
|
||||
; list of conditions and the following disclaimer.
|
||||
;
|
||||
; Redistributions in binary form must reproduce the above copyright notice,
|
||||
; this list of conditions and the following disclaimer in the documentation
|
||||
; and/or other materials provided with the distribution.
|
||||
;
|
||||
; Neither the name of ARM nor the names of its contributors may be used
|
||||
; to endorse or promote products derived from this software without specific
|
||||
; prior written permission.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
; POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
;RO AlignExpr(0x80000000, 0x1000)
|
||||
;{
|
||||
; C_SYNCH_SP0 +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_c_synch_sp0)
|
||||
; }
|
||||
; C_IRQ_SP0 +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_c_irq_sp0)
|
||||
; }
|
||||
; C_FIQ_SP0 +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_c_fiq_sp0)
|
||||
; }
|
||||
; C_SERROR_SP0 +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_c_serror_sp0)
|
||||
; }
|
||||
;
|
||||
; C_SYNCH_SPX +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_c_synch_spx)
|
||||
; }
|
||||
; C_IRQ_SPX +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_c_irq_spx)
|
||||
; }
|
||||
; C_FIQ_SPX +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_c_fiq_spx)
|
||||
; }
|
||||
; C_SERROR_SPX +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_c_serror_spx)
|
||||
; }
|
||||
;
|
||||
; L64_SYNCH +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_l64_synch)
|
||||
; }
|
||||
; L64_IRQ +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_l64_irq)
|
||||
; }
|
||||
; L64_FIQ +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_l64_fiq)
|
||||
; }
|
||||
; L64_SERROR +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_l64_serror)
|
||||
; }
|
||||
;
|
||||
; L32_SYNCH +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_l32_synch)
|
||||
; }
|
||||
; L32_IRQ +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_l32_irq)
|
||||
; }
|
||||
; L32_FIQ +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_l32_fiq)
|
||||
; }
|
||||
; L32_SERROR +0 ALIGN 0x80
|
||||
; {
|
||||
; vectors.o (_l32_serror)
|
||||
; }
|
||||
;
|
||||
; ROSEC +0 ALIGN 8
|
||||
; {
|
||||
; *( +RO )
|
||||
; }
|
||||
;
|
||||
; XTABLES +0 ALIGN 0x1000
|
||||
; {
|
||||
; xtables.o (*)
|
||||
; }
|
||||
;}
|
||||
;
|
||||
;RW AlignExpr(ImageLimit(XTABLES), 0x1000)
|
||||
;{
|
||||
; RWSEC +0
|
||||
; {
|
||||
; *( +RW )
|
||||
; }
|
||||
;
|
||||
; ZISEC +0
|
||||
; {
|
||||
; *( +ZI )
|
||||
; }
|
||||
;
|
||||
; SYS_STACK +0 ALIGN 8 EMPTY 0x1000
|
||||
; {
|
||||
; }
|
||||
;
|
||||
; ; 512 MiB heap
|
||||
; HEAP +0 ALIGN 8 EMPTY 0x10000000
|
||||
; {
|
||||
; }
|
||||
;
|
||||
; ; Free Memory section
|
||||
; FREE_MEMORY +0 ALIGN 8 EMPTY 0x10000000
|
||||
; {
|
||||
; }
|
||||
;
|
||||
; ; Per-CPU 128 MiB task stacks
|
||||
; TASK_STACKS +0 ALIGN 16 EMPTY (4 * 0x8000000)
|
||||
; {
|
||||
; }
|
||||
;
|
||||
; ; Per-CPU 128 MiB handler stacks
|
||||
; HANDLER_STACKS +0 ALIGN 16 EMPTY (4 * 0x8000000)
|
||||
; {
|
||||
; }
|
||||
;}
|
||||
@@ -0,0 +1,122 @@
|
||||
// ------------------------------------------------------------
|
||||
// SP804 Dual Timer
|
||||
//
|
||||
// Copyright (c) 2009-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#include "sp804_timer.h"
|
||||
|
||||
#define TIMER_SP804_CTRL_TIMEREN (1 << 7)
|
||||
#define TIMER_SP804_CTRL_TIMERMODE (1 << 6) // Bit 6:
|
||||
#define TIMER_SP804_CTRL_INTENABLE (1 << 5)
|
||||
#define TIMER_SP804_CTRL_TIMERSIZE (1 << 1) // Bit 1: 0=16-bit, 1=32-bit
|
||||
#define TIMER_SP804_CTRL_ONESHOT (1 << 0) // Bit 0: 0=wrapping, 1=one-shot
|
||||
|
||||
#define TIMER_SP804_CTRL_PRESCALE_1 (0 << 2) // clk/1
|
||||
#define TIMER_SP804_CTRL_PRESCALE_4 (1 << 2) // clk/4
|
||||
#define TIMER_SP804_CTRL_PRESCALE_8 (2 << 2) // clk/8
|
||||
|
||||
struct sp804_timer
|
||||
{
|
||||
volatile uint32_t Time1Load; // +0x00
|
||||
const volatile uint32_t Time1Value; // +0x04 - RO
|
||||
volatile uint32_t Timer1Control; // +0x08
|
||||
volatile uint32_t Timer1IntClr; // +0x0C - WO
|
||||
const volatile uint32_t Timer1RIS; // +0x10 - RO
|
||||
const volatile uint32_t Timer1MIS; // +0x14 - RO
|
||||
volatile uint32_t Timer1BGLoad; // +0x18
|
||||
|
||||
volatile uint32_t Time2Load; // +0x20
|
||||
volatile uint32_t Time2Value; // +0x24
|
||||
volatile uint8_t Timer2Control; // +0x28
|
||||
volatile uint32_t Timer2IntClr; // +0x2C - WO
|
||||
const volatile uint32_t Timer2RIS; // +0x30 - RO
|
||||
const volatile uint32_t Timer2MIS; // +0x34 - RO
|
||||
volatile uint32_t Timer2BGLoad; // +0x38
|
||||
|
||||
// Not including ID registers
|
||||
|
||||
};
|
||||
|
||||
// Instance of the dual timer, will be placed using the scatter file
|
||||
struct sp804_timer* dual_timer;
|
||||
|
||||
|
||||
// Set base address of timer
|
||||
// address - virtual address of SP804 timer
|
||||
void setTimerBaseAddress(uint64_t address)
|
||||
{
|
||||
dual_timer = (struct sp804_timer*)address;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Sets up the private timer
|
||||
// load_value - Initial value of timer
|
||||
// auto_reload - Periodic (SP804_AUTORELOAD) or one shot (SP804_SINGLESHOT)
|
||||
// interrupt - Whether to generate an interrupt
|
||||
void initTimer(uint32_t load_value, uint32_t auto_reload, uint32_t interrupt)
|
||||
{
|
||||
uint32_t tmp = 0;
|
||||
|
||||
dual_timer->Time1Load = load_value;
|
||||
|
||||
// Fixed setting: 32-bit, no prescaling
|
||||
tmp = TIMER_SP804_CTRL_TIMERSIZE | TIMER_SP804_CTRL_PRESCALE_1 | TIMER_SP804_CTRL_TIMERMODE;
|
||||
|
||||
// Settings from parameters: interrupt generation & reload
|
||||
tmp = tmp | interrupt | auto_reload;
|
||||
|
||||
// Write control register
|
||||
dual_timer->Timer1Control = tmp;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Starts the timer
|
||||
void startTimer(void)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = dual_timer->Timer1Control;
|
||||
tmp = tmp | TIMER_SP804_CTRL_TIMEREN; // Set TimerEn (bit 7)
|
||||
dual_timer->Timer1Control = tmp;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Stops the timer
|
||||
void stopTimer(void)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = dual_timer->Timer1Control;
|
||||
tmp = tmp & ~TIMER_SP804_CTRL_TIMEREN; // Clear TimerEn (bit 7)
|
||||
dual_timer->Timer1Control = tmp;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Returns the current timer count
|
||||
uint32_t getTimerCount(void)
|
||||
{
|
||||
return dual_timer->Time1Value;
|
||||
}
|
||||
|
||||
|
||||
void clearTimerIrq(void)
|
||||
{
|
||||
// A write to this register, of any value, clears the interrupt
|
||||
dual_timer->Timer1IntClr = 1;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// End of sp804_timer.c
|
||||
// ------------------------------------------------------------
|
||||
@@ -0,0 +1,53 @@
|
||||
// ------------------------------------------------------------
|
||||
// SP804 Dual Timer
|
||||
// Header Filer
|
||||
//
|
||||
// Copyright (c) 2009-2017 Arm Limited (or its affiliates). All rights reserved.
|
||||
// Use, modification and redistribution of this file is subject to your possession of a
|
||||
// valid End User License Agreement for the Arm Product of which these examples are part of
|
||||
// and your compliance with all applicable terms and conditions of such licence agreement.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#ifndef _SP804_TIMER_
|
||||
#define _SP804_TIMER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Set base address of timer
|
||||
// address - virtual address of SP804 timer
|
||||
void setTimerBaseAddress(uint64_t address);
|
||||
|
||||
|
||||
// Sets up the private timer
|
||||
// load_value - Initial value of timer
|
||||
// auto_reload - Periodic (SP804_AUTORELOAD) or one shot (SP804_SINGLESHOT)
|
||||
// interrupt - Whether to generate an interrupt
|
||||
|
||||
#define SP804_AUTORELOAD (0)
|
||||
#define SP804_SINGLESHOT (1)
|
||||
#define SP804_GENERATE_IRQ (1 << 5)
|
||||
#define SP804_NO_IRQ (0)
|
||||
|
||||
void initTimer(uint32_t load_value, uint32_t auto_reload, uint32_t interrupt);
|
||||
|
||||
|
||||
// Starts the timer
|
||||
void startTimer(void);
|
||||
|
||||
|
||||
// Stops the timer
|
||||
void stopTimer(void);
|
||||
|
||||
|
||||
// Returns the current timer count
|
||||
uint32_t getTimerCount(void);
|
||||
|
||||
|
||||
// Clears the timer interrupt
|
||||
void clearTimerIrq(void);
|
||||
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// End of sp804_timer.h
|
||||
// ------------------------------------------------------------
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user