mirror of
https://github.com/apache/nuttx.git
synced 2026-08-26 20:00:42 +00:00
Make sure interrupt stack is colored before IRQ is enabled. Currently, after calling irq_initialize in nx_start to enable interrupts, there is still a period of execution path before the interrupt stack is colored. Signed-off-by: guoshengyuan1 <guoshengyuan1@xiaomi.com>
514 lines
16 KiB
C
514 lines
16 KiB
C
/****************************************************************************
|
|
* arch/arm/src/common/arm_internal.h
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* 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_COMMON_ARM_INTERNAL_H
|
|
#define __ARCH_ARM_SRC_COMMON_ARM_INTERNAL_H
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#ifndef __ASSEMBLY__
|
|
# include <nuttx/compiler.h>
|
|
# include <nuttx/arch.h>
|
|
# include <sys/types.h>
|
|
# include <stdint.h>
|
|
# include <syscall.h>
|
|
|
|
# include "chip.h"
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
/* Determine which (if any) console driver to use. If a console is enabled
|
|
* and no other console device is specified, then a serial console is
|
|
* assumed.
|
|
*/
|
|
|
|
#ifndef CONFIG_DEV_CONSOLE
|
|
# undef USE_SERIALDRIVER
|
|
# undef USE_EARLYSERIALINIT
|
|
#else
|
|
# if defined(CONFIG_LWL_CONSOLE)
|
|
# undef USE_SERIALDRIVER
|
|
# undef USE_EARLYSERIALINIT
|
|
# elif defined(CONFIG_CONSOLE_SYSLOG)
|
|
# undef USE_SERIALDRIVER
|
|
# undef USE_EARLYSERIALINIT
|
|
# elif defined(CONFIG_SERIAL_RTT_CONSOLE)
|
|
# undef USE_SERIALDRIVER
|
|
# undef USE_EARLYSERIALINIT
|
|
# elif defined(CONFIG_RPMSG_UART_CONSOLE)
|
|
# undef USE_SERIALDRIVER
|
|
# undef USE_EARLYSERIALINIT
|
|
# else
|
|
# define USE_SERIALDRIVER 1
|
|
# define USE_EARLYSERIALINIT 1
|
|
# endif
|
|
#endif
|
|
|
|
/* If some other device is used as the console, then the serial driver may
|
|
* still be needed. Let's assume that if the upper half serial driver is
|
|
* built, then the lower half will also be needed. There is no need for
|
|
* the early serial initialization in this case.
|
|
*/
|
|
|
|
#if !defined(USE_SERIALDRIVER) && defined(CONFIG_STANDARD_SERIAL)
|
|
# define USE_SERIALDRIVER 1
|
|
#endif
|
|
|
|
/* For use with EABI and floating point, the stack must be aligned to 8-byte
|
|
* addresses.
|
|
*/
|
|
|
|
#define STACK_ALIGNMENT 8
|
|
|
|
/* Stack alignment macros */
|
|
|
|
#define STACK_ALIGN_MASK (STACK_ALIGNMENT - 1)
|
|
#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK)
|
|
#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK)
|
|
|
|
/* Check if an interrupt stack size is configured */
|
|
|
|
#ifndef CONFIG_ARCH_INTERRUPTSTACK
|
|
# define CONFIG_ARCH_INTERRUPTSTACK 0
|
|
#endif
|
|
|
|
#define INTSTACK_SIZE (CONFIG_ARCH_INTERRUPTSTACK & ~STACK_ALIGN_MASK)
|
|
|
|
/* Toolchain dependent, linker defined section addresses */
|
|
|
|
#if defined(__ICCARM__)
|
|
# define _START_TEXT __sfb(".text")
|
|
# define _END_TEXT __sfe(".text")
|
|
# define _START_BSS __sfb(".bss")
|
|
# define _END_BSS __sfe(".bss")
|
|
# define _DATA_INIT __sfb(".data_init")
|
|
# define _START_DATA __sfb(".data")
|
|
# define _END_DATA __sfe(".data")
|
|
#else
|
|
# define _START_TEXT _stext
|
|
# define _END_TEXT _etext
|
|
# define _START_BSS _sbss
|
|
# define _END_BSS _ebss
|
|
# define _DATA_INIT _eronly
|
|
# define _START_DATA _sdata
|
|
# define _END_DATA _edata
|
|
# define _START_TDATA _stdata
|
|
# define _END_TDATA _etdata
|
|
# define _START_TBSS _stbss
|
|
# define _END_TBSS _etbss
|
|
#endif
|
|
|
|
/* This is the value used to mark the stack for subsequent stack monitoring
|
|
* logic.
|
|
*/
|
|
|
|
#define STACK_COLOR 0xdeadbeef
|
|
#define INTSTACK_COLOR 0xdeadbeef
|
|
#define HEAP_COLOR 'h'
|
|
|
|
#define getreg8(a) (*(volatile uint8_t *)(a))
|
|
#define putreg8(v,a) (*(volatile uint8_t *)(a) = (v))
|
|
#define getreg16(a) (*(volatile uint16_t *)(a))
|
|
#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 */
|
|
|
|
#ifndef arm_fullcontextrestore
|
|
# define arm_fullcontextrestore() sys_call0(SYS_restore_context)
|
|
#endif
|
|
|
|
/* Redefine the linker symbols as armlink style */
|
|
|
|
#ifdef CONFIG_ARM_TOOLCHAIN_ARMCLANG
|
|
# define _stext Image$$text$$Base
|
|
# define _etext Image$$text$$Limit
|
|
# define _eronly Image$$eronly$$Base
|
|
# define _sdata Image$$data$$Base
|
|
# define _edata Image$$data$$RW$$Limit
|
|
# define _sbss Image$$bss$$Base
|
|
# define _ebss Image$$bss$$ZI$$Limit
|
|
# define _stdata Image$$tdata$$Base
|
|
# define _etdata Image$$tdata$$Limit
|
|
# define _stbss Image$$tbss$$Base
|
|
# define _etbss Image$$tbss$$Limit
|
|
# define _snoinit Image$$noinit$$Base
|
|
# define _enoinit Image$$noinit$$Limit
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Public Types
|
|
****************************************************************************/
|
|
|
|
#ifndef __ASSEMBLY__
|
|
/* g_interrupt_context store irq status */
|
|
|
|
extern volatile bool g_interrupt_context[CONFIG_SMP_NCPUS];
|
|
|
|
typedef void (*up_vector_t)(void);
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Public Data
|
|
****************************************************************************/
|
|
|
|
#ifndef __ASSEMBLY__
|
|
#ifdef __cplusplus
|
|
#define EXTERN extern "C"
|
|
extern "C"
|
|
{
|
|
#else
|
|
#define EXTERN extern
|
|
#endif
|
|
|
|
/* This is the beginning of heap as provided from arm_head.S.
|
|
* This is the first address in DRAM after the loaded
|
|
* program+bss+idle stack. The end of the heap is
|
|
* CONFIG_RAM_END
|
|
*/
|
|
|
|
EXTERN const uintptr_t g_idle_topstack;
|
|
|
|
/* Address of the saved user stack pointer */
|
|
|
|
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
|
EXTERN uint8_t g_intstackalloc[]; /* Allocated stack base */
|
|
EXTERN uint8_t g_intstacktop[]; /* Initial top of interrupt stack */
|
|
#endif
|
|
|
|
/* These symbols are setup by the linker script. */
|
|
|
|
EXTERN uint8_t _stext[]; /* Start of .text */
|
|
EXTERN uint8_t _etext[]; /* End_1 of .text + .rodata */
|
|
EXTERN const uint8_t _eronly[]; /* End+1 of read only section (.text + .rodata) */
|
|
EXTERN uint8_t _sdata[]; /* Start of .data */
|
|
EXTERN uint8_t _edata[]; /* End+1 of .data */
|
|
EXTERN uint8_t _sbss[]; /* Start of .bss */
|
|
EXTERN uint8_t _ebss[]; /* End+1 of .bss */
|
|
EXTERN uint8_t _stdata[]; /* Start of .tdata */
|
|
EXTERN uint8_t _etdata[]; /* End+1 of .tdata */
|
|
EXTERN uint8_t _stbss[]; /* Start of .tbss */
|
|
EXTERN uint8_t _etbss[]; /* End+1 of .tbss */
|
|
|
|
/* Sometimes, functions must be executed from RAM. In this case, the
|
|
* following macro may be used (with GCC!) to specify a function that will
|
|
* execute from RAM. For example,
|
|
*
|
|
* int __ramfunc__ foo (void);
|
|
* int __ramfunc__ foo (void) { return bar; }
|
|
*
|
|
* will create a function named foo that will execute from RAM.
|
|
*/
|
|
|
|
#ifdef CONFIG_ARCH_RAMFUNCS
|
|
|
|
# define __ramfunc__ locate_code(".ramfunc") farcall_function noinline_function
|
|
|
|
/* Functions declared in the .ramfunc section will be packaged together
|
|
* by the linker script and stored in FLASH. During boot-up, the start
|
|
* logic must include logic to copy the RAM functions from their storage
|
|
* location in FLASH to their correct destination in SRAM. The following
|
|
* following linker-defined values provide the information to copy the
|
|
* functions from flash to RAM.
|
|
*/
|
|
|
|
EXTERN const uint8_t _framfuncs[]; /* Copy source address in FLASH */
|
|
EXTERN uint8_t _sramfuncs[]; /* Copy destination start address in RAM */
|
|
EXTERN uint8_t _eramfuncs[]; /* Copy destination end address in RAM */
|
|
|
|
#else /* CONFIG_ARCH_RAMFUNCS */
|
|
|
|
/* Otherwise, a null definition is provided so that condition compilation is
|
|
* not necessary in code that may operate with or without RAM functions.
|
|
*/
|
|
|
|
# define __ramfunc__
|
|
|
|
#endif /* CONFIG_ARCH_RAMFUNCS */
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
/****************************************************************************
|
|
* Inline Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Public Function Prototypes
|
|
****************************************************************************/
|
|
|
|
#ifndef __ASSEMBLY__
|
|
/* Atomic modification of registers */
|
|
|
|
void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits);
|
|
void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits);
|
|
void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits);
|
|
|
|
/* Low level initialization provided by board-level logic *******************/
|
|
|
|
void arm_boot(void);
|
|
|
|
int arm_psci_init(const char *method);
|
|
|
|
/* Context switching */
|
|
|
|
uint32_t *arm_decodeirq(uint32_t *regs);
|
|
|
|
/* Signal handling **********************************************************/
|
|
|
|
void arm_sigdeliver(void);
|
|
|
|
/* Power management *********************************************************/
|
|
|
|
#ifdef CONFIG_PM
|
|
void arm_pminitialize(void);
|
|
#else
|
|
# define arm_pminitialize()
|
|
#endif
|
|
|
|
/* Interrupt handling *******************************************************/
|
|
|
|
#if CONFIG_ARCH_INTERRUPTSTACK > 7
|
|
void weak_function arm_initialize_stack(void);
|
|
#endif
|
|
|
|
/* Interrupt acknowledge and dispatch */
|
|
|
|
void arm_ack_irq(int irq);
|
|
uint32_t *arm_doirq(int irq, uint32_t *regs);
|
|
|
|
/* Exception handling logic unique to the Cortex-M family */
|
|
|
|
#if defined(CONFIG_ARCH_ARMV6M) || defined(CONFIG_ARCH_ARMV7M) || \
|
|
defined(CONFIG_ARCH_ARMV8M)
|
|
|
|
/* This is the address of the exception vector table (determined by the
|
|
* linker script).
|
|
*/
|
|
|
|
#if defined(__ICCARM__)
|
|
/* _vectors replaced on __vector_table for IAR C-SPY Simulator */
|
|
|
|
EXTERN const void *__vector_table[];
|
|
#else
|
|
EXTERN const void * const _vectors[];
|
|
#endif
|
|
|
|
/* Exception Handlers */
|
|
|
|
int arm_svcall(int irq, void *context, void *arg);
|
|
int arm_hardfault(int irq, void *context, void *arg);
|
|
|
|
# if defined(CONFIG_ARCH_ARMV7M) || defined(CONFIG_ARCH_ARMV8M)
|
|
|
|
int arm_memfault(int irq, void *context, void *arg);
|
|
int arm_busfault(int irq, void *context, void *arg);
|
|
int arm_usagefault(int irq, void *context, void *arg);
|
|
int arm_securefault(int irq, void *context, void *arg);
|
|
|
|
# endif /* CONFIG_ARCH_CORTEXM3,4,7 */
|
|
|
|
/* Exception handling logic unique to the Cortex-A and Cortex-R families
|
|
* (but should be back-ported to the ARM7 and ARM9 families).
|
|
*/
|
|
|
|
#elif defined(CONFIG_ARCH_ARMV7A) || defined(CONFIG_ARCH_ARMV7R) || defined(CONFIG_ARCH_ARMV8R)
|
|
|
|
/* Interrupt acknowledge and dispatch */
|
|
|
|
#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
|
|
uint32_t *arm_dofiq(int fiq, uint32_t *regs);
|
|
#endif
|
|
|
|
/* Paging support */
|
|
|
|
#ifdef CONFIG_LEGACY_PAGING
|
|
void arm_pginitialize(void);
|
|
uint32_t *arm_va2pte(uintptr_t vaddr);
|
|
#else /* CONFIG_LEGACY_PAGING */
|
|
# define arm_pginitialize()
|
|
#endif /* CONFIG_LEGACY_PAGING */
|
|
|
|
/* Exception Handlers */
|
|
|
|
uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr);
|
|
uint32_t *arm_prefetchabort(uint32_t *regs, uint32_t ifar, uint32_t ifsr);
|
|
uint32_t *arm_syscall(uint32_t *regs);
|
|
uint32_t *arm_undefinedinsn(uint32_t *regs);
|
|
|
|
/* Exception handling logic common to other ARM7 and ARM9 family. */
|
|
|
|
#else /* ARM7 | ARM9 */
|
|
|
|
/* Paging support (and exception handlers) */
|
|
|
|
#ifdef CONFIG_LEGACY_PAGING
|
|
void arm_pginitialize(void);
|
|
uint32_t *arm_va2pte(uintptr_t vaddr);
|
|
void arm_dataabort(uint32_t *regs, uint32_t far, uint32_t fsr);
|
|
#else /* CONFIG_LEGACY_PAGING */
|
|
# define arm_pginitialize()
|
|
void arm_dataabort(uint32_t *regs);
|
|
#endif /* CONFIG_LEGACY_PAGING */
|
|
|
|
/* Exception handlers */
|
|
|
|
void arm_prefetchabort(uint32_t *regs);
|
|
uint32_t *arm_syscall(uint32_t *regs);
|
|
void arm_undefinedinsn(uint32_t *regs);
|
|
|
|
#endif /* CONFIG_ARCH_ARMV[6-8]M */
|
|
|
|
void arm_vectorundefinsn(void);
|
|
void arm_vectorsvc(void);
|
|
void arm_vectorprefetch(void);
|
|
void arm_vectordata(void);
|
|
void arm_vectoraddrexcptn(void);
|
|
void arm_vectorirq(void);
|
|
void arm_vectorfiq(void);
|
|
|
|
/* Floating point unit ******************************************************/
|
|
|
|
#ifdef CONFIG_ARCH_FPU
|
|
void arm_fpuconfig(void);
|
|
#else
|
|
# define arm_fpuconfig()
|
|
#endif
|
|
|
|
/* Low level serial output **************************************************/
|
|
|
|
void arm_lowputc(char ch);
|
|
void arm_lowputs(const char *str);
|
|
|
|
#ifdef USE_SERIALDRIVER
|
|
void arm_serialinit(void);
|
|
#endif
|
|
|
|
#ifdef USE_EARLYSERIALINIT
|
|
void arm_earlyserialinit(void);
|
|
#endif
|
|
|
|
/* DMA **********************************************************************/
|
|
|
|
#ifdef CONFIG_ARCH_DMA
|
|
void weak_function arm_dma_initialize(void);
|
|
#endif
|
|
|
|
/* Cache control ************************************************************/
|
|
|
|
#ifdef CONFIG_ARCH_L2CACHE
|
|
void arm_l2ccinitialize(void);
|
|
#else
|
|
# define arm_l2ccinitialize()
|
|
#endif
|
|
|
|
/* Memory management ********************************************************/
|
|
|
|
#if CONFIG_MM_REGIONS > 1
|
|
void arm_addregion(void);
|
|
#else
|
|
# define arm_addregion()
|
|
#endif
|
|
|
|
/* Networking ***************************************************************/
|
|
|
|
/* Defined in board/xyz_network.c for board-specific Ethernet
|
|
* implementations, or chip/xyx_ethernet.c for chip-specific Ethernet
|
|
* implementations, or common/arm_etherstub.c for a corner case where the
|
|
* network is enabled yet there is no Ethernet driver to be initialized.
|
|
*
|
|
* Use of common/arm_etherstub.c is deprecated. The preferred mechanism is
|
|
* to use CONFIG_NETDEV_LATEINIT=y to suppress the call to
|
|
* arm_netinitialize() in up_initialize(). Then this stub would not be
|
|
* needed.
|
|
*/
|
|
|
|
#if defined(CONFIG_NET) && !defined(CONFIG_NETDEV_LATEINIT)
|
|
void arm_netinitialize(void);
|
|
#else
|
|
# define arm_netinitialize()
|
|
#endif
|
|
|
|
/* USB **********************************************************************/
|
|
|
|
#ifdef CONFIG_USBDEV
|
|
void arm_usbinitialize(void);
|
|
void arm_usbuninitialize(void);
|
|
#else
|
|
# define arm_usbinitialize()
|
|
# define arm_usbuninitialize()
|
|
#endif
|
|
|
|
/* Debug ********************************************************************/
|
|
#ifdef CONFIG_STACK_COLORATION
|
|
size_t arm_stack_check(void *stackbase, size_t nbytes);
|
|
void arm_stack_color(void *stackbase, size_t nbytes);
|
|
#endif
|
|
|
|
#if defined(CONFIG_STACK_COLORATION) &&\
|
|
defined(CONFIG_ARCH_INTERRUPTSTACK) && CONFIG_ARCH_INTERRUPTSTACK > 3
|
|
void arm_color_intstack(void);
|
|
#else
|
|
# define arm_color_intstack()
|
|
#endif
|
|
|
|
#ifdef CONFIG_ARCH_TRUSTZONE_SECURE
|
|
int arm_gen_nonsecurefault(int irq, uint32_t *regs);
|
|
#else
|
|
# define arm_gen_nonsecurefault(i, r) (0)
|
|
#endif
|
|
|
|
#if defined(CONFIG_ARMV7M_STACKCHECK) || defined(CONFIG_ARMV8M_STACKCHECK)
|
|
void arm_stack_check_init(void) noinstrument_function;
|
|
#endif
|
|
|
|
#ifdef CONFIG_ARM_COREDUMP_REGION
|
|
void arm_coredump_add_region(void);
|
|
#endif
|
|
|
|
#ifdef CONFIG_ARCH_HAVE_DEBUG
|
|
int arm_enable_dbgmonitor(void);
|
|
int arm_dbgmonitor(int irq, void *context, void *arg);
|
|
#endif
|
|
|
|
#undef EXTERN
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
#endif /* __ARCH_ARM_SRC_COMMON_ARM_INTERNAL_H */
|