Fixed the issue of the data/bss section cannot be read from ARM FVP debug tool in cortex-A8 GNU port. (#302)

https://msazure.visualstudio.com/One/_workitems/edit/25139203/
This commit is contained in:
Yajun Xia
2023-09-18 10:32:07 +08:00
committed by GitHub
parent 6aeefea8e6
commit a0a0ef9385
7 changed files with 557 additions and 27 deletions

View File

@@ -0,0 +1,74 @@
// ------------------------------------------------------------
// Cortex-A8 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_
#define _CORTEXA_GIC_
// ------------------------------------------------------------
// GIC
// ------------------------------------------------------------
// Typical calls to enable interrupt ID X:
// enable_irq_id(X) <-- Enable that ID
// set_irq_priority(X, 0) <-- Set the priority of X to 0 (the max priority)
// set_priority_mask(0x1F) <-- Set Core's priority mask to 0x1F (the lowest priority)
// enable_GIC() <-- Enable the GIC (global)
// enable_gic_processor_interface() <-- 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);
// Sets the priority of the specified ID
void setIntPriority(unsigned int ID, unsigned int priority);
// 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!
void setPriorityMask(unsigned int priority);
// Sets the Binary Point Register for the core run on
void setBinaryPoint(unsigned int priority);
// 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);
#endif
// ------------------------------------------------------------
// End of MP_GIC.h
// ------------------------------------------------------------

View File

@@ -0,0 +1,294 @@
//----------------------------------------------------------------
// Copyright (c) 2005-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.
//
// Cortex-A8MP example - Startup Code
//----------------------------------------------------------------
.text
//----------------------------------------------------------------
// GIC. Generic Interrupt Controller Architecture Specification
//----------------------------------------------------------------
// CPU Interface offset from base of private peripheral space --> 0x0100
// Interrupt Distributor offset from base of private peripheral space --> 0x1000
// 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 CPU's priority mask to 0x1F (the lowest priority)
// enableGIC() <-- Enable the GIC (global)
// enableGICProcessorInterface() <-- Enable the CPU interface (local to the CPU)
// void enableGIC(void)
// Global enable of the Interrupt Distributor
.global enableGIC
.type enableGIC,function
enableGIC:
// Get base address of private peripheral space
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
ADD r0, r0, #0x1000 // Add the GIC offset
LDR r1, [r0] // Read the GIC Enable Register (ICDDCR)
ORR r1, r1, #0x01 // Set bit 0, the enable bit
STR r1, [r0] // Write the GIC Enable Register (ICDDCR)
BX lr
// ------------------------------------------------------------
.global disableGIC
.type disableGIC,function
// void disableGIC(void)
// Global disable of the Interrupt Distributor
disableGIC:
// Get base address of private peripheral space
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
ADD r0, r0, #0x1000 // Add the GIC offset
LDR r1, [r0] // Read the GIC Enable Register (ICDDCR)
BIC r1, r1, #0x01 // Clear bit 0, the enable bit
STR r1, [r0] // Write the GIC Enable Register (ICDDCR)
BX lr
// ------------------------------------------------------------
.global enableIntID
.type enableIntID,function
// void enableIntID(unsigned int ID)
// Enables the interrupt source number ID
enableIntID:
// Get base address of private peripheral space
MOV r1, r0 // Back up passed in ID value
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
// Each interrupt source has an enable bit in the GIC. These
// are grouped into registers, with 32 sources per register
// First, we need to identify which 32-bit block the interrupt lives in
MOV r2, r1 // Make working copy of ID in r2
MOV r2, r2, LSR #5 // LSR by 5 places, affective divide by 32
// r2 now contains the 32-bit block this ID lives in
MOV r2, r2, LSL #2 // Now multiply by 4, to convert offset into an address offset (four bytes per reg)
// Now work out which bit within the 32-bit block the ID is
AND r1, r1, #0x1F // Mask off to give offset within 32-bit block
MOV r3, #1 // Move enable value into r3
MOV r3, r3, LSL r1 // Shift it left to position of ID
ADD r2, r2, #0x1100 // Add the base offset of the Enable Set registers to the offset for the ID
STR r3, [r0, r2] // Store out (ICDISER)
BX lr
// ------------------------------------------------------------
.global disableIntID
.type disableIntID,function
// void disableIntID(unsigned int ID)
// Disables the interrupt source number ID
disableIntID:
// Get base address of private peripheral space
MOV r1, r0 // Back up passed in ID value
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
// First, we need to identify which 32-bit block the interrupt lives in
MOV r2, r1 // Make working copy of ID in r2
MOV r2, r2, LSR #5 // LSR by 5 places, affective divide by 32
// r2 now contains the 32-bit block this ID lives in
MOV r2, r2, LSL #2 // Now multiply by 4, to convert offset into an address offset (four bytes per reg)
// Now work out which bit within the 32-bit block the ID is
AND r1, r1, #0x1F // Mask off to give offset within 32-bit block
MOV r3, #1 // Move enable value into r3
MOV r3, r3, LSL r1 // Shift it left to position of ID in 32-bit block
ADD r2, r2, #0x1180 // Add the base offset of the Enable Clear registers to the offset for the ID
STR r3, [r0, r2] // Store out (ICDICER)
BX lr
// ------------------------------------------------------------
.global setIntPriority
.type setIntPriority,function
// void setIntPriority(unsigned int ID, unsigned int priority)
// Sets the priority of the specified ID
// r0 = ID
// r1 = priority
setIntPriority:
// Get base address of private peripheral space
MOV r2, r0 // Back up passed in ID value
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
// r0 = base addr
// r1 = priority
// r2 = ID
// Make sure that priority value is only 5 bits, and convert to expected format
AND r1, r1, #0x1F
MOV r1, r1, LSL #3
// Find which register this ID lives in
BIC r3, r2, #0x03 // Make a copy of the ID, clearing off the bottom two bits
// There are four IDs per reg, by clearing the bottom two bits we get an address offset
ADD r3, r3, #0x1400 // Now add the offset of the Priority Level registers from the base of the private peripheral space
ADD r0, r0, r3 // Now add in the base address of the private peripheral space, giving us the absolute address
// Now work out which ID in the register it is
AND r2, r2, #0x03 // Clear all but the bottom two bits, leaves which ID in the reg it is (which byte)
MOV r2, r2, LSL #3 // Multiply by 8, this gives a bit offset
// Read -> Modify -> Write
MOV r12, #0xFF // 8 bit field mask
MOV r12, r12, LSL r2 // Move mask into correct bit position
MOV r1, r1, LSL r2 // Also, move passed in priority value into correct bit position
LDR r3, [r0] // Read current value of the Priority Level register (ICDIPR)
BIC r3, r3, r12 // Clear appropriate field
ORR r3, r3, r1 // Now OR in the priority value
STR r3, [r0] // And store it back again (ICDIPR)
BX lr
// ------------------------------------------------------------
.global enableGICProcessorInterface
.type enableGICProcessorInterface,function
// void enableGICProcessorInterface(void)
// Enables the processor interface
// Must be done on each core separately
enableGICProcessorInterface:
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
ADD r0, r0, #0x2000
LDR r1, [r0, #0x0] // Read the Processor Interface Control register (ICCICR/ICPICR)
ORR r1, r1, #0x03 // Bit 0: Enables secure interrupts, Bit 1: Enables Non-Secure interrupts
BIC r1, r1, #0x08 // Bit 3: Ensure Group 0 interrupts are signalled using IRQ, not FIQ
STR r1, [r0, #0x0] // Write the Processor Interface Control register (ICCICR/ICPICR)
BX lr
// ------------------------------------------------------------
.global disableGICProcessorInterface
.type disableGICProcessorInterface,function
// void disableGICProcessorInterface(void)
// Disables the processor interface
// Must be done on each core separately
disableGICProcessorInterface:
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
ADD r0, r0, #0x2000
LDR r1, [r0, #0x0] // Read the Processor Interface Control register (ICCICR/ICPICR)
BIC r1, r1, #0x03 // Bit 0: Enables secure interrupts, Bit 1: Enables Non-Secure interrupts
STR r1, [r0, #0x0] // Write the Processor Interface Control register (ICCICR/ICPICR)
BX lr
// ------------------------------------------------------------
.global setPriorityMask
.type setPriorityMask,function
// void setPriorityMask(unsigned int priority)
// Sets the Priority mask register for the CPU run on
// The reset value masks ALL interrupts!
setPriorityMask:
// Get base address of private peripheral space
MRC p15, 4, r1, c15, c0, 0 // Read periph base address
ADD r1, r1, #0x2000
STR r0, [r1, #0x4] // Write the Priority Mask register (ICCPMR/ICCIPMR)
BX lr
// ------------------------------------------------------------
.global setBinaryPoint
.type setBinaryPoint,function
// void setBinaryPoint(unsigned int priority)
// Sets the Binary Point Register for the CPU run on
setBinaryPoint:
// Get base address of private peripheral space
MRC p15, 4, r1, c15, c0, 0 // Read periph base address
ADD r1, r1, #0x2000
STR r0, [r1, #0x8] // Write the Binary register (ICCBPR/ICCBPR)
BX lr
// ------------------------------------------------------------
.global readIntAck
.type readIntAck,function
// unsigned int readIntAck(void)
// Returns the value of the Interrupt Acknowledge Register
readIntAck:
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
ADD r0, r0, #0x2000
LDR r0, [r0, #0xC] // Read the Interrupt Acknowledge Register (ICCIAR)
BX lr
// ------------------------------------------------------------
.global writeEOI
.type writeEOI,function
// void writeEOI(unsigned int ID)
// Writes ID to the End Of Interrupt register
writeEOI:
// Get base address of private peripheral space
MRC p15, 4, r1, c15, c0, 0 // Read periph base address
ADD r1, r1, #0x2000
STR r0, [r1, #0x10] // Write ID to the End of Interrupt register (ICCEOIR)
BX lr
//----------------------------------------------------------------
// SGI
//----------------------------------------------------------------
.global sendSGI
.type sendSGI,function
// void sendSGI(unsigned int ID, unsigned int target_list, unsigned int filter_list)//
// Send a software generate interrupt
sendSGI:
AND r3, r0, #0x0F // Mask off unused bits of ID, and move to r3
AND r1, r1, #0x0F // Mask off unused bits of target_filter
AND r2, r2, #0x0F // Mask off unused bits of filter_list
ORR r3, r3, r1, LSL #16 // Combine ID and target_filter
ORR r3, r3, r2, LSL #24 // and now the filter list
// Get the address of the GIC
MRC p15, 4, r0, c15, c0, 0 // Read periph base address
ADD r0, r0, #0x1F00 // Add offset of the sgi_trigger reg
STR r3, [r0] // Write to the Software Generated Interrupt Register (ICDSGIR)
BX lr
//----------------------------------------------------------------
// End of MP_GIC.s
//----------------------------------------------------------------

View File

@@ -0,0 +1,84 @@
// ------------------------------------------------------------
// Cortex-A MPCore - Private timer functions
//
// Copyright ARM Ltd 2009. All rights reserved.
// ------------------------------------------------------------
.text
.align 3
// 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
// ------------------------------------------------------------
// 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) AutoReload not supported on Cortex-A7
.global init_private_timer
.type init_private_timer,function
init_private_timer:
// Setup timeout value (CNTP_TVAL)
MCR p15, 0, r0, c14, c2, 0
BX lr
// ------------------------------------------------------------
// void start_private_timer(void)
// Starts the private timer
.global start_private_timer
.type start_private_timer,function
start_private_timer:
MOV r0, #0x1
// Enable timer (CNTP_CTL)
MCR p15, 0, r0, c14, c2, 1
BX lr
// ------------------------------------------------------------
// void stop_private_timer(void)
// Stops the private timer
.global stop_private_timer
.type stop_private_timer,function
stop_private_timer:
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:
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:
BX lr
// ------------------------------------------------------------
// End of code
// ------------------------------------------------------------
// ------------------------------------------------------------
// End of MP_PrivateTimer.s
// ------------------------------------------------------------

View File

@@ -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
// ------------------------------------------------------------

View File

@@ -1,6 +1,8 @@
arm-none-eabi-gcc -c -g -mcpu=cortex-a8 reset.S
arm-none-eabi-gcc -c -g -mcpu=cortex-a8 crt0.S
arm-none-eabi-gcc -c -g -mcpu=cortex-a8 tx_initialize_low_level.S
arm-none-eabi-gcc -c -g -mcpu=cortex-a8 MP_GIC.s
arm-none-eabi-gcc -c -g -mcpu=cortex-a8 MP_PrivateTimer.s
arm-none-eabi-gcc -c -g -mcpu=cortex-a8 V7.s
arm-none-eabi-gcc -c -g -mcpu=cortex-a8 -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-a8 -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

View File

@@ -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,42 @@ _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)
// 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
POP {lr}
#ifdef __THUMB_INTERWORK
BX lr // Return to caller
#else
@@ -202,16 +243,18 @@ __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
MOV r0, #0xF0000
MOV r1, #0x0
BL init_private_timer
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 +262,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

View File

@@ -1,18 +1,18 @@
>output thread_0_counter
2913840557
10
>output thread_1_counter
2913840557
299267
>output thread_2_counter
2913840557
299268
>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