mirror of
https://github.com/apache/nuttx.git
synced 2026-06-05 15:58:59 +08:00
arch/arm: add ARMv8-r(Cortex-R52) support
Basic work required for uniprocessor CortexR52 (ARMv8R AARCH32) using GICv3 and CP15 mapped arch timer. Tested on ARM FVP 11.20. Port is based on ARMv8R AARCH64 and ARMv7R code. Excuse possible copy-paste leftovers.
This commit is contained in:
committed by
Alan Carvalho de Assis
parent
3c54d82d81
commit
f6695738e1
@@ -936,6 +936,14 @@ config ARCH_CORTEXM85
|
||||
select ARCH_HAVE_USAGEFAULT_DEBUG
|
||||
select ARCH_HAVE_SECUREFAULT_DEBUG if ARCH_TRUSTZONE_SECURE
|
||||
|
||||
config ARCH_ARMV8R
|
||||
bool
|
||||
default n
|
||||
select ARCH_HAVE_CPUINFO
|
||||
select ONESHOT
|
||||
select ALARM_ARCH
|
||||
|
||||
|
||||
config ARCH_FAMILY
|
||||
string
|
||||
default "arm" if ARCH_ARM7TDMI || ARCH_ARM920T || ARCH_ARM926EJS || ARCH_ARM1136J || ARCH_ARM1156T2 || ARCH_ARM1176JZ
|
||||
@@ -1321,6 +1329,9 @@ endif
|
||||
if ARCH_ARMV8M
|
||||
source "arch/arm/src/armv8-m/Kconfig"
|
||||
endif
|
||||
if ARCH_ARMV8R
|
||||
source "arch/arm/src/armv8-r/Kconfig"
|
||||
endif
|
||||
if ARCH_ARM7TDMI || ARCH_ARM920T || ARCH_ARM926EJS || ARCH_ARM1136J || ARCH_ARM1156T2 || ARCH_ARM1176JZ
|
||||
source "arch/arm/src/arm/Kconfig"
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,430 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/include/armv8-r/irq.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* This file should never be included directly but, rather, only indirectly
|
||||
* through nuttx/irq.h
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_INCLUDE_ARMV8_R_IRQ_H
|
||||
#define __ARCH_ARM_INCLUDE_ARMV8_R_IRQ_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* IRQ Stack Frame Format:
|
||||
*
|
||||
* Context is always saved/restored in the same way:
|
||||
*
|
||||
* (1) stmia rx, {r0-r14}
|
||||
* (2) then the PC and CPSR
|
||||
*
|
||||
* This results in the following set of indices that can be used to access
|
||||
* individual registers in the xcp.regs array:
|
||||
*/
|
||||
|
||||
/* If the MCU supports a floating point unit, then it will be necessary
|
||||
* to save the state of the FPU status register and data registers on
|
||||
* each context switch. These registers are not saved during interrupt
|
||||
* level processing, however. So, as a consequence, floating point
|
||||
* operations may NOT be performed in interrupt handlers.
|
||||
*
|
||||
* The FPU provides an extension register file containing 32 single-
|
||||
* precision registers. These can be viewed as:
|
||||
*
|
||||
* - Sixteen 64-bit double word registers, D0-D15
|
||||
* - Thirty-two 32-bit single-word registers, S0-S31
|
||||
* S<2n> maps to the least significant half of D<n>
|
||||
* S<2n+1> maps to the most significant half of D<n>.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
# define REG_D0 (0) /* D0 */
|
||||
# define REG_S0 (0) /* S0 */
|
||||
# define REG_S1 (1) /* S1 */
|
||||
# define REG_D1 (2) /* D1 */
|
||||
# define REG_S2 (2) /* S2 */
|
||||
# define REG_S3 (3) /* S3 */
|
||||
# define REG_D2 (4) /* D2 */
|
||||
# define REG_S4 (4) /* S4 */
|
||||
# define REG_S5 (5) /* S5 */
|
||||
# define REG_D3 (6) /* D3 */
|
||||
# define REG_S6 (6) /* S6 */
|
||||
# define REG_S7 (7) /* S7 */
|
||||
# define REG_D4 (8) /* D4 */
|
||||
# define REG_S8 (8) /* S8 */
|
||||
# define REG_S9 (9) /* S9 */
|
||||
# define REG_D5 (10) /* D5 */
|
||||
# define REG_S10 (10) /* S10 */
|
||||
# define REG_S11 (11) /* S11 */
|
||||
# define REG_D6 (12) /* D6 */
|
||||
# define REG_S12 (12) /* S12 */
|
||||
# define REG_S13 (13) /* S13 */
|
||||
# define REG_D7 (14) /* D7 */
|
||||
# define REG_S14 (14) /* S14 */
|
||||
# define REG_S15 (15) /* S15 */
|
||||
# define REG_D8 (16) /* D8 */
|
||||
# define REG_S16 (16) /* S16 */
|
||||
# define REG_S17 (17) /* S17 */
|
||||
# define REG_D9 (18) /* D9 */
|
||||
# define REG_S18 (18) /* S18 */
|
||||
# define REG_S19 (19) /* S19 */
|
||||
# define REG_D10 (20) /* D10 */
|
||||
# define REG_S20 (20) /* S20 */
|
||||
# define REG_S21 (21) /* S21 */
|
||||
# define REG_D11 (22) /* D11 */
|
||||
# define REG_S22 (22) /* S22 */
|
||||
# define REG_S23 (23) /* S23 */
|
||||
# define REG_D12 (24) /* D12 */
|
||||
# define REG_S24 (24) /* S24 */
|
||||
# define REG_S25 (25) /* S25 */
|
||||
# define REG_D13 (26) /* D13 */
|
||||
# define REG_S26 (26) /* S26 */
|
||||
# define REG_S27 (27) /* S27 */
|
||||
# define REG_D14 (28) /* D14 */
|
||||
# define REG_S28 (28) /* S28 */
|
||||
# define REG_S29 (29) /* S29 */
|
||||
# define REG_D15 (30) /* D15 */
|
||||
# define REG_S30 (30) /* S30 */
|
||||
# define REG_S31 (31) /* S31 */
|
||||
# ifdef CONFIG_ARM_HAVE_DPFPU32
|
||||
# define REG_D16 (32) /* D16 */
|
||||
# define REG_D17 (34) /* D17 */
|
||||
# define REG_D18 (36) /* D18 */
|
||||
# define REG_D19 (38) /* D19 */
|
||||
# define REG_D20 (40) /* D20 */
|
||||
# define REG_D21 (42) /* D21 */
|
||||
# define REG_D22 (44) /* D22 */
|
||||
# define REG_D23 (46) /* D23 */
|
||||
# define REG_D24 (48) /* D24 */
|
||||
# define REG_D25 (50) /* D25 */
|
||||
# define REG_D26 (52) /* D26 */
|
||||
# define REG_D27 (54) /* D27 */
|
||||
# define REG_D28 (56) /* D28 */
|
||||
# define REG_D29 (58) /* D29 */
|
||||
# define REG_D30 (60) /* D30 */
|
||||
# define REG_D31 (62) /* D31 */
|
||||
# define REG_FPSCR (64) /* Floating point status and control */
|
||||
# define FPU_CONTEXT_REGS (65)
|
||||
# else
|
||||
# define REG_FPSCR (32) /* Floating point status and control */
|
||||
# define FPU_CONTEXT_REGS (33)
|
||||
# endif
|
||||
#else
|
||||
# define FPU_CONTEXT_REGS (0)
|
||||
#endif
|
||||
|
||||
#define REG_R13 (FPU_CONTEXT_REGS+0)
|
||||
#define REG_R14 (FPU_CONTEXT_REGS+1)
|
||||
#define REG_R0 (FPU_CONTEXT_REGS+2)
|
||||
#define REG_R1 (FPU_CONTEXT_REGS+3)
|
||||
#define REG_R2 (FPU_CONTEXT_REGS+4)
|
||||
#define REG_R3 (FPU_CONTEXT_REGS+5)
|
||||
#define REG_R4 (FPU_CONTEXT_REGS+6)
|
||||
#define REG_R5 (FPU_CONTEXT_REGS+7)
|
||||
#define REG_R6 (FPU_CONTEXT_REGS+8)
|
||||
#define REG_R7 (FPU_CONTEXT_REGS+9)
|
||||
#define REG_R8 (FPU_CONTEXT_REGS+10)
|
||||
#define REG_R9 (FPU_CONTEXT_REGS+11)
|
||||
#define REG_R10 (FPU_CONTEXT_REGS+12)
|
||||
#define REG_R11 (FPU_CONTEXT_REGS+13)
|
||||
#define REG_R12 (FPU_CONTEXT_REGS+14)
|
||||
#define REG_R15 (FPU_CONTEXT_REGS+15)
|
||||
#define REG_CPSR (FPU_CONTEXT_REGS+16)
|
||||
|
||||
#define ARM_CONTEXT_REGS (17)
|
||||
|
||||
/* The total number of registers saved by software */
|
||||
|
||||
#define XCPTCONTEXT_REGS (FPU_CONTEXT_REGS + ARM_CONTEXT_REGS)
|
||||
#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS)
|
||||
|
||||
/* Friendly register names */
|
||||
|
||||
#define REG_A1 REG_R0
|
||||
#define REG_A2 REG_R1
|
||||
#define REG_A3 REG_R2
|
||||
#define REG_A4 REG_R3
|
||||
#define REG_V1 REG_R4
|
||||
#define REG_V2 REG_R5
|
||||
#define REG_V3 REG_R6
|
||||
#define REG_V4 REG_R7
|
||||
#define REG_V5 REG_R8
|
||||
#define REG_V6 REG_R9
|
||||
#define REG_V7 REG_R10
|
||||
#define REG_SB REG_R9
|
||||
#define REG_SL REG_R10
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
#define REG_FP REG_R7
|
||||
#else
|
||||
#define REG_FP REG_R11
|
||||
#endif /* CONFIG_ARM_THUMB */
|
||||
#define REG_IP REG_R12
|
||||
#define REG_SP REG_R13
|
||||
#define REG_LR REG_R14
|
||||
#define REG_PC REG_R15
|
||||
|
||||
/* The PIC register is usually R10. It can be R9 is stack checking is enabled
|
||||
* or if the user changes it with -mpic-register on the GCC command line.
|
||||
*/
|
||||
|
||||
#define REG_PIC REG_R10
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* This structure represents the return state from a system call */
|
||||
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
struct xcpt_syscall_s
|
||||
{
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
uint32_t cpsr; /* The CPSR value */
|
||||
#endif
|
||||
uint32_t sysreturn; /* The return PC */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* This struct defines the way the registers are stored. We need to save:
|
||||
*
|
||||
* 1 CPSR
|
||||
* 7 Static registers, v1-v7 (aka r4-r10)
|
||||
* 1 Frame pointer, fp (aka r11)
|
||||
* 1 Stack pointer, sp (aka r13)
|
||||
* 1 Return address, lr (aka r14)
|
||||
* ---
|
||||
* 11 (XCPTCONTEXT_USER_REG)
|
||||
*
|
||||
* On interrupts, we also need to save:
|
||||
* 4 Volatile registers, a1-a4 (aka r0-r3)
|
||||
* 1 Scratch Register, ip (aka r12)
|
||||
*---
|
||||
* 5 (XCPTCONTEXT_IRQ_REGS)
|
||||
*
|
||||
* For a total of 17 (XCPTCONTEXT_REGS)
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
struct xcptcontext
|
||||
{
|
||||
/* The following function pointer is non-zero if there are pending signals
|
||||
* to be processed.
|
||||
*/
|
||||
|
||||
void *sigdeliver; /* Actual type is sig_deliver_t */
|
||||
|
||||
/* These are saved copies of the context used during
|
||||
* signal processing.
|
||||
*/
|
||||
|
||||
uint32_t *saved_regs;
|
||||
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
/* This is the saved address to use when returning from a user-space
|
||||
* signal handler.
|
||||
*/
|
||||
|
||||
uint32_t sigreturn;
|
||||
#endif
|
||||
|
||||
/* Register save area with XCPTCONTEXT_SIZE, only valid when:
|
||||
* 1.The task isn't running or
|
||||
* 2.The task is interrupted
|
||||
* otherwise task is running, and regs contain the stale value.
|
||||
*/
|
||||
|
||||
uint32_t *regs;
|
||||
|
||||
/* Extra fault address register saved for common paging logic. In the
|
||||
* case of the pre-fetch abort, this value is the same as regs[REG_R15];
|
||||
* For the case of the data abort, this value is the value of the fault
|
||||
* address register (FAR) at the time of data abort exception.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PAGING
|
||||
uintptr_t far;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIB_SYSCALL
|
||||
/* The following array holds the return address and the exc_return value
|
||||
* needed to return from each nested system call.
|
||||
*/
|
||||
|
||||
uint8_t nsyscalls;
|
||||
struct xcpt_syscall_s syscall[CONFIG_SYS_NNEST];
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_ADDRENV
|
||||
#ifdef CONFIG_ARCH_STACK_DYNAMIC
|
||||
/* This array holds the physical address of the level 2 page table used
|
||||
* to map the thread's stack memory. This array will be initially of
|
||||
* zeroed and would be back-up up with pages during page fault exception
|
||||
* handling to support dynamically sized stacks for each thread.
|
||||
*/
|
||||
|
||||
uintptr_t *ustack[ARCH_STACK_NSECTS];
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_KERNEL_STACK
|
||||
/* In this configuration, all syscalls execute from an internal kernel
|
||||
* stack. Why? Because when we instantiate and initialize the address
|
||||
* environment of the new user process, we will temporarily lose the
|
||||
* address environment of the old user process, including its stack
|
||||
* contents. The kernel C logic will crash immediately with no valid
|
||||
* stack in place.
|
||||
*/
|
||||
|
||||
uint32_t *ustkptr; /* Saved user stack pointer */
|
||||
uint32_t *kstack; /* Allocate base of the (aligned) kernel stack */
|
||||
uint32_t *kstkptr; /* Saved kernel stack pointer */
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/****************************************************************************
|
||||
* Inline functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* Name: up_irq_save, up_irq_restore, and friends.
|
||||
*
|
||||
* NOTE: This function should never be called from application code and,
|
||||
* as a general rule unless you really know what you are doing, this
|
||||
* function should not be called directly from operation system code either:
|
||||
* Typically, the wrapper functions, enter_critical_section() and
|
||||
* leave_critical section(), are probably what you really want.
|
||||
*/
|
||||
|
||||
/* Return the current IRQ state */
|
||||
|
||||
static inline irqstate_t irqstate(void)
|
||||
{
|
||||
unsigned int cpsr;
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"\tmrs %0, cpsr\n"
|
||||
: "=r" (cpsr)
|
||||
:
|
||||
: "memory"
|
||||
);
|
||||
|
||||
return cpsr;
|
||||
}
|
||||
|
||||
/* Disable IRQs and return the previous IRQ state */
|
||||
|
||||
static inline irqstate_t up_irq_save(void)
|
||||
{
|
||||
unsigned int cpsr;
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"\tmrs %0, cpsr\n"
|
||||
"\tcpsid i\n"
|
||||
#if defined(CONFIG_ARMV7R_DECODEFIQ)
|
||||
"\tcpsid f\n"
|
||||
#endif
|
||||
: "=r" (cpsr)
|
||||
:
|
||||
: "memory"
|
||||
);
|
||||
|
||||
return cpsr;
|
||||
}
|
||||
|
||||
/* Enable IRQs and return the previous IRQ state */
|
||||
|
||||
static inline irqstate_t up_irq_enable(void)
|
||||
{
|
||||
unsigned int cpsr;
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"\tmrs %0, cpsr\n"
|
||||
"\tcpsie i\n"
|
||||
#if defined(CONFIG_ARMV7R_DECODEFIQ)
|
||||
"\tcpsie f\n"
|
||||
#endif
|
||||
: "=r" (cpsr)
|
||||
:
|
||||
: "memory"
|
||||
);
|
||||
|
||||
return cpsr;
|
||||
}
|
||||
|
||||
/* Restore saved IRQ & FIQ state */
|
||||
|
||||
static inline void up_irq_restore(irqstate_t flags)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"msr cpsr_c, %0"
|
||||
:
|
||||
: "r" (flags)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_ARM_INCLUDE_ARMV8_R_IRQ_H */
|
||||
@@ -50,6 +50,8 @@
|
||||
# include <arch/armv7-a/irq.h>
|
||||
#elif defined(CONFIG_ARCH_ARMV7R)
|
||||
# include <arch/armv7-r/irq.h>
|
||||
#elif defined(CONFIG_ARCH_ARMV8R)
|
||||
# include <arch/armv8-r/irq.h>
|
||||
#elif defined(CONFIG_ARCH_ARMV7M)
|
||||
# include <arch/armv7-m/irq.h>
|
||||
#elif defined(CONFIG_ARCH_ARMV8M)
|
||||
|
||||
@@ -25,6 +25,8 @@ ifeq ($(CONFIG_ARCH_ARMV7A),y) # ARMv7-A
|
||||
ARCH_SUBDIR = armv7-a
|
||||
else ifeq ($(CONFIG_ARCH_ARMV7R),y) # ARMv7-R
|
||||
ARCH_SUBDIR = armv7-r
|
||||
else ifeq ($(CONFIG_ARCH_ARMV8R),y) # ARMv8-R
|
||||
ARCH_SUBDIR = armv8-r
|
||||
else ifeq ($(CONFIG_ARCH_ARMV7M),y) # ARMv7-M
|
||||
ARCH_SUBDIR = armv7-m
|
||||
else ifeq ($(CONFIG_ARCH_ARMV8M),y) # ARMv8-M
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
comment "ARMv8-R Configuration Options"
|
||||
|
||||
config ARMV8R_HAVE_GICv3
|
||||
bool "ARMV7R_GICv3 support"
|
||||
select ARCH_HAVE_IRQTRIGGER
|
||||
default y
|
||||
---help---
|
||||
Selected by the configuration tool if the architecture supports the
|
||||
Generic Interrupt Controller (GIC)
|
||||
|
||||
if ARMV8R_HAVE_GICv2
|
||||
|
||||
config ARMV8R_GIC_EOIMODE
|
||||
bool
|
||||
default n
|
||||
---help---
|
||||
Enable GICC_CTLR.EOImode, this will separates the priority drop and interrupt
|
||||
deactivation operations.
|
||||
|
||||
endif # ARMV8R_GIC_EOIMODE
|
||||
|
||||
config ARMV8R_MEMINIT
|
||||
bool
|
||||
default y if BOOT_SDRAM_DATA
|
||||
default n if !BOOT_SDRAM_DATA
|
||||
---help---
|
||||
If this configuration *not* selected, then it is assumed that all
|
||||
memory resources are initialized via arm_data_initialize() and
|
||||
available at power-up reset time. Other memories, such as SDRAM or
|
||||
some ECC SRAM memories, require some platform-specific
|
||||
initialization first. In that case, this option should be selected
|
||||
and the platform-specific implementation of arm_boot() must perform
|
||||
the memory initialization first, then explicitly call
|
||||
arm_data_initialize().
|
||||
|
||||
config ARMV8R_HAVE_DECODEFIQ
|
||||
bool
|
||||
default n
|
||||
|
||||
config ARMV8R_DECODEFIQ
|
||||
bool "FIQ Handler"
|
||||
default n
|
||||
depends on ARMV7R_HAVE_DECODEFIQ
|
||||
---help---
|
||||
Select this option if your platform supports the function
|
||||
arm_decodefiq().
|
||||
|
||||
config ARMV8R_ALIGNMENT_TRAP
|
||||
bool "Enable Alignment Check at __start"
|
||||
default n
|
||||
|
||||
config ARMV8R_CACHE_ROUND_ROBIN
|
||||
bool "Enable Cache Round Robin Replacement Policy at __start"
|
||||
default n
|
||||
|
||||
config ARMV8R_DCACHE_DISABLE
|
||||
bool "Disable DCACHE at __start"
|
||||
default n
|
||||
|
||||
config ARMV8R_ICACHE_DISABLE
|
||||
bool "Disable ICACHE at __start"
|
||||
default n
|
||||
|
||||
config ARMV8R_SCTLR_CCP15BEN
|
||||
bool "Enable CP15 Barrier at __start"
|
||||
default y
|
||||
|
||||
config ARMV8R_BACKGROUND_REGION
|
||||
bool "Enable MPU Background region at __start"
|
||||
default y
|
||||
|
||||
config ARMV8R_DIV0_FAULT
|
||||
bool "Enable DIV0 Fault at __start"
|
||||
default n
|
||||
|
||||
config ARMV8R_FAST_INTERRUPT
|
||||
bool "Enable Fast Interrupts at __start"
|
||||
default n
|
||||
|
||||
config ARMV8R_NONMASKABLE_FIQ
|
||||
bool "Enable Non-maskable FIQ Support at __start"
|
||||
default n
|
||||
@@ -0,0 +1,52 @@
|
||||
############################################################################
|
||||
# arch/arm/src/armv8-r/Make.defs
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
# Common ARM files
|
||||
|
||||
include common/Make.defs
|
||||
|
||||
# The vector table is the "head" object, i.e., the one that must forced into
|
||||
# the link in order to draw in all of the other components
|
||||
|
||||
HEAD_ASRC += arm_vectortab.S
|
||||
|
||||
# Common assembly language files
|
||||
|
||||
CMN_CSRCS += arm_arch_timer.c arm_cache.c arm_cpuinfo.c arm_dataabort.c
|
||||
CMN_CSRCS += arm_doirq.c arm_gicv3.c
|
||||
CMN_CSRCS += arm_initialstate.c arm_prefetchabort.c
|
||||
CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c
|
||||
CMN_CSRCS += arm_syscall.c arm_tcbinfo.c arm_undefinedinsn.c
|
||||
CMN_CSRCS += arm_perf.c cp15_cacheops.c
|
||||
|
||||
# Common C source files
|
||||
|
||||
CMN_ASRCS += arm_head.S arm_vectoraddrexcptn.S arm_vectors.S
|
||||
CMN_ASRCS += arm_saveusercontext.S
|
||||
|
||||
# ifeq ($(CONFIG_BUILD_PROTECTED),y)
|
||||
# CMN_CSRCS += arm_mpu.c
|
||||
# endif
|
||||
|
||||
# ifeq ($(CONFIG_ARCH_FPU),y)
|
||||
# CMN_CSRCS += arm_fpucmp.c
|
||||
# CMN_ASRCS += arm_fpuconfig.S
|
||||
# endif
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
############################################################################
|
||||
# arch/arm/src/armv8-r/Toolchain.defs
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ARCHCPUFLAGS += -march=armv8-r
|
||||
|
||||
ifeq ($(CONFIG_ARCH_FPU),y)
|
||||
LLVM_ABITYPE := eabihf
|
||||
ARCHCPUFLAGS += -mfpu=vfpv3-d16
|
||||
ifeq ($(CONFIG_ARM_FPU_ABI_SOFT),y)
|
||||
ARCHCPUFLAGS += -mfloat-abi=softfp
|
||||
else
|
||||
ARCHCPUFLAGS += -mfloat-abi=hard
|
||||
endif
|
||||
else
|
||||
LLVM_ABITYPE := eabi
|
||||
ARCHCPUFLAGS += -mfloat-abi=soft
|
||||
endif
|
||||
|
||||
include $(TOPDIR)/arch/arm/src/common/Toolchain.defs
|
||||
@@ -0,0 +1,151 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* References:
|
||||
*
|
||||
* "ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition",
|
||||
* Copyright 1996-1998, 2000, 2004-2012 ARM.
|
||||
* All rights reserved. ARM DDI 0406C.c (ID051414)
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_ARMV8_R_ARM_H
|
||||
#define __ARCH_ARM_SRC_ARMV8_R_ARM_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
# include <nuttx/compiler.h>
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define BIT(n) ((1UL) << (n))
|
||||
#define BIT64(n) ((1ULL) << (n))
|
||||
|
||||
/* Bit mask with bits 0 through n-1 (inclusive) set,
|
||||
* or 0 if n is 0.
|
||||
*/
|
||||
#define BIT_MASK(n) (BIT(n) - 1)
|
||||
#define BIT64_MASK(n) (BIT64(n) - 1ULL)
|
||||
|
||||
/* ARMv8-R ******************************************************************/
|
||||
|
||||
/* PSR bits */
|
||||
|
||||
#define PSR_MODE_SHIFT (0) /* Bits 0-4: Mode fields */
|
||||
#define PSR_MODE_MASK (31 << PSR_MODE_SHIFT)
|
||||
# define PSR_MODE_USR (16 << PSR_MODE_SHIFT) /* User mode */
|
||||
# define PSR_MODE_FIQ (17 << PSR_MODE_SHIFT) /* FIQ mode */
|
||||
# define PSR_MODE_IRQ (18 << PSR_MODE_SHIFT) /* IRQ mode */
|
||||
# define PSR_MODE_SVC (19 << PSR_MODE_SHIFT) /* Supervisor mode */
|
||||
# define PSR_MODE_ABT (23 << PSR_MODE_SHIFT) /* Abort mode */
|
||||
# define PSR_MODE_HYP (26 << PSR_MODE_SHIFT) /* Hypervisor mode */
|
||||
# define PSR_MODE_UND (27 << PSR_MODE_SHIFT) /* Undefined mode */
|
||||
# define PSR_MODE_SYS (31 << PSR_MODE_SHIFT) /* System mode */
|
||||
|
||||
#define PSR_T_BIT (1 << 5) /* Bit 5: Thumb execution state bit */
|
||||
#define PSR_MASK_SHIFT (6) /* Bits 6-8: Mask Bits */
|
||||
#define PSR_MASK_MASK (7 << PSR_GE_SHIFT)
|
||||
# define PSR_F_BIT (1 << 6) /* Bit 6: FIQ mask bit */
|
||||
# define PSR_I_BIT (1 << 7) /* Bit 7: IRQ mask bit */
|
||||
# define PSR_A_BIT (1 << 8) /* Bit 8: Asynchronous abort mask */
|
||||
#define PSR_E_BIT (1 << 9) /* Bit 9: Endianness execution state bit */
|
||||
#define PSR_IT27_SHIFT (10) /* Bits 10-15: If-Then execution state bits IT[2:7] */
|
||||
#define PSR_IT27_MASK (0x3f << PSR_IT27_SHIFT)
|
||||
#define PSR_GE_SHIFT (16) /* Bits 16-19: Greater than or Equal flags */
|
||||
#define PSR_GE_MASK (15 << PSR_GE_SHIFT)
|
||||
/* Bits 20-23: Reserved. RAZ/SBZP */
|
||||
#define PSR_J_BIT (1 << 24) /* Bit 24: Jazelle state bit */
|
||||
#define PSR_IT01_SHIFT (25) /* Bits 25-26: If-Then execution state bits IT[0:1] */
|
||||
#define PSR_IT01_MASK (3 << PSR_IT01_SHIFT)
|
||||
#define PSR_Q_BIT (1 << 27) /* Bit 27: Cumulative saturation bit */
|
||||
#define PSR_V_BIT (1 << 28) /* Bit 28: Overflow condition flag */
|
||||
#define PSR_C_BIT (1 << 29) /* Bit 29: Carry condition flag */
|
||||
#define PSR_Z_BIT (1 << 30) /* Bit 30: Zero condition flag */
|
||||
#define PSR_N_BIT (1 << 31) /* Bit 31: Negative condition flag */
|
||||
|
||||
/****************************************************************************
|
||||
* Inline Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_boot
|
||||
*
|
||||
* Description:
|
||||
* Complete boot operations started in arm_head.S
|
||||
*
|
||||
* Boot Sequence
|
||||
*
|
||||
* 1. The __start entry point in armv8-r/arm_head.S is invoked upon power-
|
||||
* on reset.
|
||||
* 2. __start prepares CPU for code execution.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void arm_boot(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_data_initialize
|
||||
*
|
||||
* Description:
|
||||
* Clear all of .bss to zero; set .data to the correct initial values.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void arm_data_initialize(void);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_ARMV8_R_ARM_H */
|
||||
@@ -0,0 +1,421 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_arch_timer.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <debug.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <arch/irq.h>
|
||||
#include <arch/chip/chip.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
#include <nuttx/timers/arch_alarm.h>
|
||||
|
||||
#include "barriers.h"
|
||||
#include "cp15.h"
|
||||
#include "arm_gic.h"
|
||||
#include "arm_arch_timer.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct arm_oneshot_lowerhalf_s
|
||||
{
|
||||
/* This is the part of the lower half driver that is visible to the upper-
|
||||
* half client of the driver. This must be the first thing in this
|
||||
* structure so that pointers to struct oneshot_lowerhalf_s are cast
|
||||
* compatible to struct arm64_oneshot_lowerhalf_s and vice versa.
|
||||
*/
|
||||
|
||||
struct oneshot_lowerhalf_s lh; /* Common lower-half driver fields */
|
||||
|
||||
/* Private lower half data follows */
|
||||
|
||||
void *arg; /* Argument that is passed to the handler */
|
||||
uint64_t cycle_per_tick; /* cycle per tick */
|
||||
oneshot_callback_t callback; /* Internal handler that receives callback */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static inline void arm_arch_timer_set_compare(uint64_t value)
|
||||
{
|
||||
CP15_SET64(CNTV_CVAL, value);
|
||||
}
|
||||
|
||||
static inline uint64_t arm_arch_timer_get_compare(void)
|
||||
{
|
||||
return CP15_GET64(CNTV_CVAL);
|
||||
}
|
||||
|
||||
static inline void arm_arch_timer_enable(bool enable)
|
||||
{
|
||||
uint64_t value;
|
||||
|
||||
value = CP15_GET(CNTV_CTL);
|
||||
|
||||
if (enable)
|
||||
{
|
||||
value |= CNTV_CTL_ENABLE_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
value &= ~CNTV_CTL_ENABLE_BIT;
|
||||
}
|
||||
|
||||
CP15_SET(CNTV_CTL, value);
|
||||
}
|
||||
|
||||
static inline void arm_arch_timer_set_irq_mask(bool mask)
|
||||
{
|
||||
uint64_t value;
|
||||
|
||||
value = CP15_GET(CNTV_CTL);
|
||||
|
||||
if (mask)
|
||||
{
|
||||
value |= CNTV_CTL_IMASK_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
value &= ~CNTV_CTL_IMASK_BIT;
|
||||
}
|
||||
|
||||
CP15_SET(CNTV_CTL, value);
|
||||
}
|
||||
|
||||
static inline uint64_t arm_arch_timer_count(void)
|
||||
{
|
||||
return CP15_GET64(CNTVCT);
|
||||
}
|
||||
|
||||
static inline uint64_t arm_arch_timer_get_cntfrq(void)
|
||||
{
|
||||
return CP15_GET(CNTFRQ);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_arch_timer_compare_isr
|
||||
*
|
||||
* Description:
|
||||
* Common timer interrupt callback. When any oneshot timer interrupt
|
||||
* expires, this function will be called. It will forward the call to
|
||||
* the next level up.
|
||||
*
|
||||
* Input Parameters:
|
||||
* oneshot - The state associated with the expired timer
|
||||
*
|
||||
* Returned Value:
|
||||
* Always returns OK
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int arm_arch_timer_compare_isr(int irq, void *regs, void *arg)
|
||||
{
|
||||
struct arm_oneshot_lowerhalf_s *priv =
|
||||
(struct arm_oneshot_lowerhalf_s *)arg;
|
||||
|
||||
arm_arch_timer_set_irq_mask(true);
|
||||
|
||||
if (priv->callback)
|
||||
{
|
||||
/* Then perform the callback */
|
||||
|
||||
priv->callback(&priv->lh, priv->arg);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_tick_max_delay
|
||||
*
|
||||
* Description:
|
||||
* Determine the maximum delay of the one-shot timer (in microseconds)
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower An instance of the lower-half oneshot state structure. This
|
||||
* structure must have been previously initialized via a call to
|
||||
* oneshot_initialize();
|
||||
* ticks The location in which to return the maximum delay.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned
|
||||
* on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int arm_tick_max_delay(struct oneshot_lowerhalf_s *lower,
|
||||
clock_t *ticks)
|
||||
{
|
||||
DEBUGASSERT(ticks != NULL);
|
||||
|
||||
*ticks = (clock_t)UINT64_MAX;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_tick_cancel
|
||||
*
|
||||
* Description:
|
||||
* Cancel the oneshot timer and return the time remaining on the timer.
|
||||
*
|
||||
* NOTE: This function may execute at a high rate with no timer running (as
|
||||
* when pre-emption is enabled and disabled).
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower Caller allocated instance of the oneshot state structure. This
|
||||
* structure must have been previously initialized via a call to
|
||||
* oneshot_initialize();
|
||||
* ticks The location in which to return the time remaining on the
|
||||
* oneshot timer.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. A call to up_timer_cancel() when
|
||||
* the timer is not active should also return success; a negated errno
|
||||
* value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int arm_tick_cancel(struct oneshot_lowerhalf_s *lower,
|
||||
clock_t *ticks)
|
||||
{
|
||||
struct arm_oneshot_lowerhalf_s *priv =
|
||||
(struct arm_oneshot_lowerhalf_s *)lower;
|
||||
|
||||
DEBUGASSERT(priv != NULL && ticks != NULL);
|
||||
|
||||
/* Disable int */
|
||||
|
||||
arm_arch_timer_set_irq_mask(true);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_tick_start
|
||||
*
|
||||
* Description:
|
||||
* Start the oneshot timer
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower An instance of the lower-half oneshot state structure. This
|
||||
* structure must have been previously initialized via a call to
|
||||
* oneshot_initialize();
|
||||
* handler The function to call when when the oneshot timer expires.
|
||||
* arg An opaque argument that will accompany the callback.
|
||||
* ticks Provides the duration of the one shot timer.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned
|
||||
* on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int arm_tick_start(struct oneshot_lowerhalf_s *lower,
|
||||
oneshot_callback_t callback, void *arg,
|
||||
clock_t ticks)
|
||||
{
|
||||
struct arm_oneshot_lowerhalf_s *priv =
|
||||
(struct arm_oneshot_lowerhalf_s *)lower;
|
||||
|
||||
DEBUGASSERT(priv != NULL && callback != NULL);
|
||||
|
||||
/* Save the new handler and its argument */
|
||||
|
||||
priv->callback = callback;
|
||||
priv->arg = arg;
|
||||
|
||||
/* Set the timeout */
|
||||
|
||||
arm_arch_timer_set_compare(arm_arch_timer_count() +
|
||||
priv->cycle_per_tick * ticks);
|
||||
arm_arch_timer_set_irq_mask(false);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_tick_current
|
||||
*
|
||||
* Description:
|
||||
* Get the current time.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower Caller allocated instance of the oneshot state structure. This
|
||||
* structure must have been previously initialized via a call to
|
||||
* oneshot_initialize();
|
||||
* ticks The location in which to return the current time.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success, a negated errno value is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int arm_tick_current(struct oneshot_lowerhalf_s *lower,
|
||||
clock_t *ticks)
|
||||
{
|
||||
struct arm_oneshot_lowerhalf_s *priv =
|
||||
(struct arm_oneshot_lowerhalf_s *)lower;
|
||||
|
||||
DEBUGASSERT(ticks != NULL);
|
||||
|
||||
*ticks = arm_arch_timer_count() / priv->cycle_per_tick;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct oneshot_operations_s g_oneshot_ops =
|
||||
{
|
||||
.tick_start = arm_tick_start,
|
||||
.tick_current = arm_tick_current,
|
||||
.tick_max_delay = arm_tick_max_delay,
|
||||
.tick_cancel = arm_tick_cancel,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Name: oneshot_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the oneshot timer and return a oneshot lower half driver
|
||||
* instance.
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, a non-NULL instance of the oneshot lower-half driver is
|
||||
* returned. NULL is return on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static struct oneshot_lowerhalf_s *arm_oneshot_initialize(void)
|
||||
{
|
||||
struct arm_oneshot_lowerhalf_s *priv;
|
||||
|
||||
tmrinfo("oneshot_initialize\n");
|
||||
|
||||
/* Allocate an instance of the lower half driver */
|
||||
|
||||
priv = (struct arm_oneshot_lowerhalf_s *)
|
||||
kmm_zalloc(sizeof(struct arm_oneshot_lowerhalf_s));
|
||||
|
||||
if (priv == NULL)
|
||||
{
|
||||
tmrerr("ERROR: Failed to initialized state structure\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize the lower-half driver structure */
|
||||
|
||||
priv->lh.ops = &g_oneshot_ops;
|
||||
priv->cycle_per_tick = arm_arch_timer_get_cntfrq() / TICK_PER_SEC;
|
||||
tmrinfo("cycle_per_tick %" PRIu64 "\n", priv->cycle_per_tick);
|
||||
|
||||
/* Attach handler */
|
||||
|
||||
irq_attach(ARM_ARCH_TIMER_IRQ,
|
||||
arm_arch_timer_compare_isr, priv);
|
||||
|
||||
/* Enable int */
|
||||
|
||||
up_enable_irq(ARM_ARCH_TIMER_IRQ);
|
||||
|
||||
/* Start timer */
|
||||
|
||||
arm_arch_timer_enable(true);
|
||||
|
||||
tmrinfo("oneshot_initialize ok %p \n", &priv->lh);
|
||||
|
||||
return &priv->lh;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: up_timer_initialize
|
||||
*
|
||||
* Description:
|
||||
* This function is called during start-up to initialize the system timer
|
||||
* interrupt.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_timer_initialize(void)
|
||||
{
|
||||
uint64_t freq;
|
||||
|
||||
freq = arm_arch_timer_get_cntfrq();
|
||||
tmrinfo("%s: cp15 timer(s) running at %" PRIu64 ".%" PRIu64 "MHz\n",
|
||||
__func__, freq / 1000000, (freq / 10000) % 100);
|
||||
|
||||
up_alarm_set_lowerhalf(arm_oneshot_initialize());
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/****************************************************************************
|
||||
* Function: arm_arch_timer_secondary_init
|
||||
*
|
||||
* Description:
|
||||
* This function is called during start-up to initialize the system timer
|
||||
* interrupt for smp.
|
||||
*
|
||||
* Notes:
|
||||
* The origin design for ARMv8-A timer is assigned private timer to
|
||||
* every PE(CPU core), the ARM_ARCH_TIMER_IRQ is a PPI so it's
|
||||
* should be enable at every core.
|
||||
*
|
||||
* But for NuttX, it's design only for primary core to handle timer
|
||||
* interrupt and call nxsched_process_timer at timer tick mode.
|
||||
* So we need only enable timer for primary core
|
||||
*
|
||||
* IMX6 use GPT which is a SPI rather than generic timer to handle
|
||||
* timer interrupt
|
||||
****************************************************************************/
|
||||
|
||||
void arm_arch_timer_secondary_init()
|
||||
{
|
||||
#ifdef CONFIG_SCHED_TICKLESS
|
||||
tmrinfo("arm_arch_timer_secondary_init\n");
|
||||
|
||||
/* Enable int */
|
||||
|
||||
up_enable_irq(ARM_ARCH_TIMER_IRQ);
|
||||
|
||||
/* Start timer */
|
||||
|
||||
arm_arch_timer_enable(true);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,58 @@
|
||||
/****************************************************************************
|
||||
* arch/arm64/src/common/arm64_arch_timer.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_ARMV7_R_ARM_ARCH_TIMER_H
|
||||
#define __ARCH_ARM_SRC_ARMV7_R_ARM_ARCH_TIMER_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "arm_gic.h"
|
||||
#include "arm_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* CNTV_CVAL, Counter-timer Virtual Timer CompareValue register
|
||||
* CNTV_CTL, Counter-timer Virtual Timer Control register
|
||||
*/
|
||||
|
||||
#define CNTV_CTL_ENABLE_BIT BIT(0)
|
||||
#define CNTV_CTL_IMASK_BIT BIT(1)
|
||||
|
||||
#define CONFIG_ARM_TIMER_SECURE_IRQ (GIC_PPI_INT_BASE + 13)
|
||||
#define CONFIG_ARM_TIMER_NON_SECURE_IRQ (GIC_PPI_INT_BASE + 14)
|
||||
#define CONFIG_ARM_TIMER_VIRTUAL_IRQ (GIC_PPI_INT_BASE + 11)
|
||||
#define CONFIG_ARM_TIMER_HYP_IRQ (GIC_PPI_INT_BASE + 10)
|
||||
|
||||
#define ARM_ARCH_TIMER_IRQ CONFIG_ARM_TIMER_VIRTUAL_IRQ
|
||||
#define ARM_ARCH_TIMER_PRIO IRQ_DEFAULT_PRIORITY
|
||||
#define ARM_ARCH_TIMER_FLAGS IRQ_TYPE_LEVEL
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
#ifdef CONFIG_SMP
|
||||
void arm_arch_timer_secondary_init(void);
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_ARMV7_R_ARM_ARCH_TIMER_H */
|
||||
@@ -0,0 +1,450 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_cache.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/cache.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "cp15_cacheops.h"
|
||||
#include "barriers.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_ARCH_ICACHE) || defined(CONFIG_ARCH_DCACHE)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_cache_linesize
|
||||
*
|
||||
* Description:
|
||||
* Get cache linesize
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Cache line size
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static size_t up_get_cache_linesize(void)
|
||||
{
|
||||
static uint32_t clsize;
|
||||
|
||||
if (clsize == 0)
|
||||
{
|
||||
clsize = MAX(cp15_cache_linesize(), l2cc_get_linesize());
|
||||
}
|
||||
|
||||
return clsize;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_ICACHE
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_icache_linesize
|
||||
*
|
||||
* Description:
|
||||
* Get icache linesize
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Cache line size
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
size_t up_get_icache_linesize(void)
|
||||
{
|
||||
return up_get_cache_linesize();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_invalidate_icache_all
|
||||
*
|
||||
* Description:
|
||||
* Invalidate all instruction caches to PoU, also flushes branch target
|
||||
* cache
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_invalidate_icache_all(void)
|
||||
{
|
||||
cp15_invalidate_icache_all();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_invalidate_icache
|
||||
*
|
||||
* Description:
|
||||
* Validate the specified range instruction cache as PoU,
|
||||
* and flush the branch target cache
|
||||
*
|
||||
* Input Parameters:
|
||||
* start - virtual start address of region
|
||||
* end - virtual end address of region + 1
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_invalidate_icache(uintptr_t start, uintptr_t end)
|
||||
{
|
||||
cp15_invalidate_icache(start, end);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_enable_icache
|
||||
*
|
||||
* Description:
|
||||
* Enable the I-Cache
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_enable_icache(void)
|
||||
{
|
||||
cp15_enable_icache();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_disable_icache
|
||||
*
|
||||
* Description:
|
||||
* Disable the I-Cache
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_disable_icache(void)
|
||||
{
|
||||
cp15_disable_icache();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_ICACHE */
|
||||
|
||||
#ifdef CONFIG_ARCH_DCACHE
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_dcache_linesize
|
||||
*
|
||||
* Description:
|
||||
* Get dcache linesize
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Cache line size
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
size_t up_get_dcache_linesize(void)
|
||||
{
|
||||
return up_get_cache_linesize();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_invalidate_dcache
|
||||
*
|
||||
* Description:
|
||||
* Invalidate the data cache within the specified region; we will be
|
||||
* performing a DMA operation in this region and we want to purge old data
|
||||
* in the cache.
|
||||
*
|
||||
* Input Parameters:
|
||||
* start - virtual start address of region
|
||||
* end - virtual end address of region + 1
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* This operation is not atomic. This function assumes that the caller
|
||||
* has exclusive access to the address range so that no harm is done if
|
||||
* the operation is pre-empted.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_invalidate_dcache(uintptr_t start, uintptr_t end)
|
||||
{
|
||||
cp15_invalidate_dcache(start, end);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_invalidate_dcache_all
|
||||
*
|
||||
* Description:
|
||||
* Invalidate the entire contents of D cache.
|
||||
*
|
||||
* NOTE: This function forces L1 and L2 cache operations to be atomic
|
||||
* by disabling interrupts.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_invalidate_dcache_all(void)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_L2CACHE
|
||||
irqstate_t flags = enter_critical_section();
|
||||
cp15_invalidate_dcache_all();
|
||||
leave_critical_section(flags);
|
||||
#else
|
||||
cp15_invalidate_dcache_all();
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_clean_dcache
|
||||
*
|
||||
* Description:
|
||||
* Clean the data cache within the specified region by flushing the
|
||||
* contents of the data cache to memory.
|
||||
*
|
||||
* Input Parameters:
|
||||
* start - virtual start address of region
|
||||
* end - virtual end address of region + 1
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* This operation is not atomic. This function assumes that the caller
|
||||
* has exclusive access to the address range so that no harm is done if
|
||||
* the operation is pre-empted.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_clean_dcache(uintptr_t start, uintptr_t end)
|
||||
{
|
||||
if ((end - start) < cp15_cache_size())
|
||||
{
|
||||
cp15_clean_dcache(start, end);
|
||||
}
|
||||
else
|
||||
{
|
||||
cp15_clean_dcache_all();
|
||||
}
|
||||
|
||||
l2cc_clean(start, end);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_clean_dcache_all
|
||||
*
|
||||
* Description:
|
||||
* Clean the entire data cache within the specified region by flushing the
|
||||
* contents of the data cache to memory.
|
||||
*
|
||||
* NOTE: This operation is un-necessary if the DCACHE is configured in
|
||||
* write-through mode.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* This operation is not atomic. This function assumes that the caller
|
||||
* has exclusive access to the address range so that no harm is done if
|
||||
* the operation is pre-empted.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_clean_dcache_all(void)
|
||||
{
|
||||
cp15_clean_dcache_all();
|
||||
l2cc_clean_all();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_flush_dcache
|
||||
*
|
||||
* Description:
|
||||
* Flush the data cache within the specified region by cleaning and
|
||||
* invalidating the D cache.
|
||||
*
|
||||
* Input Parameters:
|
||||
* start - virtual start address of region
|
||||
* end - virtual end address of region + 1
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* This operation is not atomic. This function assumes that the caller
|
||||
* has exclusive access to the address range so that no harm is done if
|
||||
* the operation is pre-empted.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_flush_dcache(uintptr_t start, uintptr_t end)
|
||||
{
|
||||
if ((end - start) < cp15_cache_size())
|
||||
{
|
||||
cp15_flush_dcache(start, end);
|
||||
}
|
||||
else
|
||||
{
|
||||
cp15_flush_dcache_all();
|
||||
}
|
||||
|
||||
l2cc_flush(start, end);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_flush_dcache_all
|
||||
*
|
||||
* Description:
|
||||
* Flush the entire data cache by cleaning and invalidating the D cache.
|
||||
*
|
||||
* NOTE: If DCACHE write-through is configured, then this operation is the
|
||||
* same as up_invalidate_cache_all().
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Assumptions:
|
||||
* This operation is not atomic. This function assumes that the caller
|
||||
* has exclusive access to the address range so that no harm is done if
|
||||
* the operation is pre-empted.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_flush_dcache_all(void)
|
||||
{
|
||||
cp15_flush_dcache_all();
|
||||
l2cc_flush_all();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_enable_dcache
|
||||
*
|
||||
* Description:
|
||||
* Enable the D-Cache
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_enable_dcache(void)
|
||||
{
|
||||
cp15_enable_dcache();
|
||||
l2cc_enable();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_disable_dcache
|
||||
*
|
||||
* Description:
|
||||
* Disable the D-Cache
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_disable_dcache(void)
|
||||
{
|
||||
cp15_disable_dcache();
|
||||
l2cc_disable();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_coherent_dcache
|
||||
*
|
||||
* Description:
|
||||
* Ensure that the I and D caches are coherent within specified region
|
||||
* by cleaning the D cache (i.e., flushing the D cache contents to memory
|
||||
* and invalidating the I cache. This is typically used when code has been
|
||||
* written to a memory region, and will be executed.
|
||||
*
|
||||
* Input Parameters:
|
||||
* addr - virtual start address of region
|
||||
* len - Size of the address region in bytes
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_coherent_dcache(uintptr_t addr, size_t len)
|
||||
{
|
||||
if (len > 0)
|
||||
{
|
||||
/* Perform the operation on the L1 cache */
|
||||
|
||||
cp15_coherent_dcache(addr, addr + len);
|
||||
|
||||
#ifdef CONFIG_ARCH_L2CACHE
|
||||
/* If we have an L2 cache, then there more things that need to done */
|
||||
|
||||
# warning This is insufficient
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_DCACHE */
|
||||
@@ -0,0 +1,148 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_cpuinfo.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/fs/procfs.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "hwcap.h"
|
||||
#include "cp15.h"
|
||||
|
||||
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_CPUINFO)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* name: hwcap_extract_field
|
||||
****************************************************************************/
|
||||
|
||||
static int hwcap_extract_field(uint32_t features, int field)
|
||||
{
|
||||
int feature;
|
||||
|
||||
feature = (features >> field) & 0xf;
|
||||
if (feature > 7)
|
||||
{
|
||||
feature -= 16;
|
||||
}
|
||||
|
||||
return feature;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* name: up_show_cpuinfo
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t up_show_cpuinfo(FAR char *buf, size_t buf_size, off_t file_off)
|
||||
{
|
||||
int i;
|
||||
uint32_t cpuid;
|
||||
|
||||
for (i = 0; i < CONFIG_SMP_NCPUS; i++)
|
||||
{
|
||||
procfs_sprintf(buf, buf_size, &file_off, "processor\t: %d\n", i);
|
||||
procfs_sprintf(buf, buf_size, &file_off, "BogoMIPS\t: %u.%02u\n",
|
||||
(CONFIG_BOARD_LOOPSPERMSEC / 1000),
|
||||
(CONFIG_BOARD_LOOPSPERMSEC / 10) % 100);
|
||||
procfs_sprintf(buf, buf_size, &file_off, "cpu MHz\t\t: %lu.%02lu\n",
|
||||
up_perf_getfreq() / 1000000,
|
||||
(up_perf_getfreq() / 10000) % 100);
|
||||
|
||||
/* CPU Features */
|
||||
|
||||
procfs_sprintf(buf, buf_size, &file_off, "Features\t:");
|
||||
procfs_sprintf(buf, buf_size, &file_off, " %s %s %s",
|
||||
HWCAP_HALF, HWCAP_FAST_MULT, HWCAP_EDSP);
|
||||
|
||||
/* If the CPU supports LDREX/STREX and LDREXB/STREXB,
|
||||
* avoid advertising SWP; it may not be atomic with
|
||||
* multiprocessing cores.
|
||||
*/
|
||||
|
||||
if (hwcap_extract_field(CP15_GET(ID_ISAR3), 12) <= 1 &&
|
||||
hwcap_extract_field(CP15_GET(ID_ISAR4), 20) < 3)
|
||||
{
|
||||
procfs_sprintf(buf, buf_size, &file_off, " %s", HWCAP_SWP);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
if (hwcap_extract_field(CP15_GET(ID_ISAR0), 24) >= 1)
|
||||
{
|
||||
procfs_sprintf(buf, buf_size, &file_off, " %s", HWCAP_IDIVT);
|
||||
}
|
||||
|
||||
procfs_sprintf(buf, buf_size, &file_off, " %s", HWCAP_THUMB);
|
||||
#endif
|
||||
if (hwcap_extract_field(CP15_GET(ID_ISAR0), 24) == 2)
|
||||
{
|
||||
procfs_sprintf(buf, buf_size, &file_off, " %s", HWCAP_IDIVA);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_THREAD_LOCAL
|
||||
procfs_sprintf(buf, buf_size, &file_off, " %s", HWCAP_TLS);
|
||||
#endif
|
||||
|
||||
/* LPAE implies atomic ldrd/strd instructions */
|
||||
|
||||
if (hwcap_extract_field(CP15_GET(ID_ISAR2), 0) == 1)
|
||||
{
|
||||
procfs_sprintf(buf, buf_size, &file_off, " %s", HWCAP_LPAE);
|
||||
}
|
||||
|
||||
/* VFP Features */
|
||||
|
||||
#if defined(CONFIG_ARCH_FPU)
|
||||
procfs_sprintf(buf, buf_size, &file_off, " %s %s %s %s",
|
||||
HWCAP_VFPV3, HWCAP_FPSP, HWCAP_FPDP, HWCAP_VFPV3D16);
|
||||
#endif
|
||||
|
||||
/* Cpuid info */
|
||||
|
||||
cpuid = CP15_GET(MIDR);
|
||||
procfs_sprintf(buf, buf_size, &file_off,
|
||||
"\nmodel name\t: %s rev %" PRIx32 " (%s)\n"
|
||||
"CPU architecture: %s\n",
|
||||
"ARMv8 Processor", cpuid & 15, "v8", "8");
|
||||
|
||||
procfs_sprintf(buf, buf_size, &file_off,
|
||||
"CPU implementer\t: 0x%02" PRIx32 "\n"
|
||||
"CPU variant\t: 0x%" PRIx32 "\n"
|
||||
"CPU part\t: 0x%03" PRIx32 "\n"
|
||||
"CPU revision\t: %" PRIu32 "\n\n",
|
||||
cpuid >> 24,
|
||||
(cpuid >> 20) & 0xf,
|
||||
(cpuid >> 4) & 0xfff,
|
||||
cpuid & 0xf);
|
||||
}
|
||||
|
||||
return -file_off;
|
||||
}
|
||||
#endif /* CONFIG_FS_PROCFS && !CONFIG_FS_PROCFS_EXCLUDE_CPUINFO */
|
||||
@@ -0,0 +1,68 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_dataabort.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "arm_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_dataabort
|
||||
*
|
||||
* Input Parameters:
|
||||
* regs - The standard, ARM register save array.
|
||||
* dfar - Fault address register.
|
||||
* dfsr - Fault status register.
|
||||
*
|
||||
* Description:
|
||||
* This is the data abort exception handler. The ARM data abort exception
|
||||
* occurs when a memory fault is detected during a data transfer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr)
|
||||
{
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
|
||||
/* Crash -- possibly showing diagnostic debug information. */
|
||||
|
||||
_alert("Data abort. PC: %08x DFAR: %08x DFSR: %08x\n",
|
||||
regs[REG_PC], dfar, dfsr);
|
||||
PANIC_WITH_REGS("panic", regs);
|
||||
return regs; /* To keep the compiler happy */
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_doirq.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/board.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "arm_gic.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t *arm_doirq(int irq, uint32_t *regs)
|
||||
{
|
||||
board_autoled_on(LED_INIRQ);
|
||||
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
PANIC();
|
||||
#else
|
||||
/* Nested interrupts are not supported */
|
||||
|
||||
DEBUGASSERT(CURRENT_REGS == NULL);
|
||||
|
||||
/* Current regs non-zero indicates that we are processing an interrupt;
|
||||
* CURRENT_REGS is also used to manage interrupt level context switches.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
|
||||
/* Deliver the IRQ */
|
||||
|
||||
irq_dispatch(irq, regs);
|
||||
|
||||
/* Restore the cpu lock */
|
||||
|
||||
if (regs != CURRENT_REGS)
|
||||
{
|
||||
restore_critical_section();
|
||||
regs = (uint32_t *)CURRENT_REGS;
|
||||
}
|
||||
|
||||
/* Set CURRENT_REGS to NULL to indicate that we are no longer in an
|
||||
* interrupt handler.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = NULL;
|
||||
|
||||
board_autoled_off(LED_INIRQ);
|
||||
#endif
|
||||
return regs;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_irqinitialize
|
||||
*
|
||||
* Description:
|
||||
* This function is called by up_initialize() during the bring-up of the
|
||||
* system. It is the responsibility of this function to but the interrupt
|
||||
* subsystem into the working and ready state.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_irqinitialize(void)
|
||||
{
|
||||
/* The following operations need to be atomic, but since this function is
|
||||
* called early in the initialization sequence, we expect to have exclusive
|
||||
* access to the GIC.
|
||||
*/
|
||||
|
||||
/* Initialize the Generic Interrupt Controller (GIC) for CPU0 */
|
||||
|
||||
arm_gic_initialize(); /* Initialization common to all CPUs */
|
||||
|
||||
#ifndef CONFIG_SUPPRESS_INTERRUPTS
|
||||
|
||||
/* And finally, enable interrupts */
|
||||
|
||||
up_irq_enable();
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_gic.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_ARMV8_R_ARM_GIC_H
|
||||
#define __ARCH_ARM_SRC_ARMV8_R_ARM_GIC_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <arch/irq.h>
|
||||
#include <arch/chip/chip.h>
|
||||
|
||||
#include "arm.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* GIC Distributor register Interface Base Addresses
|
||||
* Arm® Generic Interrupt Controller Architecture Specification
|
||||
* GIC architecture version 3 and version 4
|
||||
*/
|
||||
|
||||
#define GIC_DIST_BASE CONFIG_GICD_BASE
|
||||
#define GICD_CTLR (GIC_DIST_BASE + 0x0)
|
||||
#define GICD_TYPER (GIC_DIST_BASE + 0x4)
|
||||
#define GICD_IIDR (GIC_DIST_BASE + 0x8)
|
||||
#define GICD_STATUSR (GIC_DIST_BASE + 0x10)
|
||||
#define GICD_SETSPI_NSR (GIC_DIST_BASE + 0x40)
|
||||
#define GICD_CLRSPI_NSR (GIC_DIST_BASE + 0x48)
|
||||
#define GICD_SETSPI_SR (GIC_DIST_BASE + 0x50)
|
||||
#define GICD_CLRSPI_SR (GIC_DIST_BASE + 0x58)
|
||||
#define GICD_IGROUPRn (GIC_DIST_BASE + 0x80)
|
||||
#define GICD_ISENABLERn (GIC_DIST_BASE + 0x100)
|
||||
#define GICD_ICENABLERn (GIC_DIST_BASE + 0x180)
|
||||
#define GICD_ISPENDRn (GIC_DIST_BASE + 0x200)
|
||||
#define GICD_ICPENDRn (GIC_DIST_BASE + 0x280)
|
||||
#define GICD_ISACTIVERn (GIC_DIST_BASE + 0x300)
|
||||
#define GICD_ICACTIVERn (GIC_DIST_BASE + 0x380)
|
||||
#define GICD_IPRIORITYRn (GIC_DIST_BASE + 0x400)
|
||||
#define GICD_ITARGETSRn (GIC_DIST_BASE + 0x800)
|
||||
#define GICD_ICFGRn (GIC_DIST_BASE + 0xc00)
|
||||
#define GICD_SGIR (GIC_DIST_BASE + 0xf00)
|
||||
#define GICD_IDREGS (GIC_DIST_BASE + 0xFFD0)
|
||||
#define GICD_PIDR2 (GIC_DIST_BASE + 0xFFE8)
|
||||
|
||||
/* Offsets from GICD base or GICR(n) SGI_base */
|
||||
|
||||
#define GIC_DIST_IGROUPR 0x0080
|
||||
#define GIC_DIST_ISENABLER 0x0100
|
||||
#define GIC_DIST_ICENABLER 0x0180
|
||||
#define GIC_DIST_ISPENDR 0x0200
|
||||
#define GIC_DIST_ICPENDR 0x0280
|
||||
#define GIC_DIST_ISACTIVER 0x0300
|
||||
#define GIC_DIST_ICACTIVER 0x0380
|
||||
#define GIC_DIST_IPRIORITYR 0x0400
|
||||
#define GIC_DIST_ITARGETSR 0x0800
|
||||
#define GIC_DIST_ICFGR 0x0c00
|
||||
#define GIC_DIST_IGROUPMODR 0x0d00
|
||||
#define GIC_DIST_SGIR 0x0f00
|
||||
|
||||
/* GICD GICR common access macros */
|
||||
|
||||
#define IGROUPR(base, n) (base + GIC_DIST_IGROUPR + (n) * 4)
|
||||
#define ISENABLER(base, n) (base + GIC_DIST_ISENABLER + (n) * 4)
|
||||
#define ICENABLER(base, n) (base + GIC_DIST_ICENABLER + (n) * 4)
|
||||
#define ISPENDR(base, n) (base + GIC_DIST_ISPENDR + (n) * 4)
|
||||
#define ICPENDR(base, n) (base + GIC_DIST_ICPENDR + (n) * 4)
|
||||
#define IPRIORITYR(base, n) (base + GIC_DIST_IPRIORITYR + n)
|
||||
#define ITARGETSR(base, n) (base + GIC_DIST_ITARGETSR + (n) * 4)
|
||||
#define ICFGR(base, n) (base + GIC_DIST_ICFGR + (n) * 4)
|
||||
#define IGROUPMODR(base, n) (base + GIC_DIST_IGROUPMODR + (n) * 4)
|
||||
|
||||
/* GICD_PIDR2 : Peripheral ID2 Register
|
||||
* bit assignments
|
||||
* [31:8] - IMPLEMENTATION DEFINED
|
||||
* [7:4] ArchRev 0x1. GICv1.
|
||||
* 0x2. GICv2.
|
||||
* 0x3. GICv3.
|
||||
* 0x4. GICv4.
|
||||
* [3:0] - IMPLEMENTATION DEFINED.
|
||||
*/
|
||||
#define GICD_PIDR2_ARCH_MASK 0xf0
|
||||
#define GICD_PIDR2_ARCH_GICV2 0x20
|
||||
#define GICD_PIDR2_ARCH_GICV3 0x30
|
||||
#define GICD_PIDR2_ARCH_GICV4 0x40
|
||||
|
||||
/* GICD_TYPER : Interrupt Controller Type Register
|
||||
* Arm® Generic Interrupt Controller Architecture Specification
|
||||
* GIC architecture version 3 and version 4
|
||||
*/
|
||||
#define GICD_TYPER_RSS BIT(26)
|
||||
#define GICD_TYPER_LPIS BIT(17)
|
||||
#define GICD_TYPER_MBIS BIT(16)
|
||||
#define GICD_TYPER_ESPI BIT(8)
|
||||
#define GICD_TYPER_ID_BITS(typer) ((((typer) >> 19) & 0x1f) + 1)
|
||||
#define GICD_TYPER_NUM_LPIS(typer) ((((typer) >> 11) & 0x1f) + 1)
|
||||
#define GICD_TYPER_SPIS(typer) ((((typer) & 0x1f) + 1) * 32)
|
||||
#define GICD_TYPER_ESPIS(typer) \
|
||||
(((typer) & GICD_TYPER_ESPI) ? GICD_TYPER_SPIS((typer) >> 27) : 0)
|
||||
|
||||
/* Common Helper Constants */
|
||||
#define GIC_SGI_INT_BASE 0
|
||||
#define GIC_PPI_INT_BASE 16
|
||||
#define GIC_IS_SGI(intid) (((intid) >= GIC_SGI_INT_BASE) && \
|
||||
((intid) < GIC_PPI_INT_BASE))
|
||||
|
||||
#define GIC_SPI_INT_BASE 32
|
||||
#define GIC_NUM_INTR_PER_REG 32
|
||||
#define GIC_NUM_CFG_PER_REG 16
|
||||
#define GIC_NUM_PRI_PER_REG 4
|
||||
|
||||
/* GIC idle priority : value '0xff' will allow all interrupts */
|
||||
|
||||
#define GIC_IDLE_PRIO 0xff
|
||||
|
||||
/* Priority levels 0:255 */
|
||||
|
||||
#define GIC_PRI_MASK 0xff
|
||||
|
||||
/* '0xa0'is used to initialize each interrtupt default priority.
|
||||
* This is an arbitrary value in current context.
|
||||
* Any value '0x80' to '0xff' will work for both NS and S state.
|
||||
* The values of individual interrupt and default has to be chosen
|
||||
* carefully if PMR and BPR based nesting and preemption has to be done.
|
||||
*/
|
||||
|
||||
#define GIC_INT_DEF_PRI_X4 0xa0a0a0a0
|
||||
|
||||
/* GICD_CTLR : Distributor Control Register
|
||||
*
|
||||
* [31](RO) RWP Register Write Pending:
|
||||
* -- 0 No register write in progress
|
||||
* -- 1 Register write in progress
|
||||
* [30:8] - Reserved -
|
||||
* [7](RW) E1NWF Enable 1 of N Wakeup Functionality 0
|
||||
* [6](RO) DS Disable Security status:
|
||||
* -- 0 The gicd_ctlr_ds signal was LOW when the GIC
|
||||
* exited reset. Therefore, the Distributor supports
|
||||
* two Security states and Non-secure accesses cannot
|
||||
* access and modify registers that control Group 0
|
||||
* interrupts.
|
||||
* -- 1 The gicd_ctlr_ds signal was HIGH when the GIC
|
||||
* exited reset. Therefore, the Distributor only supports
|
||||
* a single Security state and Non-secure accesses
|
||||
* can access and modify registers that control
|
||||
* Group 0 interrupts.
|
||||
* [5](RO) ARE_NS Affinity Routing Enable, Non-secure state
|
||||
* [4](RO) ARE_S Affinity Routing Enable, Secure state
|
||||
* [3] - Reserved -
|
||||
* [2](RW) EnableGrp1S Enable Secure Group 1 interrupts
|
||||
* [1](RW) EnableGrp1NS Enable Non-secure Group 1 interrupts
|
||||
* [0](RW) EnableGrp0 Enable Group 0 interrupts
|
||||
*/
|
||||
|
||||
#define GICD_CTLR_ENABLE_G0 0
|
||||
#define GICD_CTLR_ENABLE_G1NS 1
|
||||
#define GICD_CTLR_ENABLE_G1S 2
|
||||
#define GICD_CTRL_ARE_S 4
|
||||
#define GICD_CTRL_ARE_NS 5
|
||||
#define GICD_CTRL_DS 6
|
||||
#define GICD_CGRL_E1NWF 7
|
||||
|
||||
/* GICD_CTLR Register write progress bit */
|
||||
#define GICD_CTLR_RWP 31
|
||||
|
||||
/* GICR_CTLR */
|
||||
#define GICR_CTLR_ENABLE_LPIS BIT(0)
|
||||
#define GICR_CTLR_RWP 3
|
||||
|
||||
/* GICD_TYPER.ITLinesNumber 0:4 */
|
||||
#define GICD_TYPER_ITLINESNUM_MASK 0x1f
|
||||
|
||||
/* GICR: Re-Distributor registers, offsets from RD_base(n) */
|
||||
#define GICR_CTLR 0x0000
|
||||
#define GICR_IIDR 0x0004
|
||||
#define GICR_TYPER 0x0008
|
||||
#define GICR_STATUSR 0x0010
|
||||
#define GICR_WAKER 0x0014
|
||||
#define GICR_PWRR 0x0024
|
||||
#define GICR_SETLPIR 0x0040
|
||||
#define GICR_CLRLPIR 0x0048
|
||||
#define GICR_PROPBASER 0x0070
|
||||
#define GICR_PENDBASER 0x0078
|
||||
#define GICR_INVLPIR 0x00A0
|
||||
#define GICR_INVALLR 0x00B0
|
||||
#define GICR_SYNCR 0x00C0
|
||||
#define GICR_MOVLPIR 0x0100
|
||||
#define GICR_MOVALLR 0x0110
|
||||
#define GICR_IDREGS 0xFFD0
|
||||
#define GICR_PIDR2 0xFFE8
|
||||
|
||||
/* GICR_PIDR2 : Peripheral ID2 Register
|
||||
* bit assignments are the same as those for GICD_PIDR2)
|
||||
* [31:8] - IMPLEMENTATION DEFINED
|
||||
* [7:4] ArchRev 0x1. GICv1.
|
||||
* 0x2. GICv2.
|
||||
* 0x3. GICv3.
|
||||
* 0x4. GICv4.
|
||||
* [3:0] - IMPLEMENTATION DEFINED.
|
||||
*/
|
||||
|
||||
#define GICR_PIDR2_ARCH_MASK 0xf0
|
||||
#define GICR_PIDR2_ARCH_GICV3 0x30
|
||||
#define GICR_PIDR2_ARCH_GICV4 0x40
|
||||
|
||||
/* GICR_TYPER : Redistributor Type Register
|
||||
* Arm® Generic Interrupt Controller Architecture Specification
|
||||
* GIC architecture version 3 and version 4
|
||||
* chapter 9.11.35 for detail descriptions
|
||||
*/
|
||||
|
||||
#define GICR_TYPER_PLPIS BIT(0)
|
||||
#define GICR_TYPER_VLPIS BIT(1)
|
||||
#define GICR_TYPER_DIRECTLPIS BIT(3)
|
||||
#define GICR_TYPER_LAST BIT(4)
|
||||
|
||||
/* GICR_WAKER */
|
||||
#define GICR_WAKER_PS 1
|
||||
#define GICR_WAKER_CA 2
|
||||
|
||||
/* SGI base is at 64K offset from Redistributor */
|
||||
#define GICR_SGI_BASE_OFF 0x10000
|
||||
|
||||
/* GICD_ICFGR */
|
||||
#define GICD_ICFGR_MASK BIT_MASK(2)
|
||||
#define GICD_ICFGR_TYPE BIT(1)
|
||||
|
||||
/* BIT(0) reserved for IRQ_ZERO_LATENCY */
|
||||
#define IRQ_TYPE_LEVEL BIT(1)
|
||||
#define IRQ_TYPE_EDGE BIT(2)
|
||||
|
||||
#define GIC_SPI_INT_BASE 32
|
||||
#define GIC_SPI_MAX_INTID 1019
|
||||
#define GIC_IS_SPI(intid) (((intid) >= GIC_SPI_INT_BASE) && \
|
||||
((intid) <= GIC_SPI_MAX_INTID))
|
||||
|
||||
/* GITCD_IROUTER */
|
||||
#define GIC_DIST_IROUTER 0x6000
|
||||
#define IROUTER(base, n) (base + GIC_DIST_IROUTER + (n) * 8)
|
||||
|
||||
/* BIT(0) reserved for IRQ_ZERO_LATENCY */
|
||||
#define IRQ_TYPE_LEVEL BIT(1)
|
||||
#define IRQ_TYPE_EDGE BIT(2)
|
||||
|
||||
#define IRQ_DEFAULT_PRIORITY 0xa0
|
||||
|
||||
#define GIC_IRQ_SGI0 0
|
||||
#define GIC_IRQ_SGI1 1
|
||||
#define GIC_IRQ_SGI2 2
|
||||
#define GIC_IRQ_SGI3 3
|
||||
#define GIC_IRQ_SGI4 4
|
||||
#define GIC_IRQ_SGI5 5
|
||||
#define GIC_IRQ_SGI6 6
|
||||
#define GIC_IRQ_SGI7 7
|
||||
#define GIC_IRQ_SGI8 8
|
||||
#define GIC_IRQ_SGI9 9
|
||||
#define GIC_IRQ_SGI10 10
|
||||
#define GIC_IRQ_SGI11 11
|
||||
#define GIC_IRQ_SGI12 12
|
||||
#define GIC_IRQ_SGI13 13
|
||||
#define GIC_IRQ_SGI14 14
|
||||
#define GIC_IRQ_SGI15 15
|
||||
|
||||
/* register constants */
|
||||
#define ICC_SRE_ELX_SRE_BIT BIT(0)
|
||||
#define ICC_SRE_ELX_DFB_BIT BIT(1)
|
||||
#define ICC_SRE_ELX_DIB_BIT BIT(2)
|
||||
#define ICC_SRE_EL3_EN_BIT BIT(3)
|
||||
|
||||
/* ICC SGI macros */
|
||||
#define SGIR_TGT_MASK (0xffff)
|
||||
#define SGIR_AFF1_SHIFT (16)
|
||||
#define SGIR_AFF2_SHIFT (32)
|
||||
#define SGIR_AFF3_SHIFT (48)
|
||||
#define SGIR_AFF_MASK (0xf)
|
||||
#define SGIR_INTID_SHIFT (24)
|
||||
#define SGIR_INTID_MASK (0xf)
|
||||
#define SGIR_IRM_SHIFT (40)
|
||||
#define SGIR_IRM_MASK (0x1)
|
||||
#define SGIR_IRM_TO_AFF (0)
|
||||
#define SGIR_IRM_TO_ALL (1)
|
||||
|
||||
#define GICV3_SGIR_VALUE(_aff3, _aff2, _aff1, _intid, _irm, _tgt) \
|
||||
((((uint64_t)(_aff3) & SGIR_AFF_MASK) << SGIR_AFF3_SHIFT) | \
|
||||
(((uint64_t)(_irm) & SGIR_IRM_MASK) << SGIR_IRM_SHIFT) | \
|
||||
(((uint64_t)(_aff2) & SGIR_AFF_MASK) << SGIR_AFF2_SHIFT) | \
|
||||
(((_intid) & SGIR_INTID_MASK) << SGIR_INTID_SHIFT) | \
|
||||
(((_aff1) & SGIR_AFF_MASK) << SGIR_AFF1_SHIFT) | \
|
||||
((_tgt) & SGIR_TGT_MASK))
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
bool arm_gic_irq_is_enabled(unsigned int intid);
|
||||
int arm_gic_initialize(void);
|
||||
void arm_gic_irq_set_priority(unsigned int intid, unsigned int prio,
|
||||
uint32_t flags);
|
||||
int arm_gic_irq_trigger(unsigned int intid, uint32_t flags);
|
||||
|
||||
int arm_gic_raise_sgi(unsigned int sgi_id, uint16_t target_list);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_pause_handler
|
||||
*
|
||||
* Description:
|
||||
* This is the handler for SGI2. It performs the following operations:
|
||||
*
|
||||
* 1. It saves the current task state at the head of the current assigned
|
||||
* task list.
|
||||
* 2. It waits on a spinlock, then
|
||||
* 3. Returns from interrupt, restoring the state of the new task at the
|
||||
* head of the ready to run list.
|
||||
*
|
||||
* Input Parameters:
|
||||
* Standard interrupt handling
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int arm_pause_handler(int irq, void *context, void *arg);
|
||||
|
||||
void arm_gic_secondary_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_get_mpid
|
||||
*
|
||||
* Description:
|
||||
* The function from cpu index to get cpu mpid which is reading
|
||||
* from mpidr_el1 register. Different ARM64 Core will use different
|
||||
* Affn define, the mpidr_el1 value is not CPU number, So we need
|
||||
* to change CPU number to mpid and vice versa
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
uint64_t arm_get_mpid(int cpu);
|
||||
#else
|
||||
# define arm_get_mpid(cpu) GET_MPIDR()
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_ARMV8_R_ARM_GIC_H */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,154 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_initialstate.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "arm.h"
|
||||
#include "arm_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_initial_state
|
||||
*
|
||||
* Description:
|
||||
* A new thread is being started and a new TCB has been created. This
|
||||
* function is called to initialize the processor specific portions of
|
||||
* the new TCB.
|
||||
*
|
||||
* This function must setup the initial architecture registers and/or
|
||||
* stack so that execution will begin at tcb->start on the next context
|
||||
* switch.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_initial_state(struct tcb_s *tcb)
|
||||
{
|
||||
struct xcptcontext *xcp = &tcb->xcp;
|
||||
uint32_t cpsr;
|
||||
|
||||
/* Initialize the initial exception register context structure */
|
||||
|
||||
memset(xcp, 0, sizeof(struct xcptcontext));
|
||||
|
||||
/* Initialize the idle thread stack */
|
||||
|
||||
if (tcb->pid == IDLE_PROCESS_ID)
|
||||
{
|
||||
tcb->stack_alloc_ptr = (void *)(g_idle_topstack -
|
||||
CONFIG_IDLETHREAD_STACKSIZE);
|
||||
tcb->stack_base_ptr = tcb->stack_alloc_ptr;
|
||||
tcb->adj_stack_size = CONFIG_IDLETHREAD_STACKSIZE;
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
/* If stack debug is enabled, then fill the stack with a
|
||||
* recognizable value that we can use later to test for high
|
||||
* water marks.
|
||||
*/
|
||||
|
||||
arm_stack_color(tcb->stack_alloc_ptr, 0);
|
||||
#endif /* CONFIG_STACK_COLORATION */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize the context registers to stack top */
|
||||
|
||||
xcp->regs = (void *)((uint32_t)tcb->stack_base_ptr +
|
||||
tcb->adj_stack_size -
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
/* Initialize the xcp registers */
|
||||
|
||||
memset(xcp->regs, 0, XCPTCONTEXT_SIZE);
|
||||
|
||||
/* Save the initial stack pointer */
|
||||
|
||||
xcp->regs[REG_SP] = (uint32_t)tcb->stack_base_ptr +
|
||||
tcb->adj_stack_size;
|
||||
|
||||
/* Save the task entry point */
|
||||
|
||||
xcp->regs[REG_PC] = (uint32_t)tcb->start;
|
||||
|
||||
/* If this task is running PIC, then set the PIC base register to the
|
||||
* address of the allocated D-Space region.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PIC
|
||||
if (tcb->dspace != NULL)
|
||||
{
|
||||
/* Set the PIC base register (probably R10) to the address of the
|
||||
* alloacated D-Space region.
|
||||
*/
|
||||
|
||||
xcp->regs[REG_PIC] = (uint32_t)tcb->dspace->region;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set supervisor-mode and disable FIQs, regardless of how NuttX is
|
||||
* configured and of what kind of thread is being started. That is
|
||||
* because all threads, even user-mode threads will start in kernel
|
||||
* trampoline at nxtask_start() or pthread_start(). The thread's
|
||||
* privileges will be dropped before transitioning to user code.
|
||||
*/
|
||||
|
||||
cpsr = PSR_MODE_SYS;
|
||||
|
||||
/* Enable or disable interrupts, based on user configuration */
|
||||
|
||||
#ifdef CONFIG_SUPPRESS_INTERRUPTS
|
||||
/* Disable interrupts (both IRQs and FIQs) */
|
||||
|
||||
cpsr |= (PSR_I_BIT | PSR_F_BIT);
|
||||
|
||||
#else /* CONFIG_SUPPRESS_INTERRUPTS */
|
||||
/* Leave IRQs enabled (Also FIQs if CONFIG_ARMV7R_DECODEFIQ is selected) */
|
||||
|
||||
#ifndef CONFIG_ARMV8R_DECODEFIQ
|
||||
|
||||
cpsr |= PSR_F_BIT;
|
||||
|
||||
#endif /* !CONFIG_ARMV7R_DECODEFIQ */
|
||||
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
cpsr |= PSR_T_BIT;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
|
||||
cpsr |= PSR_E_BIT;
|
||||
|
||||
#endif /* CONFIG_ENDIAN_BIG */
|
||||
#endif /* CONFIG_SUPPRESS_INTERRUPTS */
|
||||
|
||||
xcp->regs[REG_CPSR] = cpsr;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_perf.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/clock.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "sctlr.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static unsigned long g_cpu_freq;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_perf_*
|
||||
*
|
||||
* Description:
|
||||
* The first interface simply provides the current time value in unknown
|
||||
* units. NOTE: This function may be called early before the timer has
|
||||
* been initialized. In that event, the function should just return a
|
||||
* start time of zero.
|
||||
*
|
||||
* Nothing is assumed about the units of this time value. The following
|
||||
* are assumed, however: (1) The time is an unsigned integer value, (2)
|
||||
* the time is monotonically increasing, and (3) the elapsed time (also
|
||||
* in unknown units) can be obtained by subtracting a start time from
|
||||
* the current time.
|
||||
*
|
||||
* The second interface simple converts an elapsed time into well known
|
||||
* units.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_perf_init(void *arg)
|
||||
{
|
||||
g_cpu_freq = (unsigned long)(uintptr_t)arg;
|
||||
|
||||
cp15_pmu_uer(PMUER_UME);
|
||||
cp15_pmu_pmcr(PMCR_E);
|
||||
cp15_pmu_cesr(PMCESR_CCES);
|
||||
}
|
||||
|
||||
unsigned long up_perf_getfreq(void)
|
||||
{
|
||||
return g_cpu_freq;
|
||||
}
|
||||
|
||||
unsigned long up_perf_gettime(void)
|
||||
{
|
||||
return cp15_pmu_rdccr();
|
||||
}
|
||||
|
||||
void up_perf_convert(unsigned long elapsed, struct timespec *ts)
|
||||
{
|
||||
unsigned long left;
|
||||
|
||||
ts->tv_sec = elapsed / g_cpu_freq;
|
||||
left = elapsed - ts->tv_sec * g_cpu_freq;
|
||||
ts->tv_nsec = NSEC_PER_SEC * (uint64_t)left / g_cpu_freq;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_prefetchabort.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "arm_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_prefetchabort
|
||||
*
|
||||
* Description:
|
||||
* This is the prefetch abort exception handler. The ARM prefetch abort
|
||||
* exception occurs when a memory fault is detected during an an
|
||||
* instruction fetch.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t *arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr)
|
||||
{
|
||||
/* Save the saved processor context in CURRENT_REGS where it can be
|
||||
* accessed for register dumps and possibly context switching.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = regs;
|
||||
|
||||
/* Crash -- possibly showing diagnostic debug information. */
|
||||
|
||||
_alert("Prefetch abort. PC: %08x IFAR: %08x IFSR: %08x\n",
|
||||
regs[REG_PC], ifar, ifsr);
|
||||
PANIC_WITH_REGS("panic", regs);
|
||||
return regs; /* To keep the compiler happy */
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_saveusercontext.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
.file "arm_saveusercontext.S"
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
.arm
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_saveusercontext
|
||||
*
|
||||
* Description:
|
||||
* Save the current context. Full prototype is:
|
||||
*
|
||||
* int up_saveusercontext(void *saveregs);
|
||||
*
|
||||
* R0 = saveregs = pinter saved array
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.globl up_saveusercontext
|
||||
.globl up_saveusercontext
|
||||
.type up_saveusercontext, %function
|
||||
|
||||
up_saveusercontext:
|
||||
|
||||
/* Save r0, r1 */
|
||||
|
||||
str r0, [r0, #(4*REG_R0)]
|
||||
str r1, [r0, #(4*REG_R1)]
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
/* Save fpu */
|
||||
|
||||
# ifdef CONFIG_ARM_DPFPU32
|
||||
vstmia.64 r0!, {d0-d15}
|
||||
vstmia.64 r0!, {d16-d31}
|
||||
# else
|
||||
vstmia r0!, {s0-s31}
|
||||
# endif
|
||||
/* Save fpscr, r13 and r14 */
|
||||
|
||||
vmrs r1, fpscr
|
||||
stmia r0!, {r1, r13, r14}
|
||||
#else
|
||||
/* Save r13, r14 */
|
||||
|
||||
stmia r0!, {r13, r14}
|
||||
#endif
|
||||
|
||||
/* Save r2~r12, and store the return address as PC */
|
||||
|
||||
add r0, r0, #8
|
||||
stmia r0!, {r2-r12, r14}
|
||||
|
||||
/* Save cpsr */
|
||||
|
||||
mrs r1, CPSR
|
||||
str r1, [r0]
|
||||
|
||||
mov r0, #0
|
||||
bx lr
|
||||
|
||||
.size up_saveusercontext, . - up_saveusercontext
|
||||
.end
|
||||
@@ -0,0 +1,426 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_schedulesigaction.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sched.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "arm.h"
|
||||
#include "sched/sched.h"
|
||||
#include "arm_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_schedule_sigaction
|
||||
*
|
||||
* Description:
|
||||
* This function is called by the OS when one or more
|
||||
* signal handling actions have been queued for execution.
|
||||
* The architecture specific code must configure things so
|
||||
* that the 'sigdeliver' callback is executed on the thread
|
||||
* specified by 'tcb' as soon as possible.
|
||||
*
|
||||
* This function may be called from interrupt handling logic.
|
||||
*
|
||||
* This operation should not cause the task to be unblocked
|
||||
* nor should it cause any immediate execution of sigdeliver.
|
||||
* Typically, a few cases need to be considered:
|
||||
*
|
||||
* (1) This function may be called from an interrupt handler
|
||||
* During interrupt processing, all xcptcontext structures
|
||||
* should be valid for all tasks. That structure should
|
||||
* be modified to invoke sigdeliver() either on return
|
||||
* from (this) interrupt or on some subsequent context
|
||||
* switch to the recipient task.
|
||||
* (2) If not in an interrupt handler and the tcb is NOT
|
||||
* the currently executing task, then again just modify
|
||||
* the saved xcptcontext structure for the recipient
|
||||
* task so it will invoke sigdeliver when that task is
|
||||
* later resumed.
|
||||
* (3) If not in an interrupt handler and the tcb IS the
|
||||
* currently executing task -- just call the signal
|
||||
* handler now.
|
||||
*
|
||||
* Assumptions:
|
||||
* Called from critical section
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
{
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
|
||||
if (!tcb->xcp.sigdeliver)
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to the currently executing task.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
|
||||
if (tcb == this_task())
|
||||
{
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signalling itself for some reason.
|
||||
*/
|
||||
|
||||
if (!CURRENT_REGS)
|
||||
{
|
||||
/* In this case just deliver the signal now. */
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: We are in an interrupt handler AND the interrupted
|
||||
* task is the same as the one that must receive the signal, then
|
||||
* we will have to modify the return state as well as the state
|
||||
* in the TCB.
|
||||
*
|
||||
* Hmmm... there looks like a latent bug here: The following logic
|
||||
* would fail in the strange case where we are in an interrupt
|
||||
* handler, the thread is signalling itself, but a context switch
|
||||
* to another task has occurred so that CURRENT_REGS does not
|
||||
* refer to the thread of this_task()!
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register
|
||||
* These will be restored by the signal trampoline after
|
||||
* the signals have been delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the same
|
||||
* as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_E_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signalling some non-running task.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register. These
|
||||
* will be restored by the signal trampoline after the signals
|
||||
* have been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ENDIAN_BIG
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_E_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
||||
{
|
||||
int cpu;
|
||||
int me;
|
||||
|
||||
sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
|
||||
|
||||
/* Refuse to handle nested signal actions */
|
||||
|
||||
if (!tcb->xcp.sigdeliver)
|
||||
{
|
||||
tcb->xcp.sigdeliver = sigdeliver;
|
||||
|
||||
/* First, handle some special cases when the signal is being delivered
|
||||
* to task that is currently executing on any CPU.
|
||||
*/
|
||||
|
||||
sinfo("rtcb=%p CURRENT_REGS=%p\n", this_task(), CURRENT_REGS);
|
||||
|
||||
if (tcb->task_state == TSTATE_TASK_RUNNING)
|
||||
{
|
||||
me = this_cpu();
|
||||
cpu = tcb->cpu;
|
||||
|
||||
/* CASE 1: We are not in an interrupt handler and a task is
|
||||
* signaling itself for some reason.
|
||||
*/
|
||||
|
||||
if (cpu == me && !CURRENT_REGS)
|
||||
{
|
||||
/* In this case just deliver the signal now.
|
||||
* REVISIT: Signal handler will run in a critical section!
|
||||
*/
|
||||
|
||||
sigdeliver(tcb);
|
||||
tcb->xcp.sigdeliver = NULL;
|
||||
}
|
||||
|
||||
/* CASE 2: The task that needs to receive the signal is running.
|
||||
* This could happen if the task is running on another CPU OR if
|
||||
* we are in an interrupt handler and the task is running on this
|
||||
* CPU. In the former case, we will have to PAUSE the other CPU
|
||||
* first. But in either case, we will have to modify the return
|
||||
* state as well as the state in the TCB.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* If we signaling a task running on the other CPU, we have
|
||||
* to PAUSE the other CPU.
|
||||
*/
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
/* Pause the CPU */
|
||||
|
||||
up_cpu_pause(cpu);
|
||||
|
||||
/* Wait while the pause request is pending */
|
||||
|
||||
while (up_cpu_pausereq(cpu))
|
||||
{
|
||||
}
|
||||
|
||||
/* Now tcb on the other CPU can be accessed safely */
|
||||
|
||||
/* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* tcb is running on the same CPU */
|
||||
|
||||
/* Save the return PC, CPSR and either the BASEPRI or
|
||||
* PRIMASK registers (and perhaps also the LR). These will
|
||||
* be restored by the signal trampoline after the signal
|
||||
* has been delivered.
|
||||
*/
|
||||
|
||||
/* And make sure that the saved context in the TCB is the
|
||||
* same as the interrupt return context.
|
||||
*/
|
||||
|
||||
arm_savestate(tcb->xcp.saved_regs);
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has
|
||||
* been delivered.
|
||||
*/
|
||||
|
||||
CURRENT_REGS = (void *)
|
||||
((uint32_t)CURRENT_REGS -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
CURRENT_REGS[REG_SP] = (uint32_t)CURRENT_REGS +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Then set up vector to the trampoline with interrupts
|
||||
* disabled. The kernel-space trampoline must run in
|
||||
* privileged thread mode.
|
||||
*/
|
||||
|
||||
CURRENT_REGS[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
CURRENT_REGS[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
|
||||
PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
CURRENT_REGS[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Increment the IRQ lock count so that when the task is
|
||||
* restarted, it will hold the IRQ spinlock.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(tcb->irqcount < INT16_MAX);
|
||||
tcb->irqcount++;
|
||||
|
||||
/* NOTE: If the task runs on another CPU(cpu), adjusting
|
||||
* global IRQ controls will be done in the pause handler
|
||||
* on the CPU(cpu) by taking a critical section.
|
||||
* If the task is scheduled on this CPU(me), do nothing
|
||||
* because this CPU already took a critical section
|
||||
*/
|
||||
|
||||
/* RESUME the other CPU if it was PAUSED */
|
||||
|
||||
if (cpu != me)
|
||||
{
|
||||
up_cpu_resume(cpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, we are (1) signaling a task is not running from an
|
||||
* interrupt handler or (2) we are not in an interrupt handler and the
|
||||
* running task is signaling some other non-running task.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
/* Save the return lr and cpsr and one scratch register. These
|
||||
* will be restored by the signal trampoline after the signals
|
||||
* have been delivered.
|
||||
*/
|
||||
|
||||
/* Save the current register context location */
|
||||
|
||||
tcb->xcp.saved_regs = tcb->xcp.regs;
|
||||
|
||||
/* Duplicate the register context. These will be
|
||||
* restored by the signal trampoline after the signal has been
|
||||
* delivered.
|
||||
*/
|
||||
|
||||
tcb->xcp.regs = (void *)
|
||||
((uint32_t)tcb->xcp.regs -
|
||||
XCPTCONTEXT_SIZE);
|
||||
memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
|
||||
|
||||
tcb->xcp.regs[REG_SP] = (uint32_t)tcb->xcp.regs +
|
||||
XCPTCONTEXT_SIZE;
|
||||
|
||||
/* Increment the IRQ lock count so that when the task is restarted,
|
||||
* it will hold the IRQ spinlock.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(tcb->irqcount < INT16_MAX);
|
||||
tcb->irqcount++;
|
||||
|
||||
/* Then set up to vector to the trampoline with interrupts
|
||||
* disabled
|
||||
*/
|
||||
|
||||
tcb->xcp.regs[REG_PC] = (uint32_t)arm_sigdeliver;
|
||||
tcb->xcp.regs[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,155 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_sigdeliver.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sched.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/board.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "arm_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_sigdeliver
|
||||
*
|
||||
* Description:
|
||||
* This is the a signal handling trampoline. When a signal action was
|
||||
* posted. The task context was mucked with and forced to branch to this
|
||||
* location with interrupts disabled.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void arm_sigdeliver(void)
|
||||
{
|
||||
struct tcb_s *rtcb = this_task();
|
||||
uint32_t *regs = rtcb->xcp.saved_regs;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* In the SMP case, we must terminate the critical section while the signal
|
||||
* handler executes, but we also need to restore the irqcount when the
|
||||
* we resume the main thread of the task.
|
||||
*/
|
||||
|
||||
int16_t saved_irqcount;
|
||||
#endif
|
||||
|
||||
board_autoled_on(LED_SIGNAL);
|
||||
|
||||
sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n",
|
||||
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
|
||||
|
||||
retry:
|
||||
#ifdef CONFIG_SMP
|
||||
/* In the SMP case, up_schedule_sigaction(0) will have incremented
|
||||
* 'irqcount' in order to force us into a critical section. Save the
|
||||
* pre-incremented irqcount.
|
||||
*/
|
||||
|
||||
saved_irqcount = rtcb->irqcount;
|
||||
DEBUGASSERT(saved_irqcount >= 1);
|
||||
|
||||
/* Now we need call leave_critical_section() repeatedly to get the irqcount
|
||||
* to zero, freeing all global spinlocks that enforce the critical section.
|
||||
*/
|
||||
|
||||
do
|
||||
{
|
||||
leave_critical_section(regs[REG_CPSR]);
|
||||
}
|
||||
while (rtcb->irqcount > 0);
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
#ifndef CONFIG_SUPPRESS_INTERRUPTS
|
||||
/* Then make sure that interrupts are enabled. Signal handlers must always
|
||||
* run with interrupts enabled.
|
||||
*/
|
||||
|
||||
up_irq_enable();
|
||||
#endif
|
||||
|
||||
/* Deliver the signal */
|
||||
|
||||
((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb);
|
||||
|
||||
/* Output any debug messages BEFORE restoring errno (because they may
|
||||
* alter errno), then disable interrupts again and restore the original
|
||||
* errno that is needed by the user logic (it is probably EINTR).
|
||||
*/
|
||||
|
||||
sinfo("Resuming\n");
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Restore the saved 'irqcount' and recover the critical section
|
||||
* spinlocks.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(rtcb->irqcount == 0);
|
||||
while (rtcb->irqcount < saved_irqcount)
|
||||
{
|
||||
enter_critical_section();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SUPPRESS_INTERRUPTS
|
||||
up_irq_save();
|
||||
#endif
|
||||
|
||||
if (!sq_empty(&rtcb->sigpendactionq) &&
|
||||
(rtcb->flags & TCB_FLAG_SIGNAL_ACTION) == 0)
|
||||
{
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Modify the saved return state with the actual saved values in the
|
||||
* TCB. This depends on the fact that nested signal handling is
|
||||
* not supported. Therefore, these values will persist throughout the
|
||||
* signal handling action.
|
||||
*
|
||||
* Keeping this data in the TCB resolves a security problem in protected
|
||||
* and kernel mode: The regs[] array is visible on the user stack and
|
||||
* could be modified by a hostile program.
|
||||
*/
|
||||
|
||||
rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */
|
||||
|
||||
/* Then restore the correct state for this thread of execution. */
|
||||
|
||||
board_autoled_off(LED_SIGNAL);
|
||||
#ifdef CONFIG_SMP
|
||||
rtcb->irqcount--;
|
||||
#endif
|
||||
arm_fullcontextrestore(regs);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,122 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_tcbinfo.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#ifdef CONFIG_DEBUG_TCBINFO
|
||||
|
||||
#include <nuttx/sched.h>
|
||||
#include <arch/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const uint16_t g_reg_offs[] =
|
||||
{
|
||||
TCB_REG_OFF(REG_R0),
|
||||
TCB_REG_OFF(REG_R1),
|
||||
TCB_REG_OFF(REG_R2),
|
||||
TCB_REG_OFF(REG_R3),
|
||||
TCB_REG_OFF(REG_R4),
|
||||
TCB_REG_OFF(REG_R5),
|
||||
TCB_REG_OFF(REG_R6),
|
||||
TCB_REG_OFF(REG_R7),
|
||||
TCB_REG_OFF(REG_R8),
|
||||
TCB_REG_OFF(REG_R9),
|
||||
TCB_REG_OFF(REG_R10),
|
||||
TCB_REG_OFF(REG_R11),
|
||||
TCB_REG_OFF(REG_R12),
|
||||
TCB_REG_OFF(REG_R13),
|
||||
TCB_REG_OFF(REG_R14),
|
||||
TCB_REG_OFF(REG_R15),
|
||||
TCB_REG_OFF(REG_CPSR),
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
TCB_REG_OFF(REG_D0),
|
||||
TCB_REG_OFF(REG_D1),
|
||||
TCB_REG_OFF(REG_D2),
|
||||
TCB_REG_OFF(REG_D3),
|
||||
TCB_REG_OFF(REG_D4),
|
||||
TCB_REG_OFF(REG_D5),
|
||||
TCB_REG_OFF(REG_D6),
|
||||
TCB_REG_OFF(REG_D7),
|
||||
TCB_REG_OFF(REG_D8),
|
||||
TCB_REG_OFF(REG_D9),
|
||||
TCB_REG_OFF(REG_D10),
|
||||
TCB_REG_OFF(REG_D11),
|
||||
TCB_REG_OFF(REG_D12),
|
||||
TCB_REG_OFF(REG_D13),
|
||||
TCB_REG_OFF(REG_D14),
|
||||
TCB_REG_OFF(REG_D15),
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM_DPFPU32
|
||||
TCB_REG_OFF(REG_D16),
|
||||
TCB_REG_OFF(REG_D17),
|
||||
TCB_REG_OFF(REG_D18),
|
||||
TCB_REG_OFF(REG_D19),
|
||||
TCB_REG_OFF(REG_D20),
|
||||
TCB_REG_OFF(REG_D21),
|
||||
TCB_REG_OFF(REG_D22),
|
||||
TCB_REG_OFF(REG_D23),
|
||||
TCB_REG_OFF(REG_D24),
|
||||
TCB_REG_OFF(REG_D25),
|
||||
TCB_REG_OFF(REG_D26),
|
||||
TCB_REG_OFF(REG_D27),
|
||||
TCB_REG_OFF(REG_D28),
|
||||
TCB_REG_OFF(REG_D29),
|
||||
TCB_REG_OFF(REG_D30),
|
||||
TCB_REG_OFF(REG_D31),
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
TCB_REG_OFF(REG_FPSCR),
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
const struct tcbinfo_s g_tcbinfo =
|
||||
{
|
||||
.pid_off = TCB_PID_OFF,
|
||||
.state_off = TCB_STATE_OFF,
|
||||
.pri_off = TCB_PRI_OFF,
|
||||
.name_off = TCB_NAME_OFF,
|
||||
.regs_off = TCB_REGS_OFF,
|
||||
.basic_num = 17,
|
||||
.total_num = sizeof(g_reg_offs) / sizeof(g_reg_offs[0]),
|
||||
{
|
||||
.p = g_reg_offs,
|
||||
},
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_undefinedinsn.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_undefinedinsn
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t *arm_undefinedinsn(uint32_t *regs)
|
||||
{
|
||||
_alert("Undefined instruction at 0x%x\n", regs[REG_PC]);
|
||||
CURRENT_REGS = regs;
|
||||
PANIC_WITH_REGS("panic", regs);
|
||||
return regs; /* To keep the compiler happy */
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_vectoraddrexceptn.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
.file "arm_vectoraddrexcptn.S"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
.globl arm_vectoraddrexcptn
|
||||
|
||||
/****************************************************************************
|
||||
* Assembly Macros
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
.arm
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_vectoraddrexcptn
|
||||
*
|
||||
* Description:
|
||||
* Shouldn't happen. This exception handler is in a separate file from
|
||||
* other vector handlers because some processors do not support the
|
||||
* Address Exception vector.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
.globl arm_vectoraddrexcptn
|
||||
.type arm_vectoraddrexcptn, %function
|
||||
arm_vectoraddrexcptn:
|
||||
b arm_vectoraddrexcptn
|
||||
.size arm_vectoraddrexcptn, . - arm_vectoraddrexcptn
|
||||
.end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,126 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/arm_vectortab.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
.file "arm_vectortab.S"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARM_TOOLCHAIN_ARMCLANG
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
#endif
|
||||
|
||||
.syntax unified
|
||||
.arm
|
||||
|
||||
.globl _sys_vector_start
|
||||
.globl _sys_vector_end
|
||||
|
||||
/****************************************************************************
|
||||
* Assembly Macros
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: _vector_start
|
||||
*
|
||||
* Description:
|
||||
* Vector initialization block
|
||||
****************************************************************************/
|
||||
|
||||
.section .sys_vectors, "ax"
|
||||
|
||||
_sys_vector_start:
|
||||
ldr pc, .Lresethandler /* 0x00: Reset */
|
||||
ldr pc, .Lundefinedhandler /* 0x04: Undefined instruction */
|
||||
ldr pc, .Lsvchandler /* 0x08: Software interrupt */
|
||||
ldr pc, .Lprefetchaborthandler /* 0x0c: Prefetch abort */
|
||||
ldr pc, .Ldataaborthandler /* 0x10: Data abort */
|
||||
ldr pc, .Laddrexcptnhandler /* 0x14: Address exception (reserved) */
|
||||
ldr pc, .Lirqhandler /* 0x18: IRQ */
|
||||
ldr pc, .Lfiqhandler /* 0x1c: FIQ */
|
||||
|
||||
.globl __start
|
||||
.globl arm_vectorundefinsn
|
||||
.globl arm_vectorsvc
|
||||
.globl arm_vectorprefetch
|
||||
.globl arm_vectordata
|
||||
.globl arm_vectoraddrexcptn
|
||||
.globl arm_vectorirq
|
||||
.globl arm_vectorfiq
|
||||
|
||||
.Lresethandler:
|
||||
.long __start
|
||||
.Lundefinedhandler:
|
||||
.long arm_vectorundefinsn
|
||||
.Lsvchandler:
|
||||
.long arm_vectorsvc
|
||||
.Lprefetchaborthandler:
|
||||
.long arm_vectorprefetch
|
||||
.Ldataaborthandler:
|
||||
.long arm_vectordata
|
||||
.Laddrexcptnhandler:
|
||||
.long arm_vectoraddrexcptn
|
||||
.Lirqhandler:
|
||||
.long arm_vectorirq
|
||||
.Lfiqhandler:
|
||||
.long arm_vectorfiq
|
||||
|
||||
_sys_vector_end:
|
||||
.size _sys_vector_start, . - _sys_vector_start
|
||||
|
||||
/****************************************************************************
|
||||
* Name: _hyp_vector_start
|
||||
*
|
||||
* Description:
|
||||
* Vector initialization block
|
||||
****************************************************************************/
|
||||
|
||||
.section .hyp_vectors, "ax"
|
||||
.globl _hyp_vector_start
|
||||
|
||||
_hyp_vector_start:
|
||||
ldr pc, .Lhypresethandler /* 0x00: Reset */
|
||||
b $+0x0 /* 0x04: Undefined instruction */
|
||||
b $+0x0 /* 0x08: Software interrupt */
|
||||
b $+0x0 /* 0x0c: Prefetch abort */
|
||||
b $+0x0 /* 0x10: Data abort */
|
||||
b $+0x0 /* 0x14: Address exception (reserved) */
|
||||
b $+0x0 /* 0x18: IRQ */
|
||||
b $+0x0 /* 0x1c: FIQ */
|
||||
|
||||
.globl __start
|
||||
|
||||
.Lhypresethandler:
|
||||
.long __start
|
||||
|
||||
_hyp_vector_end:
|
||||
.size _hyp_vector_start, . - _hyp_vector_start
|
||||
.end
|
||||
@@ -0,0 +1,46 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/barriers.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_ARMV8_R_BARRIERS_H
|
||||
#define __ARCH_ARM_SRC_ARMV8_R_BARRIERS_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* ARMv8-R memory barriers */
|
||||
|
||||
#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory")
|
||||
#define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory")
|
||||
#define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory")
|
||||
#define arm_nop() __asm__ __volatile__ ("nop\n")
|
||||
#define arm_sev() __asm__ __volatile__ ("sev\n")
|
||||
|
||||
#define ARM_DSB() arm_dsb(15)
|
||||
#define ARM_ISB() arm_isb(15)
|
||||
#define ARM_DMB() arm_dmb(15)
|
||||
#define ARM_NOP() arm_nop()
|
||||
#define ARM_SEV() arm_sev()
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_ARMV8_R_BARRIERS_H */
|
||||
@@ -0,0 +1,224 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/cp15.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* References:
|
||||
* "ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition",
|
||||
* Copyright 1996-1998, 2000, 2004-2012 ARM.
|
||||
* All rights reserved. ARM DDI 0406C.c (ID051414)
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_ARMV8_R_CP15_H
|
||||
#define __ARCH_ARM_SRC_ARMV8_R_CP15_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* System control register descriptions.
|
||||
*
|
||||
* CP15 registers are accessed with MRC and MCR instructions as follows:
|
||||
*
|
||||
* MRC p15, <Op1>, <Rd>, <CRn>, <CRm>, <Op2> ; Read CP15 Register
|
||||
* MCR p15, <Op1>, <Rd>, <CRn>, <CRm>, <Op2> ; Write CP15 Register
|
||||
*
|
||||
* Where
|
||||
*
|
||||
* <Op1> is the Opcode_1 value for the register
|
||||
* <Rd> is a general purpose register
|
||||
* <CRn> is the register number within CP15
|
||||
* <CRm> is the operational register
|
||||
* <Op2> is the Opcode_2 value for the register.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
# define _CP15(op1,rd,crn,crm,op2) p15, op1, rd, crn, crm, op2
|
||||
# define _CP15_64(op1,lo,hi,op2) p15, op1, lo, hi, op2
|
||||
#else
|
||||
# define _CP15(op1,rd,crn,crm,op2) "p15, " #op1 ", %0, " #crn ", " #crm ", " #op2
|
||||
# define _CP15_64(op1,lo,hi,op2) "p15, " #op1 ", %Q0, %R0, " #op2
|
||||
#endif
|
||||
|
||||
#define CP15_MIDR(r) _CP15(0, r, c0, c0, 0) /* Main ID Register */
|
||||
#define CP15_CTR(r) _CP15(0, r, c0, c0, 1) /* Cache Type Register */
|
||||
#define CP15_TCMTR(r) _CP15(0, r, c0, c0, 2) /* TCM Type Register */
|
||||
#define CP15_MPUIR(r) _CP15(0, r, c0, c0, 4) /* MPU Type Register */
|
||||
#define CP15_MPIDR(r) _CP15(0, r, c0, c0, 5) /* Multiprocessor Affinity Register */
|
||||
#define CP15_REVIDR(r) _CP15(0, r, c0, c0, 6) /* Revision ID register (Cortex-A9) */
|
||||
#define CP15_MID_PFR0(r) _CP15(0, r, c0, c1, 0) /* Processor Feature Register 0 */
|
||||
#define CP15_MID_PFR1(r) _CP15(0, r, c0, c1, 1) /* Processor Feature Register 1 */
|
||||
#define CP15_MID_DFR0(r) _CP15(0, r, c0, c1, 2) /* Debug Feature Register 0 */
|
||||
#define CP15_MID_AFR0(r) _CP15(0, r, c0, c1, 3) /* Auxiliary Feature Register 0 (Cortex-A9) */
|
||||
#define CP15_MID_MMFR0(r) _CP15(0, r, c0, c1, 4) /* Memory Model Features Register 0 */
|
||||
#define CP15_MID_MMFR1(r) _CP15(0, r, c0, c1, 5) /* Memory Model Features Register 1 */
|
||||
#define CP15_MID_MMFR2(r) _CP15(0, r, c0, c1, 6) /* Memory Model Features Register 2 */
|
||||
#define CP15_MID_MMFR3(r) _CP15(0, r, c0, c1, 7) /* Memory Model Features Register 3 */
|
||||
#define CP15_ID_ISAR0(r) _CP15(0, r, c0, c2, 0) /* Instruction Set Attributes Register 0 */
|
||||
#define CP15_ID_ISAR1(r) _CP15(0, r, c0, c2, 1) /* Instruction Set Attributes Register 1 */
|
||||
#define CP15_ID_ISAR2(r) _CP15(0, r, c0, c2, 2) /* Instruction Set Attributes Register 2 */
|
||||
#define CP15_ID_ISAR3(r) _CP15(0, r, c0, c2, 3) /* Instruction Set Attributes Register 3 */
|
||||
#define CP15_ID_ISAR4(r) _CP15(0, r, c0, c2, 4) /* Instruction Set Attributes Register 4 */
|
||||
#define CP15_ID_ISAR5(r) _CP15(0, r, c0, c2, 5) /* Instruction Set Attributes Register 5 (Cortex-A5) */
|
||||
#define CP15_CCSIDR(r) _CP15(1, r, c0, c0, 0) /* Cache Size Identification Register */
|
||||
#define CP15_CLIDR(r) _CP15(1, r, c0, c0, 1) /* Cache Level ID Register */
|
||||
#define CP15_AIDR(r) _CP15(1, r, c0, c0, 7) /* Auxiliary ID Register */
|
||||
#define CP15_CSSELR(r) _CP15(2, r, c0, c0, 0) /* Cache Size Selection Register */
|
||||
|
||||
#define CP15_SCTLR(r) _CP15(0, r, c1, c0, 0) /* System Control Register */
|
||||
#define CP15_ACTLR(r) _CP15(0, r, c1, c0, 1) /* Auxiliary Control Register */
|
||||
#define CP15_CPACR(r) _CP15(0, r, c1, c0, 2) /* Coprocessor Access Control Register */
|
||||
|
||||
#define CP15_DFSR(r) _CP15(0, r, c5, c0, 0) /* Data Fault Status Register */
|
||||
#define CP15_IFSR(r) _CP15(0, r, c5, c0, 1) /* Instruction Fault Status Register */
|
||||
#define CP15_ADFSR(r) _CP15(0, r, c5, c1, 0) /* Auxiliary Data Fault Status Register */
|
||||
#define CP15_AIFSR(r) _CP15(0, r, c5, c1, 1) /* Auxiliary Instruction Fault Status Register */
|
||||
|
||||
#define CP15_DFAR(r) _CP15(0, r, c6, c0, 0) /* Data Fault Address Register */
|
||||
#define CP15_IFAR(r) _CP15(0, r, c6, c0, 2) /* Instruction Fault Address Register */
|
||||
#define CP15_DRBAR(r) _CP15(0, r, c6, c1, 0) /* Data Region Base Address Register */
|
||||
#define CP15_DRSR(r) _CP15(0, r, c6, c1, 2) /* Data Region Size and Enable Register */
|
||||
#define CP15_DRACR(r) _CP15(0, r, c6, c1, 4) /* Data Region Access Control Register */
|
||||
#ifndef CONFIG_ARM_HAVE_MPU_UNIFIED
|
||||
# define CP15_IRBAR(r) _CP15(0, r, c6, c1, 1) /* Instruction Region Base Address Register */
|
||||
# define CP15_IRSR(r) _CP15(0, r, c6, c1, 3) /* Instruction Region Size and Enable Register */
|
||||
# define CP15_IRACR(r) _CP15(0, r, c6, c1, 5) /* Instruction Region Access Control Register */
|
||||
#endif
|
||||
#define CP15_RGNR(r) _CP15(0, r, c6, c2, 0) /* MPU Region Number Register */
|
||||
|
||||
#define CP15_ICIALLUIS(r) _CP15(0, r, c7, c1, 0) /* Cache Operations Registers */
|
||||
#define CP15_BPIALLIS(r) _CP15(0, r, c7, c1, 6)
|
||||
|
||||
#define CP15_ICIALLU(r) _CP15(0, r, c7, c5, 0) /* Cache Operations Registers */
|
||||
#define CP15_ICIMVAU(r) _CP15(0, r, c7, c5, 1)
|
||||
#define CP15_CP15ISB(r) _CP15(0, r, c7, c5, 4) /* CP15 Instruction Synchronization Barrier operation */
|
||||
#define CP15_BPIALL(r) _CP15(0, r, c7, c5, 6) /* Cache Operations Registers */
|
||||
#define CP15_BPIMVA(r) _CP15(0, r, c7, c5, 7) /* Cortex-A5 */
|
||||
#define CP15_DCIMVAC(r) _CP15(0, r, c7, c6, 1)
|
||||
#define CP15_DCISW(r) _CP15(0, r, c7, c6, 2)
|
||||
#define CP15_DCCMVAC(r) _CP15(0, r, c7, c10, 1) /* Data Cache Clean by MVA to PoC */
|
||||
#define CP15_DCCSW(r) _CP15(0, r, c7, c10, 2) /* Data Cache Clean by Set/Way */
|
||||
#define CP15_CP15DSB(r) _CP15(0, r, c7, c10, 4) /* CP15 Data Synchronization Barrier operation */
|
||||
#define CP15_CP15DMB(r) _CP15(0, r, c7, c10, 5) /* CP15 Instruction Synchronization Barrier operation */
|
||||
#define CP15_DCCMVAU(r) _CP15(0, r, c7, c11, 1) /* Cache Operations Registers */
|
||||
#define CP15_DCCIMVAC(r) _CP15(0, r, c7, c14, 1)
|
||||
#define CP15_DCCISW(r) _CP15(0, r, c7, c14, 2)
|
||||
|
||||
#define CP15_PMCR(r) _CP15(0, r, c9, c12, 0) /* Performance Monitor Control Register */
|
||||
#define CP15_PMCNTENSET(r) _CP15(0, r, c9, c12, 1) /* Count Enable Set Register */
|
||||
#define CP15_PMCNTENCLR(r) _CP15(0, r, c9, c12, 2) /* Count Enable Clear Register */
|
||||
#define CP15_PMOVSR(r) _CP15(0, r, c9, c12, 3) /* Overflow Flag Status Register */
|
||||
#define CP15_PMSWINC(r) _CP15(0, r, c9, c12, 4) /* Software Increment Register */
|
||||
#define CP15_PMSELR(r) _CP15(0, r, c9, c12, 5) /* Event Counter Selection Register */
|
||||
#define CP15_PMCEID0(r) _CP15(0, r, c9, c12, 6) /* Common Event Identification Registers (Cortex-A5) */
|
||||
#define CP15_PMCEID1(r) _CP15(0, r, c9, c12, 7)
|
||||
#define CP15_PMCCNTR(r) _CP15(0, r, c9, c13, 0) /* Cycle Count Register */
|
||||
#define CP15_PMXEVTYPER(r) _CP15(0, r, c9, c13, 1) /* Event Type Select Register */
|
||||
#define CP15_PMXEVCNTR(r) _CP15(0, r, c9, c13, 2) /* Event Count Registers (Cortex-A5) */
|
||||
#define CP15_PMUSERENR(r) _CP15(0, r, c9, c14, 0) /* User Enable Register */
|
||||
#define CP15_PMINTENSET(r) _CP15(0, r, c9, c14, 1) /* Interrupt Enable Set Register */
|
||||
#define CP15_PMINTENCLR(r) _CP15(0, r, c9, c14, 2) /* Interrupt Enable Clear Register */
|
||||
|
||||
#define CP15_VBAR(r) _CP15(0, r, c12, c0, 0) /* Vector Base Address Register */
|
||||
#define CP15_HVBAR(r) _CP15(4, r, c12, c0, 0) /* Hypervisor Vector Base Address Register */
|
||||
|
||||
#define CP15_CONTEXTIDR(r) _CP15(0, r, c13, c0, 1) /* Context ID Register */
|
||||
#define CP15_TPIDRURW(r) _CP15(0, r, c13, c0, 2) /* Software Thread ID Registers */
|
||||
#define CP15_TPIDRURO(r) _CP15(0, r, c13, c0, 3)
|
||||
#define CP15_TPIDRPRW(r) _CP15(0, r, c13, c0, 4)
|
||||
|
||||
#define CP15_CNTFRQ(r) _CP15(0, r, c14, c0, 0) /* CNTFRQ */
|
||||
#define CP15_CNTVCT(lo,hi) _CP15_64(1, lo, hi, c14) /* CNTVCT */
|
||||
#define CP15_CNTV_CTL(r) _CP15(0, r, c14, c3, 1) /* CNTV_CTL */
|
||||
#define CP15_CNTV_CVAL(lo,hi) _CP15_64(3, lo, hi, c14) /* CNTV_CVAL */
|
||||
|
||||
#define CP15_CNTPCT(lo,hi) _CP15_64(0, lo, hi, c14) /* Physical Count register */
|
||||
|
||||
#define CP15_DCIALLU(r) _CP15(0, r, c15, c5, 0) /* Invalidate data cache */
|
||||
|
||||
#define CP15_ICC_PMR(r) _CP15(0, r, c4, c6, 0) /* ICC_PMR */
|
||||
#define CP15_ICC_IAR1(r) _CP15(0, r, c12, c12, 0) /* ICC_IAR1 */
|
||||
#define CP15_ICC_EOIR1(r) _CP15(0, r, c12, c12, 1) /* ICC_EOIR1 */
|
||||
#define CP15_ICC_SRE(r) _CP15(0, r, c12, c12, 5) /* ICC_SRE */
|
||||
#define CP15_ICC_HSRE(r) _CP15(4, r, c12, c9, 5) /* ICC_HSRE */
|
||||
#define CP15_ICC_IGRPEN1(r) _CP15(0, r, c12, c12, 7) /* ICC_IGRPEN1 */
|
||||
#define CP15_ICC_SGI1R(lo,hi) _CP15_64(2, lo, hi, c12) /* ICC_SGI1R */
|
||||
|
||||
#define CP15_SET(reg, value) \
|
||||
do \
|
||||
{ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"mcr " CP15_ ## reg(0) "\n" \
|
||||
:: "r"(value): "memory" \
|
||||
); \
|
||||
} \
|
||||
while(0) \
|
||||
|
||||
#define CP15_SET2(reg, op, value) \
|
||||
do \
|
||||
{ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"mcr " CP15_ ## reg(0, op) "\n" \
|
||||
:: "r"(value): "memory" \
|
||||
); \
|
||||
} \
|
||||
while(0) \
|
||||
|
||||
#define CP15_GET(reg) \
|
||||
({ \
|
||||
uint32_t _value; \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"mrc " CP15_ ## reg(0) "\n" \
|
||||
: "=r"(_value) :: "memory" \
|
||||
); \
|
||||
_value; \
|
||||
}) \
|
||||
|
||||
#define CP15_SET64(reg, value) \
|
||||
do \
|
||||
{ \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"mcrr " CP15_ ## reg(0,0) "\n" \
|
||||
:: "r"(value): "memory" \
|
||||
); \
|
||||
} \
|
||||
while(0) \
|
||||
|
||||
#define CP15_GET64(reg) \
|
||||
({ \
|
||||
uint64_t _value; \
|
||||
__asm__ __volatile__ \
|
||||
( \
|
||||
"mrrc " CP15_ ## reg(0,0) "\n" \
|
||||
: "=r"(_value) :: "memory" \
|
||||
); \
|
||||
_value; \
|
||||
}) \
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_ARMV8_R_CP15_H */
|
||||
@@ -0,0 +1,276 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/armv8-r/cp15_cacheops.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/cache.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "cp15_cacheops.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint32_t ilog2(uint32_t u)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (u >>= 1)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline uint32_t cp15_cache_get_info(uint32_t *sets, uint32_t *ways)
|
||||
{
|
||||
uint32_t ccsidr = CP15_GET(CCSIDR);
|
||||
|
||||
if (sets)
|
||||
{
|
||||
*sets = ((ccsidr >> 13) & 0x7fff) + 1;
|
||||
}
|
||||
|
||||
if (ways)
|
||||
{
|
||||
*ways = ((ccsidr >> 3) & 0x3ff) + 1;
|
||||
}
|
||||
|
||||
return (1 << ((ccsidr & 0x7) + 2)) * 4;
|
||||
}
|
||||
|
||||
static void cp15_dcache_op(int op)
|
||||
{
|
||||
uint32_t clidr = CP15_GET(CLIDR);
|
||||
int level;
|
||||
|
||||
for (level = 0; level < 7; level++)
|
||||
{
|
||||
uint32_t ctype = clidr & 0x7;
|
||||
|
||||
switch (ctype)
|
||||
{
|
||||
case 0x2:
|
||||
case 0x3:
|
||||
case 0x4:
|
||||
cp15_dcache_op_level(level, op);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
clidr >>= 3;
|
||||
if (clidr == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cp15_dcache_op_mva(uintptr_t start, uintptr_t end, int op)
|
||||
{
|
||||
uint32_t line;
|
||||
|
||||
line = cp15_cache_get_info(NULL, NULL);
|
||||
|
||||
ARM_DSB();
|
||||
|
||||
if ((start & (line - 1)) != 0)
|
||||
{
|
||||
start &= ~(line - 1);
|
||||
if (op == CP15_CACHE_INVALIDATE)
|
||||
{
|
||||
cp15_cleaninvalidate_dcacheline_bymva(start);
|
||||
start += line;
|
||||
}
|
||||
}
|
||||
|
||||
while (start < end)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case CP15_CACHE_INVALIDATE:
|
||||
if (start + line <= end)
|
||||
{
|
||||
cp15_invalidate_dcacheline_bymva(start);
|
||||
}
|
||||
else
|
||||
{
|
||||
cp15_cleaninvalidate_dcacheline_bymva(start);
|
||||
}
|
||||
break;
|
||||
case CP15_CACHE_CLEAN:
|
||||
cp15_clean_dcache_bymva(start);
|
||||
break;
|
||||
case CP15_CACHE_CLEANINVALIDATE:
|
||||
cp15_cleaninvalidate_dcacheline_bymva(start);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
start += line;
|
||||
}
|
||||
|
||||
ARM_ISB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void cp15_dcache_op_level(uint32_t level, int op)
|
||||
{
|
||||
uint32_t sets;
|
||||
uint32_t ways;
|
||||
uint32_t set;
|
||||
uint32_t way;
|
||||
uint32_t line;
|
||||
uint32_t way_shift;
|
||||
uint32_t set_shift;
|
||||
uint32_t val = level << 1;
|
||||
|
||||
/* Select by CSSELR */
|
||||
|
||||
CP15_SET(CSSELR, val);
|
||||
|
||||
/* Get cache info */
|
||||
|
||||
line = cp15_cache_get_info(&sets, &ways);
|
||||
|
||||
way_shift = 32 - ilog2(ways);
|
||||
set_shift = ilog2(line);
|
||||
|
||||
ARM_DSB();
|
||||
|
||||
/* A: Log2(ways)
|
||||
* B: L+S
|
||||
* L: Log2(line)
|
||||
* S: Log2(sets)
|
||||
*
|
||||
* The bits are packed as follows:
|
||||
* 31 31-A B B-1 L L-1 4 3 1 0
|
||||
* |---|-------------|--------|-------|-----|-|
|
||||
* |Way| zeros | Set | zeros |level|0|
|
||||
* |---|-------------|--------|-------|-----|-|
|
||||
*/
|
||||
|
||||
for (way = 0; way < ways; way++)
|
||||
{
|
||||
for (set = 0; set < sets; set++)
|
||||
{
|
||||
val = level << 1;
|
||||
val |= way << way_shift;
|
||||
val |= set << set_shift;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case CP15_CACHE_INVALIDATE:
|
||||
cp15_invalidate_dcacheline_bysetway(val);
|
||||
break;
|
||||
case CP15_CACHE_CLEAN:
|
||||
cp15_clean_dcache_bysetway(val);
|
||||
break;
|
||||
case CP15_CACHE_CLEANINVALIDATE:
|
||||
cp15_cleaninvalidate_dcacheline(val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ARM_ISB();
|
||||
}
|
||||
|
||||
void cp15_invalidate_icache(uintptr_t start, uintptr_t end)
|
||||
{
|
||||
uint32_t line;
|
||||
|
||||
line = cp15_cache_get_info(NULL, NULL);
|
||||
start &= ~(line - 1);
|
||||
|
||||
ARM_DSB();
|
||||
|
||||
while (start < end)
|
||||
{
|
||||
cp15_invalidate_icache_bymva(start);
|
||||
start += line;
|
||||
}
|
||||
|
||||
ARM_ISB();
|
||||
}
|
||||
|
||||
void cp15_coherent_dcache(uintptr_t start, uintptr_t end)
|
||||
{
|
||||
cp15_dcache_op_mva(start, end, CP15_CACHE_CLEANINVALIDATE);
|
||||
cp15_invalidate_icache_all();
|
||||
}
|
||||
|
||||
void cp15_invalidate_dcache(uintptr_t start, uintptr_t end)
|
||||
{
|
||||
cp15_dcache_op_mva(start, end, CP15_CACHE_INVALIDATE);
|
||||
}
|
||||
|
||||
void cp15_invalidate_dcache_all(void)
|
||||
{
|
||||
cp15_dcache_op(CP15_CACHE_INVALIDATE);
|
||||
}
|
||||
|
||||
void cp15_clean_dcache(uintptr_t start, uintptr_t end)
|
||||
{
|
||||
cp15_dcache_op_mva(start, end, CP15_CACHE_CLEAN);
|
||||
}
|
||||
|
||||
void cp15_clean_dcache_all(void)
|
||||
{
|
||||
cp15_dcache_op(CP15_CACHE_CLEAN);
|
||||
}
|
||||
|
||||
void cp15_flush_dcache(uintptr_t start, uintptr_t end)
|
||||
{
|
||||
cp15_dcache_op_mva(start, end, CP15_CACHE_CLEANINVALIDATE);
|
||||
}
|
||||
|
||||
void cp15_flush_dcache_all(void)
|
||||
{
|
||||
cp15_dcache_op(CP15_CACHE_CLEANINVALIDATE);
|
||||
}
|
||||
|
||||
uint32_t cp15_cache_size(void)
|
||||
{
|
||||
uint32_t sets;
|
||||
uint32_t ways;
|
||||
uint32_t line;
|
||||
|
||||
line = cp15_cache_get_info(&sets, &ways);
|
||||
|
||||
return sets * ways * line;
|
||||
}
|
||||
|
||||
uint32_t cp15_cache_linesize(void)
|
||||
{
|
||||
return cp15_cache_get_info(NULL, NULL);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -133,12 +133,15 @@
|
||||
#define putreg16(v,a) (*(volatile uint16_t *)(a) = (v))
|
||||
#define getreg32(a) (*(volatile uint32_t *)(a))
|
||||
#define putreg32(v,a) (*(volatile uint32_t *)(a) = (v))
|
||||
#define getreg64(a) (*(volatile uint64_t *)(a))
|
||||
#define putreg64(v,a) (*(volatile uint64_t *)(a) = (v))
|
||||
|
||||
/* Non-atomic, but more effective modification of registers */
|
||||
|
||||
#define modreg8(v,m,a) putreg8((getreg8(a) & ~(m)) | ((v) & (m)), (a))
|
||||
#define modreg16(v,m,a) putreg16((getreg16(a) & ~(m)) | ((v) & (m)), (a))
|
||||
#define modreg32(v,m,a) putreg32((getreg32(a) & ~(m)) | ((v) & (m)), (a))
|
||||
#define modreg64(v,m,a) putreg64((getreg64(a) & ~(m)) | ((v) & (m)), (a))
|
||||
|
||||
/* Context switching */
|
||||
|
||||
@@ -175,6 +178,45 @@ extern void arm_switchcontext(uint32_t **saveregs,
|
||||
# define _enoinit Image$$noinit$$Limit
|
||||
#endif
|
||||
|
||||
/* MPIDR_EL1, Multiprocessor Affinity Register */
|
||||
|
||||
#define MPIDR_AFFLVL_MASK (0xff)
|
||||
#define MPIDR_ID_MASK (0x00ffffff)
|
||||
|
||||
#define MPIDR_AFF0_SHIFT (0)
|
||||
#define MPIDR_AFF1_SHIFT (8)
|
||||
#define MPIDR_AFF2_SHIFT (16)
|
||||
|
||||
/* mpidr register, the register is define:
|
||||
* - bit 0~7: Aff0
|
||||
* - bit 8~15: Aff1
|
||||
* - bit 16~23: Aff2
|
||||
* - bit 24: MT, multithreading
|
||||
* - bit 25~29: RES0
|
||||
* - bit 30: U, multiprocessor/Uniprocessor
|
||||
* - bit 31: RES1
|
||||
* Different ARM/ARM64 cores will use different Affn define, the mpidr
|
||||
* value is not CPU number, So we need to change CPU number to mpid
|
||||
* and vice versa
|
||||
*/
|
||||
|
||||
#define GET_MPIDR() CP15_GET(MPIDR)
|
||||
|
||||
#define MPIDR_AFFLVL(mpidr, aff_level) \
|
||||
(((mpidr) >> MPIDR_AFF ## aff_level ## _SHIFT) & MPIDR_AFFLVL_MASK)
|
||||
|
||||
#define MPID_TO_CORE(mpid, aff_level) \
|
||||
(((mpid) >> MPIDR_AFF ## aff_level ## _SHIFT) & MPIDR_AFFLVL_MASK)
|
||||
|
||||
#define CORE_TO_MPID(core, aff_level) \
|
||||
({ \
|
||||
uint64_t __mpidr = GET_MPIDR(); \
|
||||
__mpidr &= ~(MPIDR_AFFLVL_MASK << MPIDR_AFF ## aff_level ## _SHIFT); \
|
||||
__mpidr |= (cpu << MPIDR_AFF ## aff_level ## _SHIFT); \
|
||||
__mpidr &= MPIDR_ID_MASK; \
|
||||
__mpidr; \
|
||||
})
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
@@ -344,7 +386,7 @@ int arm_securefault(int irq, void *context, void *arg);
|
||||
* (but should be back-ported to the ARM7 and ARM9 families).
|
||||
*/
|
||||
|
||||
#elif defined(CONFIG_ARCH_ARMV7A) || defined(CONFIG_ARCH_ARMV7R)
|
||||
#elif defined(CONFIG_ARCH_ARMV7A) || defined(CONFIG_ARCH_ARMV7R) || defined(CONFIG_ARCH_ARMV8R)
|
||||
|
||||
/* Interrupt acknowledge and dispatch */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user