mirror of
https://github.com/eclipse-threadx/threadx.git
synced 2026-08-17 17:43:54 +08:00
Fixed the issue of the data/bss section cannot be read from ARM FVP debug tool in cortex-A9 GNU port. (#303)
https://msazure.visualstudio.com/One/_workitems/edit/25153785/
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,120 @@
|
||||
// ------------------------------------------------------------
|
||||
// Cortex-A MPCore - Interrupt Controller functions
|
||||
// Header File
|
||||
//
|
||||
// Copyright (c) 2011-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.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#ifndef _CORTEXA_GIC_H
|
||||
#define _CORTEXA_GIC_H
|
||||
|
||||
#define SPURIOUS (255)
|
||||
|
||||
// PPI IDs:
|
||||
#define MPCORE_PPI_PRIVATE_TIMER (29)
|
||||
#define MPCORE_PPI_PRIVATE_WD (30)
|
||||
#define MPCORE_PPI_GLOBAL_TIMER (27)
|
||||
#define MPCORE_PPI_LEGACY_IRQ (31)
|
||||
#define MPCORE_PPI_LEGACY_FIQ (28)
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// GIC
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// Typical calls to enable interrupt ID X:
|
||||
// enableIntID(X) <-- Enable that ID
|
||||
// setIntPriority(X, 0) <-- Set the priority of X to 0 (the max priority)
|
||||
// setPriorityMask(0x1F) <-- Set Core's priority mask to 0x1F (the lowest priority)
|
||||
// enableGIC() <-- Enable the GIC (global)
|
||||
// enableGICProcessorInterface() <-- Enable the CPU interface (local to the core)
|
||||
//
|
||||
|
||||
|
||||
// Global enable of the Interrupt Distributor
|
||||
void enableGIC(void);
|
||||
|
||||
// Global disable of the Interrupt Distributor
|
||||
void disableGIC(void);
|
||||
|
||||
// Enables the interrupt source number ID
|
||||
void enableIntID(unsigned int ID);
|
||||
|
||||
// Disables the interrupt source number ID
|
||||
void disableIntID(unsigned int ID);
|
||||
|
||||
// Enables the processor interface
|
||||
// Must be done on each core separately
|
||||
void enableGICProcessorInterface(void);
|
||||
|
||||
// Disables the processor interface
|
||||
// Must be done on each core separately
|
||||
void disableGICProcessorInterface(void);
|
||||
|
||||
// Sets the Priority mask register for the core run on
|
||||
// The reset value masks ALL interrupts!
|
||||
//
|
||||
// NOTE: Bits 2:0 of this register are SBZ, the function does perform any shifting!
|
||||
void setPriorityMask(unsigned int priority);
|
||||
|
||||
// Sets the Binary Point Register for the core run on
|
||||
void setBinaryPoint(unsigned int priority);
|
||||
|
||||
// Sets the priority of the specified ID
|
||||
void setIntPriority(unsigned int ID, unsigned int priority);
|
||||
|
||||
// Returns the priority of the specified ID
|
||||
unsigned int getIntPriority(unsigned int ID, unsigned int priority);
|
||||
|
||||
#define MPCORE_IC_TARGET_NONE (0x0)
|
||||
#define MPCORE_IC_TARGET_CPU0 (0x1)
|
||||
#define MPCORE_IC_TARGET_CPU1 (0x2)
|
||||
#define MPCORE_IC_TARGET_CPU2 (0x4)
|
||||
#define MPCORE_IC_TARGET_CPU3 (0x8)
|
||||
|
||||
// Sets the target CPUs of the specified ID
|
||||
// For 'target' use one of the above defines
|
||||
void setIntTarget(unsigned int ID, unsigned int target);
|
||||
|
||||
// Returns the target CPUs of the specified ID
|
||||
unsigned int getIntTarget(unsigned int ID);
|
||||
|
||||
// Returns the value of the Interrupt Acknowledge Register
|
||||
unsigned int readIntAck(void);
|
||||
|
||||
// Writes ID to the End Of Interrupt register
|
||||
void writeEOI(unsigned int ID);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// SGI
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// Send a software generate interrupt
|
||||
void sendSGI(unsigned int ID, unsigned int core_list, unsigned int filter_list);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// TrustZone
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// Enables the sending of secure interrupts as FIQs
|
||||
void enableSecureFIQs(void);
|
||||
|
||||
// Disables the sending of secure interrupts as FIQs
|
||||
void disableSecureFIQs(void);
|
||||
|
||||
// Sets the specified ID as secure
|
||||
void makeIntSecure(unsigned int ID);
|
||||
|
||||
// Set the specified ID as non-secure
|
||||
void makeIntNonSecure(unsigned int ID);
|
||||
|
||||
// Returns the security of the specified ID
|
||||
unsigned int getIntSecurity(unsigned int ID);
|
||||
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// End of MP_GIC.h
|
||||
// ------------------------------------------------------------
|
||||
@@ -0,0 +1,118 @@
|
||||
// ------------------------------------------------------------
|
||||
// Cortex-A MPCore - Private timer functions
|
||||
//
|
||||
// Copyright ARM Ltd 2009. All rights reserved.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
.text
|
||||
.align 4
|
||||
|
||||
// PPI ID 29
|
||||
|
||||
|
||||
// Typical set of calls to enable Timer:
|
||||
// init_private_timer(0xXXXX, 0) <-- Counter down value of 0xXXXX, with auto-reload
|
||||
// start_private_timer()
|
||||
|
||||
// Timer offset from base of private peripheral space --> 0x600
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
.global init_private_timer
|
||||
.type init_private_timer,function
|
||||
// void init_private_timer(unsigned int load_value, unsigned int auto_reload)
|
||||
// Sets up the private timer
|
||||
// r0: initial load value
|
||||
// r1: IF 0 (AutoReload) ELSE (SingleShot)
|
||||
init_private_timer:
|
||||
|
||||
// Get base address of private perpherial space
|
||||
MOV r2, r0 // Make a copy of r0 before corrupting
|
||||
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
|
||||
|
||||
// Set the load value
|
||||
STR r2, [r0, #0x600]
|
||||
|
||||
// Control register bit layout
|
||||
// Bit 0 - Enable
|
||||
// Bit 1 - Auto-Reload // see DE681117
|
||||
// Bit 2 - IRQ Generation
|
||||
|
||||
// Form control reg value
|
||||
CMP r1, #0 // Check whether to enable auto-reload
|
||||
MOVNE r2, #0x04 // No auto-reload
|
||||
MOVEQ r2, #0x06 // With auto-reload
|
||||
|
||||
// Store to control register
|
||||
STR r2, [r0, #0x608]
|
||||
|
||||
BX lr
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// void start_private_timer(void)
|
||||
// Starts the private timer
|
||||
.global start_private_timer
|
||||
.type start_private_timer,function
|
||||
start_private_timer:
|
||||
|
||||
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
|
||||
|
||||
LDR r1, [r0, #0x608] // Read control reg
|
||||
ORR r1, r1, #0x01 // Set enable bit
|
||||
STR r1, [r0, #0x608] // Write modified value back
|
||||
|
||||
BX lr
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// void stop_private_timer(void)
|
||||
// Stops the private timer
|
||||
.global stop_private_timer
|
||||
.type stop_private_timer,function
|
||||
stop_private_timer:
|
||||
|
||||
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
|
||||
|
||||
LDR r1, [r0, #0x608] // Read control reg
|
||||
BIC r1, r1, #0x01 // Clear enable bit
|
||||
STR r1, [r0, #0x608] // Write modified value back
|
||||
|
||||
BX lr
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// unsigned int read_private_timer(void)
|
||||
// Reads the current value of the timer count register
|
||||
.global get_private_timer_count
|
||||
.type get_private_timer_count,function
|
||||
get_private_timer_count:
|
||||
|
||||
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
|
||||
|
||||
LDR r0, [r0, #0x604] // Read count register
|
||||
|
||||
BX lr
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// void clear_private_timer_irq(void)
|
||||
// Clears the private timer interrupt
|
||||
.global clear_private_timer_irq
|
||||
.type clear_private_timer_irq,function
|
||||
clear_private_timer_irq:
|
||||
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
|
||||
|
||||
// Clear the interrupt by writing 0x1 to the Timer's Interrupt Status register
|
||||
MOV r1, #1
|
||||
STR r1, [r0, #0x60C]
|
||||
|
||||
BX lr
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// End of code
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// End of MP_PrivateTimer.s
|
||||
// ------------------------------------------------------------
|
||||
@@ -0,0 +1,36 @@
|
||||
// ------------------------------------------------------------
|
||||
// Cortex-A MPCore - Private timer functions
|
||||
// Header Filer
|
||||
//
|
||||
// Copyright ARM Ltd 2009. All rights reserved.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#ifndef _CORTEXA_PRIVATE_TIMER_
|
||||
#define _CORTEXA_PRIVATE_TIMER_
|
||||
|
||||
// Typical set of calls to enable Timer:
|
||||
// init_private_timer(0xXXXX, 0) <-- Counter down value of 0xXXXX, with auto-reload
|
||||
// start_private_timer()
|
||||
|
||||
// Sets up the private timer
|
||||
// r0: initial load value
|
||||
// r1: IF 0 (AutoReload) ELSE (SingleShot)
|
||||
void init_private_timer(unsigned int load_value, unsigned int auto_reload);
|
||||
|
||||
// Starts the private timer
|
||||
void start_private_timer(void);
|
||||
|
||||
// Stops the private timer
|
||||
void stop_private_timer(void);
|
||||
|
||||
// Reads the current value of the timer count register
|
||||
unsigned int get_private_timer_count(void);
|
||||
|
||||
// Clears the private timer interrupt
|
||||
void clear_private_timer_irq(void);
|
||||
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// End of MP_PrivateTimer.h
|
||||
// ------------------------------------------------------------
|
||||
@@ -1,6 +1,8 @@
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-a9 reset.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-a9 crt0.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-a9 tx_initialize_low_level.S
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-a9 MP_GIC.s
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-a9 MP_PrivateTimer.s
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-a9 V7.s
|
||||
arm-none-eabi-gcc -c -g -mcpu=cortex-a9 -I../../../../common/inc -I../inc sample_threadx.c
|
||||
arm-none-eabi-gcc -g -mcpu=cortex-a8 -T sample_threadx.ld --specs=nosys.specs -o sample_threadx.out -Wl,-Map=sample_threadx.map tx_initialize_low_level.o sample_threadx.o tx.a
|
||||
|
||||
arm-none-eabi-gcc -g -nostartfiles -mcpu=cortex-a9 -T sample_threadx.ld --specs=nosys.specs -o sample_threadx.out -Wl,-Map=sample_threadx.map MP_GIC.o MP_PrivateTimer.o V7.o crt0.o reset.o tx_initialize_low_level.o sample_threadx.o tx.a
|
||||
|
||||
@@ -41,8 +41,13 @@ SYS_STACK_SIZE = 1024 // System stack size
|
||||
.global _end
|
||||
.global _sp
|
||||
.global _stack_bottom
|
||||
|
||||
|
||||
.global __vectors
|
||||
.global disableHighVecs
|
||||
.global enableGIC
|
||||
.global enableGICProcessorInterface
|
||||
.global enableCaches
|
||||
.global init_private_timer
|
||||
.global start_private_timer
|
||||
/* Define the 16-bit Thumb mode veneer for _tx_initialize_low_level for
|
||||
applications calling this function from to 16-bit Thumb mode. */
|
||||
|
||||
@@ -160,6 +165,57 @@ _stack_error_loop:
|
||||
ADD r1, r1, #8 // Increment to next free word
|
||||
STR r1, [r2] // Save first free memory address
|
||||
|
||||
PUSH {lr}
|
||||
|
||||
/* Setup the vector table. */
|
||||
LDR r0, =__vectors // Get address of vector table
|
||||
MCR p15, 0, r0, c12, c0, 0 // Write vector table address to CP15
|
||||
BL disableHighVecs // Disable high vectors
|
||||
|
||||
//
|
||||
// GIC Init
|
||||
// ---------
|
||||
BL enableGIC
|
||||
BL enableGICProcessorInterface
|
||||
|
||||
//
|
||||
// Enable Private Timer for periodic IRQ
|
||||
// --------------------------------------
|
||||
MOV r0, #0x1F
|
||||
BL setPriorityMask // Set priority mask (local)
|
||||
|
||||
// [EL] Change start - don't enable interrupts here!
|
||||
//CPSIE i // Clear CPSR I bit
|
||||
// [EL] Change end
|
||||
|
||||
// Enable the Private Timer Interrupt Source
|
||||
MOV r0, #29
|
||||
MOV r1, #0
|
||||
BL enableIntID
|
||||
|
||||
// Set the priority
|
||||
MOV r0, #29
|
||||
MOV r1, #0
|
||||
BL setIntPriority
|
||||
|
||||
// Configure Timer
|
||||
MOV r0, #0xF0000
|
||||
MOV r1, #0x0
|
||||
BL init_private_timer
|
||||
BL start_private_timer
|
||||
|
||||
//
|
||||
// Enable receipt of SGI 0
|
||||
// ------------------------
|
||||
MOV r0, #0x0 // ID
|
||||
BL enableIntID
|
||||
|
||||
// Set the priority
|
||||
MOV r0, #0x0 // ID
|
||||
MOV r1, #0x0 // Priority
|
||||
BL setIntPriority
|
||||
|
||||
POP {lr}
|
||||
#ifdef __THUMB_INTERWORK
|
||||
BX lr // Return to caller
|
||||
#else
|
||||
@@ -202,16 +258,16 @@ __tx_irq_processing_return:
|
||||
if nested IRQ interrupts are desired. Interrupts may be re-enabled over
|
||||
small code sequences where lr is saved before enabling interrupts and
|
||||
restored after interrupts are again disabled. */
|
||||
|
||||
PUSH {r4, r5} // Save some preserved registers (r5 is saved just for 8-byte alignment)
|
||||
BL readIntAck
|
||||
MOV r4, r0
|
||||
|
||||
/* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start
|
||||
from IRQ mode with interrupts disabled. This routine switches to the
|
||||
system mode and returns with IRQ interrupts enabled.
|
||||
CMP r0, #29 // If not Private Timer interrupt (ID 29), by pass
|
||||
BNE by_pass_timer_interrupt
|
||||
|
||||
NOTE: It is very important to ensure all IRQ interrupts are cleared
|
||||
prior to enabling nested IRQ interrupts. */
|
||||
#ifdef TX_ENABLE_IRQ_NESTING
|
||||
BL _tx_thread_irq_nesting_start
|
||||
#endif
|
||||
BL clear_private_timer_irq
|
||||
DSB
|
||||
|
||||
/* For debug purpose, execute the timer interrupt processing here. In
|
||||
a real system, some kind of status indication would have to be checked
|
||||
@@ -219,13 +275,10 @@ __tx_irq_processing_return:
|
||||
|
||||
BL _tx_timer_interrupt // Timer interrupt handler
|
||||
|
||||
|
||||
/* If interrupt nesting was started earlier, the end of interrupt nesting
|
||||
service must be called before returning to _tx_thread_context_restore.
|
||||
This routine returns in processing in IRQ mode with interrupts disabled. */
|
||||
#ifdef TX_ENABLE_IRQ_NESTING
|
||||
BL _tx_thread_irq_nesting_end
|
||||
#endif
|
||||
by_pass_timer_interrupt:
|
||||
MOV r0, r4
|
||||
BL writeEOI
|
||||
POP {r4, r5} // Recover preserved registers
|
||||
|
||||
/* Jump to context restore to restore system context. */
|
||||
B _tx_thread_context_restore
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
>output thread_0_counter
|
||||
2913840557
|
||||
10
|
||||
>output thread_1_counter
|
||||
2913840557
|
||||
599068
|
||||
>output thread_2_counter
|
||||
2913840557
|
||||
599046
|
||||
>output thread_3_counter
|
||||
2913840557
|
||||
23
|
||||
>output thread_4_counter
|
||||
2913840557
|
||||
23
|
||||
>output thread_5_counter
|
||||
2913840557
|
||||
9
|
||||
>output thread_6_counter
|
||||
2913840557
|
||||
23
|
||||
>output thread_7_counter
|
||||
2913840557
|
||||
23
|
||||
>log file
|
||||
Stopped duplicating logging output
|
||||
|
||||
Reference in New Issue
Block a user