Fixed the issue of the data/bss section cannot be read from ARM FVP d… (#301)

* Fixed the issue of the data/bss section cannot be read from ARM FVP debug tool in cortex-A7 GNU port.

https://msazure.visualstudio.com/One/_workitems/edit/24597276/

* remove untracked files.
This commit is contained in:
Yajun Xia
2023-09-15 10:46:20 +08:00
committed by GitHub
parent cd9007712b
commit 6aeefea8e6
40 changed files with 5677 additions and 348 deletions

View File

@@ -79,6 +79,14 @@ _mainCRTStartup:
#endif
#endif
.global _fini
.type _fini,function
_fini:
#ifdef __THUMB_INTERWORK
BX lr // Return to caller
#else
MOV pc, lr // Return to caller
#endif
/* Workspace for Angel calls. */
.data

View File

@@ -109,7 +109,7 @@ SECTIONS
.eh_frame_hdr : { *(.eh_frame_hdr) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN(256) + (. & (256 - 1));
. = 0x2E000000;
.data :
{
*(.data)

View File

@@ -1,311 +0,0 @@
/**************************************************************************/
/* */
/* 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
.arm
SVC_MODE = 0xD3 // Disable IRQ/FIQ SVC mode
IRQ_MODE = 0xD2 // Disable IRQ/FIQ IRQ mode
FIQ_MODE = 0xD1 // Disable IRQ/FIQ FIQ mode
SYS_MODE = 0xDF // Disable IRQ/FIQ SYS mode
FIQ_STACK_SIZE = 512 // FIQ stack size
IRQ_STACK_SIZE = 1024 // IRQ stack size
SYS_STACK_SIZE = 1024 // System stack size
.global _tx_thread_system_stack_ptr
.global _tx_initialize_unused_memory
.global _tx_thread_context_save
.global _tx_thread_context_restore
.global _tx_timer_interrupt
.global _end
.global _sp
.global _stack_bottom
/* Define the 16-bit Thumb mode veneer for _tx_initialize_low_level for
applications calling this function from to 16-bit Thumb mode. */
.text
.align 2
.thumb
.global $_tx_initialize_low_level
.type $_tx_initialize_low_level,function
$_tx_initialize_low_level:
BX pc // Switch to 32-bit mode
NOP //
.arm
STMFD sp!, {lr} // Save return address
BL _tx_initialize_low_level // Call _tx_initialize_low_level function
LDMFD sp!, {lr} // Recover saved return address
BX lr // Return to 16-bit caller
.text
.align 2
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_initialize_low_level ARMv7-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 */
/* 04-25-2022 Zhen Kong Updated comments, */
/* 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_initialize_low_level
.type _tx_initialize_low_level,function
_tx_initialize_low_level:
/* We must be in SVC mode at this point! */
/* Setup various stack pointers. */
LDR r1, =_sp // Get pointer to stack area
#ifdef TX_ENABLE_IRQ_NESTING
/* Setup the system mode stack for nested interrupt support */
LDR r2, =SYS_STACK_SIZE // Pickup stack size
MOV r3, #SYS_MODE // Build SYS mode CPSR
MSR CPSR_c, r3 // Enter SYS mode
SUB r1, r1, #1 // Backup 1 byte
BIC r1, r1, #7 // Ensure 8-byte alignment
MOV sp, r1 // Setup SYS stack pointer
SUB r1, r1, r2 // Calculate start of next stack
#endif
LDR r2, =FIQ_STACK_SIZE // Pickup stack size
MOV r0, #FIQ_MODE // Build FIQ mode CPSR
MSR CPSR, r0 // Enter FIQ mode
SUB r1, r1, #1 // Backup 1 byte
BIC r1, r1, #7 // Ensure 8-byte alignment
MOV sp, r1 // Setup FIQ stack pointer
SUB r1, r1, r2 // Calculate start of next stack
LDR r2, =IRQ_STACK_SIZE // Pickup IRQ stack size
MOV r0, #IRQ_MODE // Build IRQ mode CPSR
MSR CPSR, r0 // Enter IRQ mode
SUB r1, r1, #1 // Backup 1 byte
BIC r1, r1, #7 // Ensure 8-byte alignment
MOV sp, r1 // Setup IRQ stack pointer
SUB r3, r1, r2 // Calculate end of IRQ stack
MOV r0, #SVC_MODE // Build SVC mode CPSR
MSR CPSR, r0 // Enter SVC mode
LDR r2, =_stack_bottom // Pickup stack bottom
CMP r3, r2 // Compare the current stack end with the bottom
_stack_error_loop:
BLT _stack_error_loop // If the IRQ stack exceeds the stack bottom, just sit here!
LDR r2, =_tx_thread_system_stack_ptr // Pickup stack pointer
STR r1, [r2] // Save the system stack
LDR r1, =_end // Get end of non-initialized RAM area
LDR r2, =_tx_initialize_unused_memory // Pickup unused memory ptr address
ADD r1, r1, #8 // Increment to next free word
STR r1, [r2] // Save first free memory address
#ifdef __THUMB_INTERWORK
BX lr // Return to caller
#else
MOV pc, lr // Return to caller
#endif
/* Define shells for each of the interrupt vectors. */
.global __tx_undefined
__tx_undefined:
B __tx_undefined // Undefined handler
.global __tx_swi_interrupt
__tx_swi_interrupt:
B __tx_swi_interrupt // Software interrupt handler
.global __tx_prefetch_handler
__tx_prefetch_handler:
B __tx_prefetch_handler // Prefetch exception handler
.global __tx_abort_handler
__tx_abort_handler:
B __tx_abort_handler // Abort exception handler
.global __tx_reserved_handler
__tx_reserved_handler:
B __tx_reserved_handler // Reserved exception handler
.global __tx_irq_handler
.global __tx_irq_processing_return
__tx_irq_handler:
/* Jump to context save to save system context. */
B _tx_thread_context_save
__tx_irq_processing_return:
//
/* At this point execution is still in the IRQ mode. The CPSR, point of
interrupt, and all C scratch registers are available for use. In
addition, IRQ interrupts may be re-enabled - with certain restrictions -
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. */
/* 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.
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
/* For debug purpose, execute the timer interrupt processing here. In
a real system, some kind of status indication would have to be checked
before the timer interrupt handler could be called. */
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
/* Jump to context restore to restore system context. */
B _tx_thread_context_restore
/* This is an example of a vectored IRQ handler. */
/* Save initial context and call context save to prepare for
vectored ISR execution. */
/* At this point execution is still in the IRQ mode. The CPSR, point of
interrupt, and all C scratch registers are available for use. In
addition, IRQ interrupts may be re-enabled - with certain restrictions -
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. */
/* 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.
NOTE: It is very important to ensure all IRQ interrupts are cleared
prior to enabling nested IRQ interrupts. */
/* Application IRQ handlers can be called here! */
/* 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_FIQ_SUPPORT
.global __tx_fiq_handler
.global __tx_fiq_processing_return
__tx_fiq_handler:
/* Jump to fiq context save to save system context. */
B _tx_thread_fiq_context_save
__tx_fiq_processing_return:
/* At this point execution is still in the FIQ mode. The CPSR, point of
interrupt, and all C scratch registers are available for use. */
/* Interrupt nesting is allowed after calling _tx_thread_fiq_nesting_start
from FIQ mode with interrupts disabled. This routine switches to the
system mode and returns with FIQ interrupts enabled.
NOTE: It is very important to ensure all FIQ interrupts are cleared
prior to enabling nested FIQ interrupts. */
#ifdef TX_ENABLE_FIQ_NESTING
BL _tx_thread_fiq_nesting_start
#endif
/* Application FIQ handlers can be called here! */
/* If interrupt nesting was started earlier, the end of interrupt nesting
service must be called before returning to _tx_thread_fiq_context_restore. */
#ifdef TX_ENABLE_FIQ_NESTING
BL _tx_thread_fiq_nesting_end
#endif
/* Jump to fiq context restore to restore system context. */
B _tx_thread_fiq_context_restore
#else
.global __tx_fiq_handler
__tx_fiq_handler:
B __tx_fiq_handler // FIQ interrupt handler
#endif
BUILD_OPTIONS:
.word _tx_build_options // Reference to bring in
VERSION_ID:
.word _tx_version_id // Reference to bring in

View File

@@ -0,0 +1,155 @@
// ------------------------------------------------------------
// v7-A Cache, TLB and Branch Prediction Maintenance Operations
// Header File
//
// Copyright (c) 2011-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 _ARMV7A_GENERIC_H
#define _ARMV7A_GENERIC_H
// ------------------------------------------------------------
// Memory barrier mnemonics
enum MemBarOpt {
RESERVED_0 = 0, RESERVED_1 = 1, OSHST = 2, OSH = 3,
RESERVED_4 = 4, RESERVED_5 = 5, NSHST = 6, NSH = 7,
RESERVED_8 = 8, RESERVED_9 = 9, ISHST = 10, ISH = 11,
RESERVED_12 = 12, RESERVED_13 = 13, ST = 14, SY = 15
};
//
// Note:
// *_IS() stands for "inner shareable"
// DO NOT USE THESE FUNCTIONS ON A CORTEX-A8
//
// ------------------------------------------------------------
// Interrupts
// Enable/disables IRQs (not FIQs)
void enableInterrupts(void);
void disableInterrupts(void);
// ------------------------------------------------------------
// Caches
void invalidateCaches_IS(void);
void cleanInvalidateDCache(void);
void invalidateCaches_IS(void);
void enableCaches(void);
void disableCaches(void);
void invalidateCaches(void);
void cleanDCache(void);
// ------------------------------------------------------------
// TLBs
void invalidateUnifiedTLB(void);
void invalidateUnifiedTLB_IS(void);
// ------------------------------------------------------------
// Branch prediction
void flushBranchTargetCache(void);
void flushBranchTargetCache_IS(void);
// ------------------------------------------------------------
// High Vecs
void enableHighVecs(void);
void disableHighVecs(void);
// ------------------------------------------------------------
// ID Registers
unsigned int getMIDR(void);
#define MIDR_IMPL_SHIFT 24
#define MIDR_IMPL_MASK 0xFF
#define MIDR_VAR_SHIFT 20
#define MIDR_VAR_MASK 0xF
#define MIDR_ARCH_SHIFT 16
#define MIDR_ARCH_MASK 0xF
#define MIDR_PART_SHIFT 4
#define MIDR_PART_MASK 0xFFF
#define MIDR_REV_SHIFT 0
#define MIDR_REV_MASK 0xF
// tmp = get_MIDR();
// implementor = (tmp >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
// variant = (tmp >> MIDR_VAR_SHIFT) & MIDR_VAR_MASK;
// architecture= (tmp >> MIDR_ARCH_SHIFT) & MIDR_ARCH_MASK;
// part_number = (tmp >> MIDR_PART_SHIFT) & MIDR_PART_MASK;
// revision = tmp & MIDR_REV_MASK;
#define MIDR_PART_CA5 0xC05
#define MIDR_PART_CA8 0xC08
#define MIDR_PART_CA9 0xC09
unsigned int getMPIDR(void);
#define MPIDR_FORMAT_SHIFT 31
#define MPIDR_FORMAT_MASK 0x1
#define MPIDR_UBIT_SHIFT 30
#define MPIDR_UBIT_MASK 0x1
#define MPIDR_CLUSTER_SHIFT 7
#define MPIDR_CLUSTER_MASK 0xF
#define MPIDR_CPUID_SHIFT 0
#define MPIDR_CPUID_MASK 0x3
#define MPIDR_CPUID_CPU0 0x0
#define MPIDR_CPUID_CPU1 0x1
#define MPIDR_CPUID_CPU2 0x2
#define MPIDR_CPUID_CPU3 0x3
#define MPIDR_UNIPROCESSPR 0x1
#define MPDIR_NEW_FORMAT 0x1
// ------------------------------------------------------------
// Context ID
unsigned int getContextID(void);
void setContextID(unsigned int);
#define CONTEXTID_ASID_SHIFT 0
#define CONTEXTID_ASID_MASK 0xFF
#define CONTEXTID_PROCID_SHIFT 8
#define CONTEXTID_PROCID_MASK 0x00FFFFFF
// tmp = getContextID();
// ASID = tmp & CONTEXTID_ASID_MASK;
// PROCID = (tmp >> CONTEXTID_PROCID_SHIFT) & CONTEXTID_PROCID_MASK;
// ------------------------------------------------------------
// SMP related for Armv7-A MPCore processors
//
// DO NOT CALL THESE FUNCTIONS ON A CORTEX-A8
// Returns the base address of the private peripheral memory space
unsigned int getBaseAddr(void);
// Returns the CPU ID (0 to 3) of the CPU executed on
#define MP_CPU0 (0)
#define MP_CPU1 (1)
#define MP_CPU2 (2)
#define MP_CPU3 (3)
unsigned int getCPUID(void);
// Set this core as participating in SMP
void joinSMP(void);
// Set this core as NOT participating in SMP
void leaveSMP(void);
// Go to sleep, never returns
void goToSleep(void);
#endif
// ------------------------------------------------------------
// End of v7.h
// ------------------------------------------------------------

View File

@@ -0,0 +1,476 @@
// ------------------------------------------------------------
// v7-A Cache and Branch Prediction Maintenance Operations
//
// 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.
// ------------------------------------------------------------
.arm
// ------------------------------------------------------------
// Interrupt enable/disable
// ------------------------------------------------------------
// Could use intrinsic instead of these
.global enableInterrupts
.type enableInterrupts,function
// void enableInterrupts(void)//
enableInterrupts:
CPSIE i
BX lr
.global disableInterrupts
.type disableInterrupts,function
// void disableInterrupts(void)//
disableInterrupts:
CPSID i
BX lr
// ------------------------------------------------------------
// Cache Maintenance
// ------------------------------------------------------------
.global enableCaches
.type enableCaches,function
// void enableCaches(void)//
enableCaches:
MRC p15, 0, r0, c1, c0, 0 // Read System Control Register
ORR r0, r0, #(1 << 2) // Set C bit
ORR r0, r0, #(1 << 12) // Set I bit
MCR p15, 0, r0, c1, c0, 0 // Write System Control Register
ISB
BX lr
.global disableCaches
.type disableCaches,function
// void disableCaches(void)
disableCaches:
MRC p15, 0, r0, c1, c0, 0 // Read System Control Register
BIC r0, r0, #(1 << 2) // Clear C bit
BIC r0, r0, #(1 << 12) // Clear I bit
MCR p15, 0, r0, c1, c0, 0 // Write System Control Register
ISB
BX lr
.global cleanDCache
.type cleanDCache,function
// void cleanDCache(void)//
cleanDCache:
PUSH {r4-r12}
//
// Based on code example given in section 11.2.4 of Armv7-A/R Architecture Reference Manual (DDI 0406B)
//
MRC p15, 1, r0, c0, c0, 1 // Read CLIDR
ANDS r3, r0, #0x7000000
MOV r3, r3, LSR #23 // Cache level value (naturally aligned)
BEQ clean_dcache_finished
MOV r10, #0
clean_dcache_loop1:
ADD r2, r10, r10, LSR #1 // Work out 3xcachelevel
MOV r1, r0, LSR r2 // bottom 3 bits are the Cache type for this level
AND r1, r1, #7 // get those 3 bits alone
CMP r1, #2
BLT clean_dcache_skip // no cache or only instruction cache at this level
MCR p15, 2, r10, c0, c0, 0 // write the Cache Size selection register
ISB // ISB to sync the change to the CacheSizeID reg
MRC p15, 1, r1, c0, c0, 0 // reads current Cache Size ID register
AND r2, r1, #7 // extract the line length field
ADD r2, r2, #4 // add 4 for the line length offset (log2 16 bytes)
LDR r4, =0x3FF
ANDS r4, r4, r1, LSR #3 // R4 is the max number on the way size (right aligned)
CLZ r5, r4 // R5 is the bit position of the way size increment
LDR r7, =0x00007FFF
ANDS r7, r7, r1, LSR #13 // R7 is the max number of the index size (right aligned)
clean_dcache_loop2:
MOV r9, R4 // R9 working copy of the max way size (right aligned)
clean_dcache_loop3:
ORR r11, r10, r9, LSL r5 // factor in the way number and cache number into R11
ORR r11, r11, r7, LSL r2 // factor in the index number
MCR p15, 0, r11, c7, c10, 2 // DCCSW - clean by set/way
SUBS r9, r9, #1 // decrement the way number
BGE clean_dcache_loop3
SUBS r7, r7, #1 // decrement the index
BGE clean_dcache_loop2
clean_dcache_skip:
ADD r10, r10, #2 // increment the cache number
CMP r3, r10
BGT clean_dcache_loop1
clean_dcache_finished:
POP {r4-r12}
BX lr
.global cleanInvalidateDCache
.type cleanInvalidateDCache,function
// void cleanInvalidateDCache(void)//
cleanInvalidateDCache:
PUSH {r4-r12}
//
// Based on code example given in section 11.2.4 of Armv7-A/R Architecture Reference Manual (DDI 0406B)
//
MRC p15, 1, r0, c0, c0, 1 // Read CLIDR
ANDS r3, r0, #0x7000000
MOV r3, r3, LSR #23 // Cache level value (naturally aligned)
BEQ clean_invalidate_dcache_finished
MOV r10, #0
clean_invalidate_dcache_loop1:
ADD r2, r10, r10, LSR #1 // Work out 3xcachelevel
MOV r1, r0, LSR r2 // bottom 3 bits are the Cache type for this level
AND r1, r1, #7 // get those 3 bits alone
CMP r1, #2
BLT clean_invalidate_dcache_skip // no cache or only instruction cache at this level
MCR p15, 2, r10, c0, c0, 0 // write the Cache Size selection register
ISB // ISB to sync the change to the CacheSizeID reg
MRC p15, 1, r1, c0, c0, 0 // reads current Cache Size ID register
AND r2, r1, #7 // extract the line length field
ADD r2, r2, #4 // add 4 for the line length offset (log2 16 bytes)
LDR r4, =0x3FF
ANDS r4, r4, r1, LSR #3 // R4 is the max number on the way size (right aligned)
CLZ r5, r4 // R5 is the bit position of the way size increment
LDR r7, =0x00007FFF
ANDS r7, r7, r1, LSR #13 // R7 is the max number of the index size (right aligned)
clean_invalidate_dcache_loop2:
MOV r9, R4 // R9 working copy of the max way size (right aligned)
clean_invalidate_dcache_loop3:
ORR r11, r10, r9, LSL r5 // factor in the way number and cache number into R11
ORR r11, r11, r7, LSL r2 // factor in the index number
MCR p15, 0, r11, c7, c14, 2 // DCCISW - clean and invalidate by set/way
SUBS r9, r9, #1 // decrement the way number
BGE clean_invalidate_dcache_loop3
SUBS r7, r7, #1 // decrement the index
BGE clean_invalidate_dcache_loop2
clean_invalidate_dcache_skip:
ADD r10, r10, #2 // increment the cache number
CMP r3, r10
BGT clean_invalidate_dcache_loop1
clean_invalidate_dcache_finished:
POP {r4-r12}
BX lr
.global invalidateCaches
.type invalidateCaches,function
// void invalidateCaches(void)//
invalidateCaches:
PUSH {r4-r12}
//
// Based on code example given in section B2.2.4/11.2.4 of Armv7-A/R Architecture Reference Manual (DDI 0406B)
//
MOV r0, #0
MCR p15, 0, r0, c7, c5, 0 // ICIALLU - Invalidate entire I Cache, and flushes branch target cache
MRC p15, 1, r0, c0, c0, 1 // Read CLIDR
ANDS r3, r0, #0x7000000
MOV r3, r3, LSR #23 // Cache level value (naturally aligned)
BEQ invalidate_caches_finished
MOV r10, #0
invalidate_caches_loop1:
ADD r2, r10, r10, LSR #1 // Work out 3xcachelevel
MOV r1, r0, LSR r2 // bottom 3 bits are the Cache type for this level
AND r1, r1, #7 // get those 3 bits alone
CMP r1, #2
BLT invalidate_caches_skip // no cache or only instruction cache at this level
MCR p15, 2, r10, c0, c0, 0 // write the Cache Size selection register
ISB // ISB to sync the change to the CacheSizeID reg
MRC p15, 1, r1, c0, c0, 0 // reads current Cache Size ID register
AND r2, r1, #7 // extract the line length field
ADD r2, r2, #4 // add 4 for the line length offset (log2 16 bytes)
LDR r4, =0x3FF
ANDS r4, r4, r1, LSR #3 // R4 is the max number on the way size (right aligned)
CLZ r5, r4 // R5 is the bit position of the way size increment
LDR r7, =0x00007FFF
ANDS r7, r7, r1, LSR #13 // R7 is the max number of the index size (right aligned)
invalidate_caches_loop2:
MOV r9, R4 // R9 working copy of the max way size (right aligned)
invalidate_caches_loop3:
ORR r11, r10, r9, LSL r5 // factor in the way number and cache number into R11
ORR r11, r11, r7, LSL r2 // factor in the index number
MCR p15, 0, r11, c7, c6, 2 // DCISW - invalidate by set/way
SUBS r9, r9, #1 // decrement the way number
BGE invalidate_caches_loop3
SUBS r7, r7, #1 // decrement the index
BGE invalidate_caches_loop2
invalidate_caches_skip:
ADD r10, r10, #2 // increment the cache number
CMP r3, r10
BGT invalidate_caches_loop1
invalidate_caches_finished:
POP {r4-r12}
BX lr
.global invalidateCaches_IS
.type invalidateCaches_IS,function
// void invalidateCaches_IS(void)//
invalidateCaches_IS:
PUSH {r4-r12}
MOV r0, #0
MCR p15, 0, r0, c7, c1, 0 // ICIALLUIS - Invalidate entire I Cache inner shareable
MRC p15, 1, r0, c0, c0, 1 // Read CLIDR
ANDS r3, r0, #0x7000000
MOV r3, r3, LSR #23 // Cache level value (naturally aligned)
BEQ invalidate_caches_is_finished
MOV r10, #0
invalidate_caches_is_loop1:
ADD r2, r10, r10, LSR #1 // Work out 3xcachelevel
MOV r1, r0, LSR r2 // bottom 3 bits are the Cache type for this level
AND r1, r1, #7 // get those 3 bits alone
CMP r1, #2
BLT invalidate_caches_is_skip // no cache or only instruction cache at this level
MCR p15, 2, r10, c0, c0, 0 // write the Cache Size selection register
ISB // ISB to sync the change to the CacheSizeID reg
MRC p15, 1, r1, c0, c0, 0 // reads current Cache Size ID register
AND r2, r1, #7 // extract the line length field
ADD r2, r2, #4 // add 4 for the line length offset (log2 16 bytes)
LDR r4, =0x3FF
ANDS r4, r4, r1, LSR #3 // R4 is the max number on the way size (right aligned)
CLZ r5, r4 // R5 is the bit position of the way size increment
LDR r7, =0x00007FFF
ANDS r7, r7, r1, LSR #13 // R7 is the max number of the index size (right aligned)
invalidate_caches_is_loop2:
MOV r9, R4 // R9 working copy of the max way size (right aligned)
invalidate_caches_is_loop3:
ORR r11, r10, r9, LSL r5 // factor in the way number and cache number into R11
ORR r11, r11, r7, LSL r2 // factor in the index number
MCR p15, 0, r11, c7, c6, 2 // DCISW - clean by set/way
SUBS r9, r9, #1 // decrement the way number
BGE invalidate_caches_is_loop3
SUBS r7, r7, #1 // decrement the index
BGE invalidate_caches_is_loop2
invalidate_caches_is_skip:
ADD r10, r10, #2 // increment the cache number
CMP r3, r10
BGT invalidate_caches_is_loop1
invalidate_caches_is_finished:
POP {r4-r12}
BX lr
// ------------------------------------------------------------
// TLB
// ------------------------------------------------------------
.global invalidateUnifiedTLB
.type invalidateUnifiedTLB,function
// void invalidateUnifiedTLB(void)//
invalidateUnifiedTLB:
MOV r0, #0
MCR p15, 0, r0, c8, c7, 0 // TLBIALL - Invalidate entire unified TLB
BX lr
.global invalidateUnifiedTLB_IS
.type invalidateUnifiedTLB_IS,function
// void invalidateUnifiedTLB_IS(void)//
invalidateUnifiedTLB_IS:
MOV r0, #1
MCR p15, 0, r0, c8, c3, 0 // TLBIALLIS - Invalidate entire unified TLB Inner Shareable
BX lr
// ------------------------------------------------------------
// Branch Prediction
// ------------------------------------------------------------
.global flushBranchTargetCache
.type flushBranchTargetCache,function
// void flushBranchTargetCache(void)
flushBranchTargetCache:
MOV r0, #0
MCR p15, 0, r0, c7, c5, 6 // BPIALL - Invalidate entire branch predictor array
BX lr
.global flushBranchTargetCache_IS
.type flushBranchTargetCache_IS,function
// void flushBranchTargetCache_IS(void)
flushBranchTargetCache_IS:
MOV r0, #0
MCR p15, 0, r0, c7, c1, 6 // BPIALLIS - Invalidate entire branch predictor array Inner Shareable
BX lr
// ------------------------------------------------------------
// High Vecs
// ------------------------------------------------------------
.global enableHighVecs
.type enableHighVecs,function
// void enableHighVecs(void)//
enableHighVecs:
MRC p15, 0, r0, c1, c0, 0 // Read Control Register
ORR r0, r0, #(1 << 13) // Set the V bit (bit 13)
MCR p15, 0, r0, c1, c0, 0 // Write Control Register
ISB
BX lr
.global disableHighVecs
.type disableHighVecs,function
// void disable_highvecs(void)//
disableHighVecs:
MRC p15, 0, r0, c1, c0, 0 // Read Control Register
BIC r0, r0, #(1 << 13) // Clear the V bit (bit 13)
MCR p15, 0, r0, c1, c0, 0 // Write Control Register
ISB
BX lr
// ------------------------------------------------------------
// Context ID
// ------------------------------------------------------------
.global getContextID
.type getContextID,function
// uint32_t getContextIDd(void)//
getContextID:
MRC p15, 0, r0, c13, c0, 1 // Read Context ID Register
BX lr
.global setContextID
.type setContextID,function
// void setContextID(uint32_t)//
setContextID:
MCR p15, 0, r0, c13, c0, 1 // Write Context ID Register
BX lr
// ------------------------------------------------------------
// ID registers
// ------------------------------------------------------------
.global getMIDR
.type getMIDR,function
// uint32_t getMIDR(void)//
getMIDR:
MRC p15, 0, r0, c0, c0, 0 // Read Main ID Register (MIDR)
BX lr
.global getMPIDR
.type getMPIDR,function
// uint32_t getMPIDR(void)//
getMPIDR:
MRC p15, 0, r0, c0 ,c0, 5// Read Multiprocessor ID register (MPIDR)
BX lr
// ------------------------------------------------------------
// CP15 SMP related
// ------------------------------------------------------------
.global getBaseAddr
.type getBaseAddr,function
// uint32_t getBaseAddr(void)
// Returns the value CBAR (base address of the private peripheral memory space)
getBaseAddr:
MRC p15, 4, r0, c15, c0, 0 // Read peripheral base address
BX lr
// ------------------------------------------------------------
.global getCPUID
.type getCPUID,function
// uint32_t getCPUID(void)
// Returns the CPU ID (0 to 3) of the CPU executed on
getCPUID:
MRC p15, 0, r0, c0, c0, 5 // Read CPU ID register
AND r0, r0, #0x03 // Mask off, leaving the CPU ID field
BX lr
// ------------------------------------------------------------
.global goToSleep
.type goToSleep,function
// void goToSleep(void)
goToSleep:
DSB // Clear all pending data accesses
WFI // Go into standby
B goToSleep // Catch in case of rogue events
BX lr
// ------------------------------------------------------------
.global joinSMP
.type joinSMP,function
// void joinSMP(void)
// Sets the ACTRL.SMP bit
joinSMP:
// SMP status is controlled by bit 6 of the CP15 Aux Ctrl Reg
MRC p15, 0, r0, c1, c0, 1 // Read ACTLR
MOV r1, r0
ORR r0, r0, #0x040 // Set bit 6
CMP r0, r1
MCRNE p15, 0, r0, c1, c0, 1 // Write ACTLR
ISB
BX lr
// ------------------------------------------------------------
.global leaveSMP
.type leaveSMP,function
// void leaveSMP(void)
// Clear the ACTRL.SMP bit
leaveSMP:
// SMP status is controlled by bit 6 of the CP15 Aux Ctrl Reg
MRC p15, 0, r0, c1, c0, 1 // Read ACTLR
BIC r0, r0, #0x040 // Clear bit 6
MCR p15, 0, r0, c1, c0, 1 // Write ACTLR
ISB
BX lr
// ------------------------------------------------------------
// End of v7.s
// ------------------------------------------------------------