diff --git a/arch/Kconfig b/arch/Kconfig index 828ba24d000b..610b29901367 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -422,6 +422,12 @@ config CPU_HAS_TEE Execution Environment (e.g. when it has a security attribution unit). +config CPU_HAS_DCLS + bool + help + This option is enabled when the processor hardware is configured in + Dual-redundant Core Lock-step (DCLS) topology. + config CPU_HAS_FPU bool help diff --git a/arch/arm/core/CMakeLists.txt b/arch/arm/core/CMakeLists.txt index cb090dace32b..3cc39d49bb08 100644 --- a/arch/arm/core/CMakeLists.txt +++ b/arch/arm/core/CMakeLists.txt @@ -10,7 +10,7 @@ zephyr_library_sources( exc_exit.S swap.c swap_helper.S - irq_manage.c + irq.c thread.c cpu_idle.S fault_s.S diff --git a/arch/arm/core/Kconfig b/arch/arm/core/Kconfig index cb9337a7d771..a8fffdced7f0 100644 --- a/arch/arm/core/Kconfig +++ b/arch/arm/core/Kconfig @@ -31,6 +31,7 @@ config CPU_CORTEX_M config CPU_CORTEX_R bool select CPU_CORTEX + select HAS_CMSIS_CORE select HAS_FLASH_LOAD_OFFSET help This option signifies the use of a CPU of the Cortex-R family. @@ -76,9 +77,24 @@ config ISA_ARM processor start-up. Much of its functionality was subsumed into T32 with the introduction of Thumb-2 technology. +config COMPILER_ISA_THUMB2 + bool "Compile C functions using Thumb-2 instruction set" + depends on ISA_THUMB2 + default y + help + This option configures the compiler to compile all C functions using the + Thumb-2 instruction set. + config NUM_IRQS int +config IRQ_COMMON_EOI + bool + help + This option signifies that the architectural interrupt controller + requires a common End of Interrupt (EOI) action after servicing every + interrupt. + config STACK_ALIGN_DOUBLE_WORD bool "Align stacks on double-words (8 octets)" default y @@ -98,6 +114,12 @@ config RUNTIME_NMI NMI handler installed when the CPU boots. If a custom handler is needed, enable this option and attach it via _NmiHandlerSet(). +config PLATFORM_SPECIFIC_INIT + bool "Enable platform (SOC) specific startup hook" + help + The platform specific initialization code (z_platform_init) is executed + at the beginning of the startup code (__start). + config FAULT_DUMP int "Fault dump level" default 2 diff --git a/arch/arm/core/cortex_m/CMakeLists.txt b/arch/arm/core/cortex_m/CMakeLists.txt index 556db5930b1b..44e920d13fda 100644 --- a/arch/arm/core/cortex_m/CMakeLists.txt +++ b/arch/arm/core/cortex_m/CMakeLists.txt @@ -8,6 +8,7 @@ zephyr_library_sources( fault.c scb.c irq_init.c + irq_manage.c thread_abort.c ) diff --git a/arch/arm/core/cortex_m/Kconfig b/arch/arm/core/cortex_m/Kconfig index b89213dd4d5f..b864febb4534 100644 --- a/arch/arm/core/cortex_m/Kconfig +++ b/arch/arm/core/cortex_m/Kconfig @@ -258,12 +258,6 @@ config SW_VECTOR_RELAY (or an Armv8-M baseline core) with no VTOR and no other hardware relocation table mechanisms. -config PLATFORM_SPECIFIC_INIT - bool "Enable platform (SOC) specific startup hook" - help - The platform specific initialization code (z_platform_init) is executed - at the beginning of the startup code (__start). - endmenu endif # CPU_CORTEX_M diff --git a/arch/arm/core/irq_manage.c b/arch/arm/core/cortex_m/irq_manage.c similarity index 55% rename from arch/arm/core/irq_manage.c rename to arch/arm/core/cortex_m/irq_manage.c index 0724be773e1d..629ef12ba177 100644 --- a/arch/arm/core/irq_manage.c +++ b/arch/arm/core/cortex_m/irq_manage.c @@ -6,7 +6,7 @@ /** * @file - * @brief ARM Cortex-M and Cortex-R interrupt management + * @brief ARM Cortex-M interrupt management * * * Interrupt management: enabling/disabling and dynamic ISR @@ -16,12 +16,7 @@ #include #include -#if defined(CONFIG_CPU_CORTEX_M) #include -#elif defined(CONFIG_CPU_CORTEX_R) -#include -#include -#endif #include #include #include @@ -32,7 +27,6 @@ extern void z_arm_reserved(void); -#if defined(CONFIG_CPU_CORTEX_M) #define NUM_IRQS_PER_REG 32 #define REG_FROM_IRQ(irq) (irq / NUM_IRQS_PER_REG) #define BIT_FROM_IRQ(irq) (irq % NUM_IRQS_PER_REG) @@ -97,121 +91,6 @@ void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags) NVIC_SetPriority((IRQn_Type)irq, prio); } -#elif defined(CONFIG_CPU_CORTEX_R) -void z_arch_irq_enable(unsigned int irq) -{ - struct device *dev = _sw_isr_table[0].arg; - - irq_enable_next_level(dev, (irq >> 8) - 1); -} - -void z_arch_irq_disable(unsigned int irq) -{ - struct device *dev = _sw_isr_table[0].arg; - - irq_disable_next_level(dev, (irq >> 8) - 1); -} - -int z_arch_irq_is_enabled(unsigned int irq) -{ - struct device *dev = _sw_isr_table[0].arg; - - return irq_is_enabled_next_level(dev); -} - -/** - * @internal - * - * @brief Set an interrupt's priority - * - * The priority is verified if ASSERT_ON is enabled. The maximum number - * of priority levels is a little complex, as there are some hardware - * priority levels which are reserved: three for various types of exceptions, - * and possibly one additional to support zero latency interrupts. - * - * @return N/A - */ -void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags) -{ - struct device *dev = _sw_isr_table[0].arg; - - if (irq == 0) - return; - - irq_set_priority_next_level(dev, (irq >> 8) - 1, prio, flags); -} - -#endif - -/** - * - * @brief Spurious interrupt handler - * - * Installed in all dynamic interrupt slots at boot time. Throws an error if - * called. - * - * See z_arm_reserved(). - * - * @return N/A - */ -void z_irq_spurious(void *unused) -{ - ARG_UNUSED(unused); - z_arm_reserved(); -} - -/* FIXME: IRQ direct inline functions have to be placed here and not in - * arch/cpu.h as inline functions due to nasty circular dependency between - * arch/cpu.h and kernel_structs.h; the inline functions typically need to - * perform operations on _kernel. For now, leave as regular functions, a - * future iteration will resolve this. - * - * See https://github.com/zephyrproject-rtos/zephyr/issues/3056 - */ - -#ifdef CONFIG_SYS_POWER_MANAGEMENT -void _arch_isr_direct_pm(void) -{ -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) \ - || defined(CONFIG_ARMV7_R) - unsigned int key; - - /* irq_lock() does what we wan for this CPU */ - key = irq_lock(); -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - /* Lock all interrupts. irq_lock() will on this CPU only disable those - * lower than BASEPRI, which is not what we want. See comments in - * arch/arm/core/isr_wrapper.S - */ - __asm__ volatile("cpsid i" : : : "memory"); -#else -#error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ - - if (_kernel.idle) { - s32_t idle_val = _kernel.idle; - - _kernel.idle = 0; - z_sys_power_save_idle_exit(idle_val); - } - -#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) \ - || defined(CONFIG_ARMV7_R) - irq_unlock(key); -#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) - __asm__ volatile("cpsie i" : : : "memory"); -#else -#error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ - -} -#endif - -void z_arch_isr_direct_header(void) -{ - sys_trace_isr_enter(); -} - #if defined(CONFIG_ARM_SECURE_FIRMWARE) /** * @@ -267,14 +146,3 @@ int irq_target_state_is_secure(unsigned int irq) } #endif /* CONFIG_ARM_SECURE_FIRMWARE */ - -#ifdef CONFIG_DYNAMIC_INTERRUPTS -int z_arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, - void (*routine)(void *parameter), void *parameter, - u32_t flags) -{ - z_isr_install(irq, routine, parameter); - z_arm_irq_priority_set(irq, priority, flags); - return irq; -} -#endif /* CONFIG_DYNAMIC_INTERRUPTS */ diff --git a/arch/arm/core/cortex_r/CMakeLists.txt b/arch/arm/core/cortex_r/CMakeLists.txt index a1154a3efb94..52b6d71804e9 100644 --- a/arch/arm/core/cortex_r/CMakeLists.txt +++ b/arch/arm/core/cortex_r/CMakeLists.txt @@ -6,6 +6,7 @@ zephyr_library_sources( vector_table.S reset.S fault.c + irq_init.c reboot.c stacks.c ) diff --git a/arch/arm/core/cortex_r/Kconfig b/arch/arm/core/cortex_r/Kconfig index 366db5eecc63..0cd4b760a491 100644 --- a/arch/arm/core/cortex_r/Kconfig +++ b/arch/arm/core/cortex_r/Kconfig @@ -36,6 +36,7 @@ config ARMV7_R bool select ATOMIC_OPERATIONS_BUILTIN select ISA_ARM + select ISA_THUMB2 help This option signifies the use of an ARMv7-R processor implementation. @@ -78,17 +79,19 @@ config ARMV7_SYS_STACK_SIZE help This option specifies the size of the stack used by the system mode. -if CPU_CORTEX_R - config RUNTIME_NMI default y config GEN_ISR_TABLES default y -config GEN_IRQ_VECTOR_TABLE - default n - -endif # CPU_CORTEX_R +config VIC_IRQ_VECTOR + bool "Enable VIC port hardware IRQ vector" + depends on (CPU_CORTEX_R4 || CPU_CORTEX_R5) + help + Enable hardware IRQ vector using the handler address provided by the + the system interrupt controller through VIC port. When this option is + selected, the IRQ vector (offset 0x18) in the CPU exception vector table + is not used. endif # CPU_CORTEX_R diff --git a/arch/arm/core/cortex_r/irq_init.c b/arch/arm/core/cortex_r/irq_init.c new file mode 100644 index 000000000000..70e34c0ebf43 --- /dev/null +++ b/arch/arm/core/cortex_r/irq_init.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019 Stephanos Ioannidis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM Cortex-R interrupt initialization + */ + +#include +#include + +/** + * @brief Initialize interrupts + * + * @return N/A + */ + +void z_arm_int_lib_init(void) +{ + /* Invoke SoC-specific interrupt initialisation */ + z_soc_irq_init(); + + /* Configure hardware vectored interrupt mode.*/ +#if defined(CONFIG_VIC_IRQ_VECTOR) + unsigned int sctlr = __get_SCTLR(); + sctlr |= SCTLR_VE_Msk; + __set_SCTLR(sctlr); +#endif +} diff --git a/arch/arm/core/cortex_r/reset.S b/arch/arm/core/cortex_r/reset.S index d88a9e2ecadf..0590bfbc592b 100644 --- a/arch/arm/core/cortex_r/reset.S +++ b/arch/arm/core/cortex_r/reset.S @@ -26,17 +26,17 @@ GDATA(z_arm_sys_stack) GDATA(z_arm_fiq_stack) GDATA(z_arm_abort_stack) GDATA(z_arm_undef_stack) - -#define STACK_MARGIN 4 - +#if defined(CONFIG_PLATFORM_SPECIFIC_INIT) +GTEXT(z_platform_init) +#endif /** * * @brief Reset vector * - * Ran when the system comes out of reset. The processor is in thread mode with - * privileged level. At this point, the main stack pointer (MSP) is already - * pointing to a valid area in SRAM. + * Ran when the system comes out of reset. The processor is in Supervisor mode + * and interrupts are disabled. The processor architectural registers are in + * an indeterminate state. * * When these steps are completed, jump to z_arm_prep_c(), which will finish * setting up the system for running C code. @@ -44,59 +44,143 @@ GDATA(z_arm_undef_stack) * @return N/A */ SECTION_SUBSEC_FUNC(TEXT, _reset_section, z_arm_reset) -SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start) - mov r0, #0 - mov r1, #0 - mov r2, #0 - mov r3, #0 - mov r4, #0 - mov r5, #0 - mov r6, #0 - mov r7, #0 - mov r8, #0 - mov r9, #0 - mov r10, #0 - mov r11, #0 - mov r12, #0 - mov r14, #0 - - /* lock interrupts: will get unlocked when switch to main task */ - cpsid if - - /* Setup FIQ stack */ - msr CPSR_c, #(MODE_FIQ | I_BIT | F_BIT) - ldr sp, =(z_arm_fiq_stack + CONFIG_ARMV7_FIQ_STACK_SIZE - STACK_MARGIN) - - /* Setup IRQ stack */ - msr CPSR_c, #(MODE_IRQ | I_BIT | F_BIT) - ldr sp, =(_interrupt_stack + CONFIG_ISR_STACK_SIZE - STACK_MARGIN) - - /* Setup data abort stack */ - msr CPSR_c, #(MODE_ABT | I_BIT | F_BIT) - ldr sp, =(z_arm_abort_stack + CONFIG_ARMV7_EXCEPTION_STACK_SIZE - \ - STACK_MARGIN) - - /* Setup undefined mode stack */ - msr CPSR_c, #(MODE_UDF | I_BIT | F_BIT) - ldr sp, =(z_arm_undef_stack + CONFIG_ARMV7_EXCEPTION_STACK_SIZE - \ - STACK_MARGIN) - - /* Setup SVC mode stack */ - msr CPSR_c, #(MODE_SVC | I_BIT | F_BIT) - ldr sp, =(z_arm_svc_stack + CONFIG_ARMV7_SVC_STACK_SIZE - STACK_MARGIN) - - /* Setup System mode stack */ - msr CPSR_c, #(MODE_SYS | I_BIT | F_BIT) - ldr sp, =(z_arm_sys_stack + CONFIG_ARMV7_SYS_STACK_SIZE - STACK_MARGIN) - - /* Setup system control register */ - mrc p15, 0, r0, c1, c0, 0 /* SCTLR */ - bic r0, r0, #HIVECS /* Exception vectors from 0-0x1c */ - mcr p15, 0, r0, c1, c0, 0 +SECTION_SUBSEC_FUNC(TEXT, _reset_section, __start) + +#if defined(CONFIG_CPU_HAS_DCLS) + /* + * Initialise CPU registers to a defined state if the processor is + * configured as Dual-redundant Core Lock-step (DCLS). This is required + * for state convergence of the two parallel executing cores. + */ + + /* Common and SVC mode registers */ + mov r0, #0 + mov r1, #0 + mov r2, #0 + mov r3, #0 + mov r4, #0 + mov r5, #0 + mov r6, #0 + mov r7, #0 + mov r8, #0 + mov r9, #0 + mov r10, #0 + mov r11, #0 + mov r12, #0 + mov r13, #0 /* r13_svc */ + mov r14, #0 /* r14_svc */ + mrs r0, cpsr + msr spsr_cxsf, r0 /* spsr_svc */ + + /* FIQ mode registers */ + cps #MODE_FIQ + mov r8, #0 /* r8_fiq */ + mov r9, #0 /* r9_fiq */ + mov r10, #0 /* r10_fiq */ + mov r11, #0 /* r11_fiq */ + mov r12, #0 /* r12_fiq */ + mov r13, #0 /* r13_fiq */ + mov r14, #0 /* r14_fiq */ + mrs r0, cpsr + msr spsr_cxsf, r0 /* spsr_fiq */ + + /* IRQ mode registers */ + cps #MODE_IRQ + mov r13, #0 /* r13_irq */ + mov r14, #0 /* r14_irq */ + mrs r0, cpsr + msr spsr_cxsf, r0 /* spsr_irq */ + + /* ABT mode registers */ + cps #MODE_ABT + mov r13, #0 /* r13_abt */ + mov r14, #0 /* r14_abt */ + mrs r0, cpsr + msr spsr_cxsf, r0 /* spsr_abt */ + + /* UND mode registers */ + cps #MODE_UND + mov r13, #0 /* r13_und */ + mov r14, #0 /* r14_und */ + mrs r0, cpsr + msr spsr_cxsf, r0 /* spsr_und */ + + /* SYS mode registers */ + cps #MODE_SYS + mov r13, #0 /* r13_sys */ + mov r14, #0 /* r14_sys */ + +#if defined(CONFIG_FLOAT) + /* + * Initialise FPU registers to a defined state. + */ + + /* Allow VFP coprocessor access */ + mrc p15, 0, r0, c1, c0, 2 + orr r0, r0, #(CPACR_CP10(CPACR_FA) | CPACR_CP11(CPACR_FA)) + mcr p15, 0, r0, c1, c0, 2 + + /* Enable VFP */ + mov r0, #FPEXC_EN + fmxr fpexc, r0 + + /* Initialise VFP registers */ + fmdrr d0, r1, r1 + fmdrr d1, r1, r1 + fmdrr d2, r1, r1 + fmdrr d3, r1, r1 + fmdrr d4, r1, r1 + fmdrr d5, r1, r1 + fmdrr d6, r1, r1 + fmdrr d7, r1, r1 + fmdrr d8, r1, r1 + fmdrr d9, r1, r1 + fmdrr d10, r1, r1 + fmdrr d11, r1, r1 + fmdrr d12, r1, r1 + fmdrr d13, r1, r1 + fmdrr d14, r1, r1 + fmdrr d15, r1, r1 +#endif /* CONFIG_FLOAT */ + +#endif /* CONFIG_CPU_HAS_DCLS */ + + /* + * Configure stack. + */ + + /* FIQ mode stack */ + msr CPSR_c, #(MODE_FIQ | I_BIT | F_BIT) + ldr sp, =(z_arm_fiq_stack + CONFIG_ARMV7_FIQ_STACK_SIZE) + + /* IRQ mode stack */ + msr CPSR_c, #(MODE_IRQ | I_BIT | F_BIT) + ldr sp, =(_interrupt_stack + CONFIG_ISR_STACK_SIZE) + + /* ABT mode stack */ + msr CPSR_c, #(MODE_ABT | I_BIT | F_BIT) + ldr sp, =(z_arm_abort_stack + CONFIG_ARMV7_EXCEPTION_STACK_SIZE) + + /* UND mode stack */ + msr CPSR_c, #(MODE_UND | I_BIT | F_BIT) + ldr sp, =(z_arm_undef_stack + CONFIG_ARMV7_EXCEPTION_STACK_SIZE) + + /* SVC mode stack */ + msr CPSR_c, #(MODE_SVC | I_BIT | F_BIT) + ldr sp, =(z_arm_svc_stack + CONFIG_ARMV7_SVC_STACK_SIZE) + + /* SYS mode stack */ + msr CPSR_c, #(MODE_SYS | I_BIT | F_BIT) + ldr sp, =(z_arm_sys_stack + CONFIG_ARMV7_SYS_STACK_SIZE) + +#if defined(CONFIG_PLATFORM_SPECIFIC_INIT) + /* Execute platform-specific initialisation if applicable */ + bl z_platform_init +#endif #if defined(CONFIG_WDOG_INIT) - /* board-specific watchdog initialization is necessary */ - bl z_arm_watchdog_init + /* board-specific watchdog initialization is necessary */ + bl z_arm_watchdog_init #endif - b z_arm_prep_c + b z_arm_prep_c diff --git a/arch/arm/core/exc_exit.S b/arch/arm/core/exc_exit.S index cc5407a3e01c..4a560be2edc0 100644 --- a/arch/arm/core/exc_exit.S +++ b/arch/arm/core/exc_exit.S @@ -71,10 +71,6 @@ SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_int_exit) */ SECTION_SUBSEC_FUNC(TEXT, _HandlerModeExit, z_arm_exc_exit) -#if defined(CONFIG_CPU_CORTEX_R) - /* r0 contains the caller mode */ - push {r0, lr} -#endif #ifdef CONFIG_PREEMPT_ENABLED ldr r0, =_kernel @@ -117,9 +113,6 @@ _EXIT_EXC: #if defined(CONFIG_CPU_CORTEX_M) bx lr #elif defined(CONFIG_CPU_CORTEX_R) - /* Restore the caller mode to r0 */ - pop {r0, lr} - /* * Restore r0-r3, r12 and lr stored into the process stack by the mode * entry function. These registers are saved by _isr_wrapper for IRQ mode @@ -128,22 +121,15 @@ _EXIT_EXC: * r0-r3 are either the values from the thread before it was switched out * or they are the args to _new_thread for a new thread. */ - push {r4, r5} + push {r4-r6} + mrs r6, cpsr - cmp r0, #RET_FROM_SVC cps #MODE_SYS ldmia sp!, {r0-r5} - beq _svc_exit - - cps #MODE_IRQ - b _exc_exit - -_svc_exit: - cps #MODE_SVC + msr cpsr_c, r6 -_exc_exit: mov r12, r4 mov lr, r5 - pop {r4, r5} + pop {r4-r6} movs pc, lr #endif diff --git a/arch/arm/core/irq.c b/arch/arm/core/irq.c new file mode 100644 index 000000000000..1d27f59f34b0 --- /dev/null +++ b/arch/arm/core/irq.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM interrupt handler + * + * Interrupt management: dynamic ISR connecting/replacing; + * SW_ISR_TABLE_DYNAMIC has to be enabled for connecting ISRs at runtime. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void z_arm_reserved(void); + +/** + * + * @brief Spurious interrupt handler + * + * Installed in all dynamic interrupt slots at boot time. Throws an error if + * called. + * + * See z_arm_reserved(). + * + * @return N/A + */ +void z_irq_spurious(void *unused) +{ + ARG_UNUSED(unused); + z_arm_reserved(); +} + +/* FIXME: IRQ direct inline functions have to be placed here and not in + * arch/cpu.h as inline functions due to nasty circular dependency between + * arch/cpu.h and kernel_structs.h; the inline functions typically need to + * perform operations on _kernel. For now, leave as regular functions, a + * future iteration will resolve this. + * + * See https://github.com/zephyrproject-rtos/zephyr/issues/3056 + */ + +#ifdef CONFIG_SYS_POWER_MANAGEMENT +void _arch_isr_direct_pm(void) +{ +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) \ + || defined(CONFIG_ARMV7_R) + unsigned int key; + + /* irq_lock() does what we wan for this CPU */ + key = irq_lock(); +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + /* Lock all interrupts. irq_lock() will on this CPU only disable those + * lower than BASEPRI, which is not what we want. See comments in + * arch/arm/core/isr_wrapper.S + */ + __asm__ volatile("cpsid i" : : : "memory"); +#else +#error Unknown ARM architecture +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ + + if (_kernel.idle) { + s32_t idle_val = _kernel.idle; + + _kernel.idle = 0; + z_sys_power_save_idle_exit(idle_val); + } + +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) \ + || defined(CONFIG_ARMV7_R) + irq_unlock(key); +#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + __asm__ volatile("cpsie i" : : : "memory"); +#else +#error Unknown ARM architecture +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ + +} +#endif + +#ifdef CONFIG_DYNAMIC_INTERRUPTS +int z_arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, + void (*routine)(void *parameter), void *parameter, + u32_t flags) +{ + z_isr_install(irq, routine, parameter); + z_arm_irq_priority_set(irq, priority, flags); + return irq; +} +#endif /* CONFIG_DYNAMIC_INTERRUPTS */ diff --git a/arch/arm/core/isr_wrapper.S b/arch/arm/core/isr_wrapper.S index 466afa05123e..e4ad9db43e36 100644 --- a/arch/arm/core/isr_wrapper.S +++ b/arch/arm/core/isr_wrapper.S @@ -123,12 +123,11 @@ _idle_state_cleared: #elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) sub r0, r0, #16 /* get IRQ number */ lsl r0, r0, #3 /* table is 8-byte wide */ -#elif defined(CONFIG_ARMV7_R) - /* - * Cortex-R only has one IRQ line so the main handler will be at - * offset 0 of the table. - */ - mov r0, #0 +#elif defined(CONFIG_CPU_CORTEX_R4) || defined(CONFIG_CPU_CORTEX_R5) + /* Get active IRQ number from the SoC interrupt controller */ + bl z_soc_irq_get_active + push {r0, r1} + lsl r0, r0, #3 /* table is 8-byte wide */ #else #error Unknown ARM architecture #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ @@ -151,6 +150,11 @@ _idle_state_cleared: #endif /* CONFIG_EXECUTION_BENCHMARKING */ blx r3 /* call ISR */ +#ifdef CONFIG_IRQ_COMMON_EOI + pop {r0, r1} + bl z_soc_irq_eoi +#endif + #ifdef CONFIG_TRACING bl sys_trace_isr_exit #endif @@ -171,10 +175,6 @@ _idle_state_cleared: #error Unknown ARM architecture #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ -#if defined(CONFIG_CPU_CORTEX_R) - mov r0, #RET_FROM_IRQ -#endif - /* Use 'bx' instead of 'b' because 'bx' can jump further, and use * 'bx' instead of 'blx' because exception return is done in * z_arm_int_exit() */ diff --git a/arch/arm/core/swap_helper.S b/arch/arm/core/swap_helper.S index 44ee723cc492..3afc7ce4d40c 100644 --- a/arch/arm/core/swap_helper.S +++ b/arch/arm/core/swap_helper.S @@ -618,7 +618,6 @@ demux: blx z_irq_do_offload /* call C routine which executes the offload */ /* exception return is done in z_arm_int_exit() */ - mov r0, #RET_FROM_SVC b z_arm_int_exit #endif @@ -626,7 +625,6 @@ _context_switch: /* handler mode exit, to PendSV */ bl z_arm_pendsv - mov r0, #RET_FROM_SVC b z_arm_int_exit _oops: diff --git a/arch/arm/core/thread.c b/arch/arm/core/thread.c index d06c8f875d62..00f678f19924 100644 --- a/arch/arm/core/thread.c +++ b/arch/arm/core/thread.c @@ -136,9 +136,13 @@ void z_arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, thread->callee_saved.psp = (u32_t)pInitCtx; #if defined(CONFIG_CPU_CORTEX_R) pInitCtx->basic.lr = (u32_t)pInitCtx->basic.pc; +#if defined(CONFIG_COMPILER_ISA_THUMB2) thread->callee_saved.spsr = A_BIT | T_BIT | MODE_SYS; +#else + thread->callee_saved.spsr = A_BIT | MODE_SYS; +#endif /* CONFIG_ISA_THUMB2 */ thread->callee_saved.lr = (u32_t)pInitCtx->basic.pc; -#endif +#endif /* CONFIG_CPU_CORTEX_R */ thread->arch.basepri = 0; #if defined(CONFIG_USERSPACE) || defined(CONFIG_FP_SHARING) diff --git a/arch/arm/include/cortex_r/exc.h b/arch/arm/include/cortex_r/exc.h index 50b42c8d1839..c49abff09e4d 100644 --- a/arch/arm/include/cortex_r/exc.h +++ b/arch/arm/include/cortex_r/exc.h @@ -42,7 +42,9 @@ static ALWAYS_INLINE bool z_arch_is_in_isr(void) : "=r" (status) : : "memory", "cc"); status &= MODE_MASK; - return (status == MODE_FIQ) || (status == MODE_IRQ); + return (status == MODE_FIQ) || + (status == MODE_IRQ) || + (status == MODE_SVC); } /** diff --git a/arch/common/isr_tables.c b/arch/common/isr_tables.c index 43b4dc88e0eb..af24484779c7 100644 --- a/arch/common/isr_tables.c +++ b/arch/common/isr_tables.c @@ -29,10 +29,9 @@ Z_GENERIC_SECTION(.irq_info) struct int_list_header _iheader = { /* These are placeholder tables. They will be replaced by the real tables * generated by gen_isr_tables.py. * - * z_irq_spurious and _isr_wrapper are used as placeholder values to - * ensure that they are not optimized out in the first link. The first - * link must contain the same symbols as the second one for the code - * generation to work. + * z_irq_spurious is used as placeholder values to ensure that they are not + * optimized out in the first link. The first link must contain the same + * symbols as the second one for the code generation to work. */ /* Some arches don't use a vector table, they have a common exception entry @@ -40,7 +39,11 @@ Z_GENERIC_SECTION(.irq_info) struct int_list_header _iheader = { */ #ifdef CONFIG_GEN_IRQ_VECTOR_TABLE u32_t __irq_vector_table _irq_vector_table[IRQ_TABLE_SIZE] = { +#ifdef CONFIG_GEN_SW_ISR_TABLE [0 ...(IRQ_TABLE_SIZE - 1)] = (u32_t)&_isr_wrapper, +#else + [0 ...(IRQ_TABLE_SIZE - 1)] = (u32_t)&z_irq_spurious, +#endif }; #endif diff --git a/cmake/compiler/gcc/target_arm.cmake b/cmake/compiler/gcc/target_arm.cmake index 41d9c1c913c7..a48ea037906d 100644 --- a/cmake/compiler/gcc/target_arm.cmake +++ b/cmake/compiler/gcc/target_arm.cmake @@ -1,12 +1,11 @@ # SPDX-License-Identifier: Apache-2.0 -list(APPEND TOOLCHAIN_C_FLAGS - -mthumb - -mcpu=${GCC_M_CPU} - ) -list(APPEND TOOLCHAIN_LD_FLAGS - -mthumb - -mcpu=${GCC_M_CPU} - ) +list(APPEND TOOLCHAIN_C_FLAGS -mcpu=${GCC_M_CPU}) +list(APPEND TOOLCHAIN_LD_FLAGS -mcpu=${GCC_M_CPU}) + +if(CONFIG_COMPILER_ISA_THUMB2) + list(APPEND TOOLCHAIN_C_FLAGS -mthumb) + list(APPEND TOOLCHAIN_LD_FLAGS -mthumb) +endif() # Defines a mapping from GCC_M_CPU to FPU @@ -19,6 +18,8 @@ endif() set(FPU_FOR_cortex-m4 fpv4-${PRECISION_TOKEN}d16) set(FPU_FOR_cortex-m7 fpv5-${PRECISION_TOKEN}d16) set(FPU_FOR_cortex-m33 fpv5-${PRECISION_TOKEN}d16) +set(FPU_FOR_cortex-r4 vfpv3-d16) +set(FPU_FOR_cortex-r5 vfpv3-d16) if(CONFIG_FLOAT) list(APPEND TOOLCHAIN_C_FLAGS -mfpu=${FPU_FOR_${GCC_M_CPU}}) diff --git a/drivers/interrupt_controller/Kconfig b/drivers/interrupt_controller/Kconfig index 53d7d8c2a529..9c590f3a67e1 100644 --- a/drivers/interrupt_controller/Kconfig +++ b/drivers/interrupt_controller/Kconfig @@ -145,10 +145,10 @@ config DW_ICTL_INIT_PRIORITY config GIC bool "ARM Generic Interrupt Controller (GIC)" - depends on CPU_CORTEX_R + select IRQ_COMMON_EOI help - The ARM Generic Interrupt Controller works with Cortex-A and - Cortex-R processors. + The ARM Generic Interrupt Controller is an interrupt controller that is + used often by ARM Cortex-A and Cortex-R devices. source "drivers/interrupt_controller/Kconfig.stm32" diff --git a/drivers/interrupt_controller/gic-400.c b/drivers/interrupt_controller/gic-400.c index 774aedb5118a..e976e4a702d4 100644 --- a/drivers/interrupt_controller/gic-400.c +++ b/drivers/interrupt_controller/gic-400.c @@ -1,13 +1,14 @@ /* * Copyright (c) 2018 Marvell * Copyright (c) 2018 Lexmark International, Inc. + * Copyright (c) 2019 Stephanos Ioannidis * * SPDX-License-Identifier: Apache-2.0 */ #include #include -#include +#include #include #define DT_GIC_DIST_BASE DT_INST_0_ARM_GIC_BASE_ADDRESS_0 @@ -44,9 +45,81 @@ #define GIC_INT_TYPE_MASK 0x3 #define GIC_INT_TYPE_EDGE (1 << 1) -struct gic_ictl_config { - u32_t isr_table_offset; -}; +void arm_gic_irq_enable(unsigned int irq) +{ + int int_grp, int_off; + + irq += GIC_SPI_INT_BASE; + int_grp = irq / 32; + int_off = irq % 32; + + sys_write32((1 << int_off), (GICD_ISENABLERn + int_grp * 4)); +} + +void arm_gic_irq_disable(unsigned int irq) +{ + int int_grp, int_off; + + irq += GIC_SPI_INT_BASE; + int_grp = irq / 32; + int_off = irq % 32; + + sys_write32((1 << int_off), (GICD_ICENABLERn + int_grp * 4)); +} + +int arm_gic_irq_is_enabled(unsigned int irq) +{ + int int_grp, int_off; + unsigned int enabler; + + irq += GIC_SPI_INT_BASE; + int_grp = irq / 32; + int_off = irq % 32; + + enabler = sys_read32(GICD_ICENABLERn + int_grp * 4); + + return (enabler & (1 << int_off)) != 0; +} + +void arm_gic_irq_set_priority( + unsigned int irq, unsigned int prio, unsigned int flags) +{ + int int_grp, int_off; + u8_t val; + + irq += GIC_SPI_INT_BASE; + + /* Set priority */ + sys_write8(prio & 0xff, GICD_IPRIORITYRn + irq); + + /* Set interrupt type */ + int_grp = irq / 4; + int_off = (irq % 4) * 2; + + val = sys_read8(GICD_ICFGRn + int_grp); + val &= ~(GIC_INT_TYPE_MASK << int_off); + if (flags & IRQ_TYPE_EDGE) + val |= (GIC_INT_TYPE_EDGE << int_off); + sys_write8(val, GICD_ICFGRn + int_grp); +} + +unsigned int arm_gic_irq_get_active(void) +{ + int irq; + + irq = sys_read32(GICC_IAR) & 0x3ff; + irq -= GIC_SPI_INT_BASE; + + return irq; +} + +void arm_gic_irq_eoi(unsigned int irq) +{ + irq += GIC_SPI_INT_BASE; + + /* set to inactive */ + sys_write32(irq, GICC_EOIR); +} static void gic_dist_init(void) { @@ -129,98 +202,6 @@ static void gic_cpu_init(void) sys_write32(val, GICC_CTRL); } -static void gic_irq_enable(struct device *dev, unsigned int irq) -{ - int int_grp, int_off; - - irq += GIC_SPI_INT_BASE; - int_grp = irq / 32; - int_off = irq % 32; - - sys_write32((1 << int_off), (GICD_ISENABLERn + int_grp * 4)); -} - -static void gic_irq_disable(struct device *dev, unsigned int irq) -{ - int int_grp, int_off; - - irq += GIC_SPI_INT_BASE; - int_grp = irq / 32; - int_off = irq % 32; - - sys_write32((1 << int_off), (GICD_ICENABLERn + int_grp * 4)); -} - -static unsigned int gic_irq_get_state(struct device *dev) -{ - return 1; -} - -static void gic_irq_set_priority(struct device *dev, - unsigned int irq, unsigned int prio, u32_t flags) -{ - int int_grp, int_off; - u8_t val; - - irq += GIC_SPI_INT_BASE; - - /* Set priority */ - sys_write8(prio & 0xff, GICD_IPRIORITYRn + irq); - - /* Set interrupt type */ - int_grp = irq / 4; - int_off = (irq % 4) * 2; - - val = sys_read8(GICD_ICFGRn + int_grp); - val &= ~(GIC_INT_TYPE_MASK << int_off); - if (flags & IRQ_TYPE_EDGE) - val |= (GIC_INT_TYPE_EDGE << int_off); - sys_write8(val, GICD_ICFGRn + int_grp); -} - -static void gic_isr(void *arg) -{ - struct device *dev = arg; - const struct gic_ictl_config *cfg = dev->config->config_info; - void (*gic_isr_handle)(void *); - int irq, isr_offset; - - irq = sys_read32(GICC_IAR); - irq &= 0x3ff; - - if (irq == NO_GIC_INT_PENDING) { - printk("gic: Invalid interrupt\n"); - return; - } - - isr_offset = cfg->isr_table_offset + irq - GIC_SPI_INT_BASE; - - gic_isr_handle = _sw_isr_table[isr_offset].isr; - if (gic_isr_handle) - gic_isr_handle(_sw_isr_table[isr_offset].arg); - else - printk("gic: no handler found for int %d\n", irq); - - /* set to inactive */ - sys_write32(irq, GICC_EOIR); -} - -static int gic_init(struct device *unused); -static const struct irq_next_level_api gic_apis = { - .intr_enable = gic_irq_enable, - .intr_disable = gic_irq_disable, - .intr_get_state = gic_irq_get_state, - .intr_set_priority = gic_irq_set_priority, -}; - -static const struct gic_ictl_config gic_config = { - .isr_table_offset = CONFIG_2ND_LVL_ISR_TBL_OFFSET, -}; - -DEVICE_AND_API_INIT(arm_gic, DT_INST_0_ARM_GIC_LABEL, - gic_init, NULL, &gic_config, - PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &gic_apis); - /** * * @brief Initialize the GIC device driver @@ -228,14 +209,8 @@ DEVICE_AND_API_INIT(arm_gic, DT_INST_0_ARM_GIC_LABEL, * * @return N/A */ -#define GIC_PARENT_IRQ 0 -#define GIC_PARENT_IRQ_PRI 0 -#define GIC_PARENT_IRQ_FLAGS 0 -static int gic_init(struct device *unused) +int arm_gic_init(void) { - IRQ_CONNECT(GIC_PARENT_IRQ, GIC_PARENT_IRQ_PRI, gic_isr, - DEVICE_GET(arm_gic), GIC_PARENT_IRQ_FLAGS); - /* Init of Distributor interface registers */ gic_dist_init(); diff --git a/include/arch/arm/asm_inline_gcc.h b/include/arch/arm/asm_inline_gcc.h index 839777904d02..1ac2a0e328a9 100644 --- a/include/arch/arm/asm_inline_gcc.h +++ b/include/arch/arm/asm_inline_gcc.h @@ -22,6 +22,10 @@ #include #include +#if defined(CONFIG_CPU_CORTEX_R) +#include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -58,8 +62,10 @@ static ALWAYS_INLINE unsigned int z_arch_irq_lock(void) : "i"(_EXC_IRQ_DEFAULT_PRIO) : "memory"); #elif defined(CONFIG_ARMV7_R) - __asm__ volatile("mrs %0, cpsr;" - "cpsid i" + __asm__ volatile( + "mrs %0, cpsr;" + "and %0, #" TOSTR(I_BIT) ";" + "cpsid i;" : "=r" (key) : : "memory", "cc"); @@ -91,10 +97,12 @@ static ALWAYS_INLINE void z_arch_irq_unlock(unsigned int key) "isb;" : : "r"(key) : "memory"); #elif defined(CONFIG_ARMV7_R) - __asm__ volatile("msr cpsr_c, %0" - : - : "r" (key) - : "memory", "cc"); + if (key) { + return; + } + __asm__ volatile( + "cpsie i;" + : : : "memory", "cc"); #else #error Unknown ARM architecture #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ diff --git a/include/arch/arm/cortex_r/cmsis.h b/include/arch/arm/cortex_r/cmsis.h new file mode 100644 index 000000000000..14bbd015bcc3 --- /dev/null +++ b/include/arch/arm/cortex_r/cmsis.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 Stephanos Ioannidis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief CMSIS interface file + * + * This header contains the interface to the ARM CMSIS Core headers. + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_R_CMSIS_H_ +#define ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_R_CMSIS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __CR_REV +#define __CR_REV 0U +#endif + +#ifndef __FPU_PRESENT +#define __FPU_PRESENT CONFIG_CPU_HAS_FPU +#endif + +#ifdef __cplusplus +} +#endif + +#if defined(CONFIG_CPU_CORTEX_R4) +#include +#elif defined(CONFIG_CPU_CORTEX_R5) +#include +#else +#error "Unknown Cortex-R device" +#endif + +#endif /* ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_R_CMSIS_H_ */ diff --git a/include/arch/arm/cortex_r/cpu.h b/include/arch/arm/cortex_r/cpu.h index 9ce788a511bd..984ec9d907b0 100644 --- a/include/arch/arm/cortex_r/cpu.h +++ b/include/arch/arm/cortex_r/cpu.h @@ -12,7 +12,7 @@ #define MODE_IRQ 0x12 #define MODE_SVC 0x13 #define MODE_ABT 0x17 -#define MODE_UDF 0x1b +#define MODE_UND 0x1b #define MODE_SYS 0x1f #define MODE_MASK 0x1f @@ -23,10 +23,12 @@ #define HIVECS (1 << 13) -#define RET_FROM_SVC 0 -#define RET_FROM_IRQ 1 +#define CPACR_NA (0U) +#define CPACR_FA (3U) -#define __ISB() __asm__ volatile ("isb sy" : : : "memory") -#define __DMB() __asm__ volatile ("dmb sy" : : : "memory") +#define CPACR_CP10(r) (r << 20) +#define CPACR_CP11(r) (r << 22) + +#define FPEXC_EN (1 << 30) #endif diff --git a/include/arch/arm/cortex_r/sys_io.h b/include/arch/arm/cortex_r/sys_io.h index 197d289d3f9f..06f276e654dc 100644 --- a/include/arch/arm/cortex_r/sys_io.h +++ b/include/arch/arm/cortex_r/sys_io.h @@ -16,6 +16,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/arch/arm/irq.h b/include/arch/arm/irq.h index 3ef252ba6748..ff45c885f2f8 100644 --- a/include/arch/arm/irq.h +++ b/include/arch/arm/irq.h @@ -6,41 +6,76 @@ /** * @file - * @brief Cortex-M public interrupt handling + * @brief ARM public interrupt handling * * ARM-specific kernel interrupt handling interface. Included by arm/arch.h. */ -#ifndef ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_IRQ_H_ -#define ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_IRQ_H_ +#ifndef ZEPHYR_INCLUDE_ARCH_ARM_IRQ_H_ +#define ZEPHYR_INCLUDE_ARCH_ARM_IRQ_H_ #include #include #include +#if defined(CONFIG_CPU_CORTEX_R) +#include +#endif + #ifdef __cplusplus extern "C" { #endif #ifdef _ASMLANGUAGE GTEXT(z_arm_int_exit); -GTEXT(z_arch_irq_enable) -GTEXT(z_arch_irq_disable) -GTEXT(z_arch_irq_is_enabled) +GTEXT(z_soc_irq_get_active); +GTEXT(z_soc_irq_eoi); #else + +#if defined(CONFIG_CPU_CORTEX_M) extern void z_arch_irq_enable(unsigned int irq); extern void z_arch_irq_disable(unsigned int irq); extern int z_arch_irq_is_enabled(unsigned int irq); -extern void z_arm_int_exit(void); +/* internal routine documented in C file, needed by IRQ_CONNECT() macro */ +extern void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, + unsigned int flags); -#if defined(CONFIG_ARMV7_R) -static ALWAYS_INLINE void z_arm_int_lib_init(void) -{ -} #else +/* + * Many Cortex-A and Cortex-R series cores do not designate an architectural + * interrupt controller and an arbitrary SoC-specific interrupt controller may + * be used. + * + * For this reason, the arch interrupt management functions are mapped to the + * SoC layer. + */ + +void z_soc_irq_init(void); +void z_soc_irq_enable(unsigned int irq); +void z_soc_irq_disable(unsigned int irq); +int z_soc_irq_is_enabled(unsigned int irq); + +unsigned int z_soc_irq_get_active(void); +void z_soc_irq_eoi(unsigned int irq); + +void z_soc_irq_priority_set( + unsigned int irq, unsigned int prio, unsigned int flags); + +#define z_arch_irq_enable(irq) z_soc_irq_enable(irq) +#define z_arch_irq_disable(irq) z_soc_irq_disable(irq) +#define z_arch_irq_is_enabled(irq) z_soc_irq_is_enabled(irq) + +#define z_arm_irq_priority_set(irq, prio, flags) \ + z_soc_irq_priority_set(irq, prio, flags) + +#endif /* CONFIG_CPU_CORTEX_M */ + + +extern void z_arm_int_exit(void); + extern void z_arm_int_lib_init(void); -#endif + /* macros convert value of it's argument to a string */ #define DO_TOSTR(s) #s @@ -50,10 +85,6 @@ extern void z_arm_int_lib_init(void); #define DO_CONCAT(x, y) x ## y #define CONCAT(x, y) DO_CONCAT(x, y) -/* internal routine documented in C file, needed by IRQ_CONNECT() macro */ -extern void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, - u32_t flags); - /* Flags for use with IRQ_CONNECT() */ #ifdef CONFIG_ZERO_LATENCY_IRQS @@ -90,6 +121,36 @@ extern void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, irq_p; \ }) +#ifndef CONFIG_CPU_CORTEX_M +static ALWAYS_INLINE void z_arm_isr_enter(void) +{ + __asm volatile( + "push {r4, r5};" + "mov r4, r12;" + "sub r5, lr, #4;" + "cps #" TOSTR(MODE_SYS) ";" + "stmdb sp!, {r0-r5};" + "cps #" TOSTR(MODE_IRQ) ";" + "pop {r4, r5};" + ); +} + +static ALWAYS_INLINE void z_arm_isr_exit(void) +{ + __asm volatile( + "push {r4-r6};" + "mrs r6, cpsr;" + "cps #" TOSTR(MODE_SYS) ";" + "ldmia sp!, {r0-r5};" + "msr cpsr_c, r6;" + "mov r12, r4;" + "mov lr, r5;" + "pop {r4-r6};" + "movs pc, lr;" + ); +} +#endif /* !CONFIG_CPU_CORTEX_M */ + /* FIXME prefer these inline, but see GH-3056 */ #ifdef CONFIG_SYS_POWER_MANAGEMENT extern void _arch_isr_direct_pm(void); @@ -98,32 +159,36 @@ extern void _arch_isr_direct_pm(void); #define Z_ARCH_ISR_DIRECT_PM() do { } while (false) #endif -#define Z_ARCH_ISR_DIRECT_HEADER() z_arch_isr_direct_header() -extern void z_arch_isr_direct_header(void); - -#define Z_ARCH_ISR_DIRECT_FOOTER(swap) z_arch_isr_direct_footer(swap) - -/* arch/arm/core/exc_exit.S */ -extern void z_arm_int_exit(void); - #ifdef CONFIG_TRACING +extern void sys_trace_isr_enter(void); extern void sys_trace_isr_exit(void); #endif -static inline void z_arch_isr_direct_footer(int maybe_swap) +#define Z_ARCH_ISR_DIRECT_HEADER() z_arch_isr_direct_header() +static ALWAYS_INLINE void z_arch_isr_direct_header(void) { +#ifdef CONFIG_TRACING + sys_trace_isr_enter(); +#endif +} +#define Z_ARCH_ISR_DIRECT_FOOTER(swap) z_arch_isr_direct_footer(swap) +static ALWAYS_INLINE void z_arch_isr_direct_footer(int maybe_swap) +{ #ifdef CONFIG_TRACING sys_trace_isr_exit(); #endif + if (maybe_swap) { z_arm_int_exit(); } } +#ifdef CONFIG_CPU_CORTEX_M + #define Z_ARCH_ISR_DIRECT_DECLARE(name) \ static inline int name##_body(void); \ - __attribute__ ((interrupt ("IRQ"))) void name(void) \ + __attribute__((interrupt)) void name(void) \ { \ int check_reschedule; \ ISR_DIRECT_HEADER(); \ @@ -132,6 +197,25 @@ static inline void z_arch_isr_direct_footer(int maybe_swap) } \ static inline int name##_body(void) +#else + +#define Z_ARCH_ISR_DIRECT_DECLARE(name) \ + static int name##_body(void); \ + __attribute__((naked, target("arm"))) void name(void) \ + { \ + z_arm_isr_enter(); \ + { \ + int check_reschedule; \ + ISR_DIRECT_HEADER(); \ + check_reschedule = name##_body(); \ + ISR_DIRECT_FOOTER(check_reschedule); \ + } \ + z_arm_isr_exit(); \ + } \ + static __attribute__((noinline)) int name##_body(void) + +#endif /* CONFIG_CPU_CORTEX_M */ + /* Spurious interrupt handler. Throws an error if called */ extern void z_irq_spurious(void *unused); @@ -149,4 +233,4 @@ extern void _isr_wrapper(void); } #endif -#endif /* ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_IRQ_H_ */ +#endif /* ZEPHYR_INCLUDE_ARCH_ARM_IRQ_H_ */ diff --git a/include/drivers/interrupt_controller/gic.h b/include/drivers/interrupt_controller/gic.h new file mode 100644 index 000000000000..af87472007d7 --- /dev/null +++ b/include/drivers/interrupt_controller/gic.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2019 Stephanos Ioannidis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_GIC_H_ +#define ZEPHYR_INCLUDE_DRIVERS_GIC_H_ + +int arm_gic_init(void); + +void arm_gic_irq_enable(unsigned int irq); +void arm_gic_irq_disable(unsigned int irq); +int arm_gic_irq_is_enabled(unsigned int irq); +unsigned int arm_gic_irq_get_active(void); +void arm_gic_irq_eoi(unsigned int irq); + +void arm_gic_irq_set_priority( + unsigned int irq, unsigned int prio, unsigned int flags); + +#endif /* ZEPHYR_INCLUDE_DRIVERS_GIC_400_H_ */ diff --git a/include/linker/common-ram.ld b/include/linker/common-ram.ld index 41525be9d657..d95a2b697c1a 100644 --- a/include/linker/common-ram.ld +++ b/include/linker/common-ram.ld @@ -5,7 +5,7 @@ DEVICE_INIT_SECTIONS() } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) -#if defined(CONFIG_GEN_ISR_TABLES) && defined(CONFIG_DYNAMIC_INTERRUPTS) +#if defined(CONFIG_GEN_SW_ISR_TABLE) && defined(CONFIG_DYNAMIC_INTERRUPTS) SECTION_DATA_PROLOGUE(sw_isr_table,,) { /* diff --git a/include/linker/common-rom.ld b/include/linker/common-rom.ld index f1e4db547036..8307edf1b12d 100644 --- a/include/linker/common-rom.ld +++ b/include/linker/common-rom.ld @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: Apache-2.0 */ -#if defined(CONFIG_GEN_ISR_TABLES) && !defined(CONFIG_DYNAMIC_INTERRUPTS) +#if defined(CONFIG_GEN_SW_ISR_TABLE) && !defined(CONFIG_DYNAMIC_INTERRUPTS) SECTION_PROLOGUE(sw_isr_table,,) { /* diff --git a/include/toolchain/gcc.h b/include/toolchain/gcc.h index 936dde341c71..21ca897f1fb7 100644 --- a/include/toolchain/gcc.h +++ b/include/toolchain/gcc.h @@ -217,14 +217,14 @@ do { \ #ifdef CONFIG_ARM -#if defined(CONFIG_ISA_THUMB2) +#if defined(CONFIG_ISA_ARM) -#define FUNC_CODE() .thumb; +#define FUNC_CODE() .code 32 #define FUNC_INSTR(a) -#elif defined(CONFIG_ISA_ARM) +#elif defined(CONFIG_ISA_THUMB2) -#define FUNC_CODE() .code 32 +#define FUNC_CODE() .thumb; #define FUNC_INSTR(a) #else @@ -238,7 +238,7 @@ do { \ #define FUNC_CODE() #define FUNC_INSTR(a) -#endif /* !CONFIG_ARM */ +#endif /* CONFIG_ARM */ #endif /* _ASMLANGUAGE */ @@ -344,14 +344,16 @@ do { \ #endif /* _ASMLANGUAGE */ -#if defined(CONFIG_ARM) && defined(_ASMLANGUAGE) -#if defined(CONFIG_ISA_THUMB2) +#if defined(_ASMLANGUAGE) +#if defined(CONFIG_ARM) +#if defined(CONFIG_ISA_ARM) +#define _ASM_FILE_PROLOGUE .text; .code 32 +#else /* '.syntax unified' is a gcc-ism used in thumb-2 asm files */ #define _ASM_FILE_PROLOGUE .text; .syntax unified; .thumb -#else -#define _ASM_FILE_PROLOGUE .text; .code 32 -#endif -#endif +#endif /* CONFIG_ISA_ARM */ +#endif /* CONFIG_ARM */ +#endif /* _ASMLANGUAGE */ /* * These macros generate absolute symbols for GCC diff --git a/soc/arm/Kconfig b/soc/arm/Kconfig index d83fe84ad49e..6a5a63c9e10d 100644 --- a/soc/arm/Kconfig +++ b/soc/arm/Kconfig @@ -34,7 +34,7 @@ config CPU_HAS_NRF_IDAU config CPU_HAS_FPU_DOUBLE_PRECISION bool - depends on CPU_CORTEX_M7 + depends on (CPU_CORTEX_M7 || CPU_CORTEX_R4 || CPU_CORTEX_R5) select CPU_HAS_FPU help When enabled, indicates that the SoC has a double diff --git a/soc/arm/xilinx_zynqmp/CMakeLists.txt b/soc/arm/xilinx_zynqmp/CMakeLists.txt index 3d770db77d01..a6858f7a83dd 100644 --- a/soc/arm/xilinx_zynqmp/CMakeLists.txt +++ b/soc/arm/xilinx_zynqmp/CMakeLists.txt @@ -4,4 +4,5 @@ zephyr_sources( soc.c + irq.c ) diff --git a/soc/arm/xilinx_zynqmp/Kconfig.defconfig b/soc/arm/xilinx_zynqmp/Kconfig.defconfig index ba74d0a0bdd8..f06f48cfcce0 100644 --- a/soc/arm/xilinx_zynqmp/Kconfig.defconfig +++ b/soc/arm/xilinx_zynqmp/Kconfig.defconfig @@ -10,16 +10,10 @@ config SOC config NUM_IRQS # must be >= the highest interrupt number used # - include the UART interrupts - default 220 - -config 2ND_LVL_ISR_TBL_OFFSET - default 1 - -config MAX_IRQ_PER_AGGREGATOR default 219 -config NUM_2ND_LEVEL_AGGREGATORS - default 1 +config GEN_IRQ_VECTOR_TABLE + default n config SYS_CLOCK_HW_CYCLES_PER_SEC default 12000000 diff --git a/soc/arm/xilinx_zynqmp/Kconfig.soc b/soc/arm/xilinx_zynqmp/Kconfig.soc index 4ad0bc70fa29..f89afb1497e0 100644 --- a/soc/arm/xilinx_zynqmp/Kconfig.soc +++ b/soc/arm/xilinx_zynqmp/Kconfig.soc @@ -6,5 +6,4 @@ config SOC_XILINX_ZYNQMP bool "Xilinx ZynqMP" select CPU_CORTEX_R5 select GIC - select MULTI_LEVEL_INTERRUPTS - select 2ND_LEVEL_INTERRUPTS + select PLATFORM_SPECIFIC_INIT diff --git a/soc/arm/xilinx_zynqmp/dts_fixup.h b/soc/arm/xilinx_zynqmp/dts_fixup.h index 70b231a114d6..3262a429d44e 100644 --- a/soc/arm/xilinx_zynqmp/dts_fixup.h +++ b/soc/arm/xilinx_zynqmp/dts_fixup.h @@ -6,11 +6,11 @@ */ #undef DT_INST_0_XLNX_XUARTPS_IRQ_0 -#define DT_INST_0_XLNX_XUARTPS_IRQ_0 ((DT_INST_0_XLNX_XUARTPS_IRQ_IRQ_0 + 1) << 8) +#define DT_INST_0_XLNX_XUARTPS_IRQ_0 DT_INST_0_XLNX_XUARTPS_IRQ_IRQ_0 #undef DT_INST_0_CDNS_TTC_IRQ_0 -#define DT_INST_0_CDNS_TTC_IRQ_0 ((DT_INST_0_CDNS_TTC_IRQ_IRQ_0 + 1) << 8) +#define DT_INST_0_CDNS_TTC_IRQ_0 DT_INST_0_CDNS_TTC_IRQ_IRQ_0 #undef DT_INST_0_CDNS_TTC_IRQ_1 -#define DT_INST_0_CDNS_TTC_IRQ_1 ((DT_INST_0_CDNS_TTC_IRQ_IRQ_1 + 1) << 8) +#define DT_INST_0_CDNS_TTC_IRQ_1 DT_INST_0_CDNS_TTC_IRQ_IRQ_1 #undef DT_INST_0_CDNS_TTC_IRQ_2 -#define DT_INST_0_CDNS_TTC_IRQ_2 ((DT_INST_0_CDNS_TTC_IRQ_IRQ_2 + 1) << 8) +#define DT_INST_0_CDNS_TTC_IRQ_2 DT_INST_0_CDNS_TTC_IRQ_IRQ_2 diff --git a/soc/arm/xilinx_zynqmp/irq.c b/soc/arm/xilinx_zynqmp/irq.c new file mode 100644 index 000000000000..eaeea7353d5a --- /dev/null +++ b/soc/arm/xilinx_zynqmp/irq.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2019 Stephanos Ioannidis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include + +#include + +void z_soc_irq_init(void) +{ + /* Initialise GIC-400 */ + arm_gic_init(); +} + +void z_soc_irq_enable(unsigned int irq) +{ + /* Enable interrupt */ + arm_gic_irq_enable(irq); +} + +void z_soc_irq_disable(unsigned int irq) +{ + /* Disable interrupt */ + arm_gic_irq_disable(irq); +} + +int z_soc_irq_is_enabled(unsigned int irq) +{ + return arm_gic_irq_is_enabled(irq); +} + +unsigned int z_soc_irq_get_active(void) +{ + return arm_gic_irq_get_active(); +} + +void z_soc_irq_eoi(unsigned int irq) +{ + arm_gic_irq_eoi(irq); +} + +/** + * @internal + * + * @brief Set an interrupt's priority + * + * The priority is verified if ASSERT_ON is enabled. The maximum number + * of priority levels is a little complex, as there are some hardware + * priority levels which are reserved. + * + * @return N/A + */ +void z_soc_irq_priority_set( + unsigned int irq, unsigned int prio, unsigned int flags) +{ + arm_gic_irq_set_priority(irq, prio, flags); +} diff --git a/soc/arm/xilinx_zynqmp/soc.c b/soc/arm/xilinx_zynqmp/soc.c index 68fae6a2c8d0..20e9a2a01dae 100644 --- a/soc/arm/xilinx_zynqmp/soc.c +++ b/soc/arm/xilinx_zynqmp/soc.c @@ -9,7 +9,8 @@ #include #include -#include +#include + /** * * @brief Perform basic hardware initialization @@ -29,3 +30,10 @@ static int soc_init(struct device *arg) } SYS_INIT(soc_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); + +void z_platform_init(void) +{ + unsigned int sctlr = __get_SCTLR(); + sctlr &= ~SCTLR_V_Msk; + __set_SCTLR(sctlr); +} diff --git a/soc/arm/xilinx_zynqmp/soc.h b/soc/arm/xilinx_zynqmp/soc.h index 6df678412334..528a82a650d0 100644 --- a/soc/arm/xilinx_zynqmp/soc.h +++ b/soc/arm/xilinx_zynqmp/soc.h @@ -8,12 +8,10 @@ #ifndef _BOARD__H_ #define _BOARD__H_ -#include - #ifndef _ASMLANGUAGE -#include -#include +/* Define CMSIS configurations */ +#define __CR_REV 1U #endif /* !_ASMLANGUAGE */