Make 'qemu-vexpress-a9' and 'imx6ul' use the same libcpu code.

This commit is contained in:
qz721
2019-03-25 20:03:49 +08:00
parent efd8b404a3
commit 2eb1bef773
47 changed files with 1228 additions and 2957 deletions
+358
View File
File diff suppressed because it is too large Load Diff
+14 -5
View File
@@ -20,6 +20,15 @@
#include <epit.h>
#include <cortex_a.h>
#include <mmu.h>
struct mem_desc platform_mem_desc[] = {
{0x00000000, 0x80000000, 0x00000000, DEVICE_MEM},
{0x80000000, 0xFFF00000, 0x80000000, NORMAL_MEM}
};
const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]);
static void rt_hw_timer_isr(int vector, void *param)
{
rt_tick_increase();
@@ -32,17 +41,17 @@ int rt_hw_timer_init(void)
// Make sure the timer is off.
HW_ARMGLOBALTIMER_CONTROL.B.TIMER_ENABLE = 0;
HW_ARMGLOBALTIMER_CONTROL.B.FCR0 =1;
HW_ARMGLOBALTIMER_CONTROL.B.FCR1 =0;
HW_ARMGLOBALTIMER_CONTROL.B.DBG_ENABLE =0;
// Clear counter.
HW_ARMGLOBALTIMER_COUNTER_HI_WR(0);
HW_ARMGLOBALTIMER_COUNTER_LO_WR(0);
// Now turn on the timer.
HW_ARMGLOBALTIMER_CONTROL.B.TIMER_ENABLE = 1;
+1 -3
View File
@@ -8,14 +8,12 @@ drivers/imx_timer.c
drivers/imx_i2c.c
drivers/imx_uart.c
cpu/armv7_cache.c
cpu/gic.c
cpu/ccm_pll2.c
cpu/mmu.c
cpu/cortex_a_gcc.S
''')
CPPPATH = [ cwd + '/cpu',
cwd + '/include',
cwd + '/include',
cwd + '/include/mx6ul',
cwd + '/include/mx6ul/registers'
]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-157
View File
@@ -1,157 +0,0 @@
/*
* Copyright (c) 2008-2012, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//! @addtogroup diag_mmu
//! @{
/*!
* @file mmu.h
* @brief System memory arrangement.
*/
#ifndef _MMU_H_
#define _MMU_H_
#include "sdk.h"
////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////
//! @brief Memory region attributes.
typedef enum _mmu_memory_type
{
kStronglyOrdered,
kDevice,
kOuterInner_WB_WA,
kOuterInner_WT,
kNoncacheable,
} mmu_memory_type_t;
//! @brief Memory region shareability options.
typedef enum _mmu_shareability
{
kShareable = 1,
kNonshareable = 0
} mmu_shareability_t;
//! @brief Access permissions for a memory region.
typedef enum _mmu_access
{
kNoAccess,
kROAccess,
kRWAccess
} mmu_access_t;
////////////////////////////////////////////////////////////////////////////////
// Prototypes
////////////////////////////////////////////////////////////////////////////////
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Enable the MMU.
*
* The L1 page tables and MMU settings must have already been configured by
* calling mmu_init() before the MMU is enabled.
*/
void mmu_enable();
/*!
* @brief Disable the MMU.
*/
void mmu_disable();
/*!
* @brief Set up the default first-level page table.
*
* Initializes the L1 page table with the following regions:
* - 0x00000000...0x00900000 : ROM and peripherals, strongly-ordered
* - 0x00900000...0x00a00000 : OCRAM, strongly-ordered
* - For MX6DQ or MX6SDL: 0x10000000...0x90000000 : DDR, normal, outer inner, write-back, write-allocate
* - For MX6SL: 0x80000000...0xc0000000 : DDR, normal, outer inner, write-back, write-allocate
*
* If the CPU is participating in SMP, then the DDR regions are made shareable. Otherwise they
* are marked as non-shareable.
*
* The TTBR0 register is set to the base of the L1 table.
*
* All memory domains are configured to allow client access. However, note that only domain 0 is
* used by mmu_map_l1_range().
*/
void mmu_init();
/*!
* @brief Maps a range of memory in the first-level page table.
*
* Entries in the first-level page table are filled in for the range of virtual addresses
* starting at @a va and continuing for @a length bytes. These virtual addreses are mapped
* to the physical addresses starting at @a pa and continuing for @a length bytes. All table
* entries for the range of mapped memory have the same attributes, which are selected with
* the @a memoryType, @a isShareable, and @a access parameters.
*
* @param pa The base physical address of the range to which the virtual address will be mapped.
* @param va The base virtual address of the range.
* @param length The size of the range to be mapped, in bytes. This value must be divisible by 1MB.
* @param memoryType The type of the memory region. This controls caching, buffering, ordering of
* memory accesses, and other attributes of the region.
* @param isShareable The shareability of the physical memory. Ignored for strongly-ordered memory.
* @param access Access permissions.
*/
void mmu_map_l1_range(uint32_t pa, uint32_t va, uint32_t length, mmu_memory_type_t memoryType, mmu_shareability_t isShareable, mmu_access_t access);
/*!
* @brief Convert virtual address to physical.
*
* First attempts a priviledged read translation for the current security mode. If that fails,
* a priviledged write translation, also for the current security mode, is attempted. If this
* second attempt at translation fails, then false will be returned.
*
* @param virtualAddress Virtual address to convert to a physical address.
* @param[out] physicalAddress This parameter is filled in with the physical address corresponding
* to the virtual address passed in @a virtualAddress.
* @retval true The address returned through @a physicalAddress is valid.
* @retval false The conversion failed for some reason.
*/
bool mmu_virtual_to_physical(uint32_t virtualAddress, uint32_t * physicalAddress);
#if defined(__cplusplus)
}
#endif
//! @}
#endif // _MMU_H_
////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////
+96
View File
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-03-22 quanzhao first version
*/
#ifndef __PLATFORM_H__
#define __PLATFORM_H__
#include <rthw.h>
#include <rtthread.h>
/* SOC-relative definitions */
//#include "realview.h"
#include "gic_registers.h"
#include "irq_numbers.h"
/* the maximum number of gic */
# define ARM_GIC_MAX_NR 1
/* the maximum number of interrupts */
#define ARM_GIC_NR_IRQS IMX_INTERRUPT_COUNT
/* the maximum entries of the interrupt table */
#define MAX_HANDLERS IMX_INTERRUPT_COUNT
/* the basic constants needed by gic */
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
{
rt_uint32_t gic_base;
asm volatile ("mrc p15, 4, %0, c15, c0, 0" : "=r"(gic_base));
return gic_base + kGICDBaseOffset;
}
rt_inline rt_uint32_t platform_get_gic_cpu_base(void)
{
rt_uint32_t gic_base;
asm volatile ("mrc p15, 4, %0, c15, c0, 0" : "=r"(gic_base));
return gic_base + kGICCBaseOffset;
}
#define GIC_IRQ_START 0
#define GIC_ACK_INTID_MASK 0x000003ff
/* the definition needed by gic.c */
#define __REG32(x) (*((volatile unsigned int *)(x)))
/* keep compatible with platform SDK */
typedef enum {
CPU_0,
CPU_1,
CPU_2,
CPU_3,
} cpuid_e;
enum _gicd_sgi_filter
{
//! Forward the interrupt to the CPU interfaces specified in the @a target_list parameter.
kGicSgiFilter_UseTargetList = 0,
//! Forward the interrupt to all CPU interfaces except that of the processor that requested
//! the interrupt.
kGicSgiFilter_AllOtherCPUs = 1,
//! Forward the interrupt only to the CPU interface of the processor that requested the
//! interrupt.
kGicSgiFilter_OnlyThisCPU = 2
};
typedef void (*irq_hdlr_t) (void);
extern void rt_hw_interrupt_mask(int vector);
extern void rt_hw_interrupt_umask(int vector);
extern rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name);
rt_inline void register_interrupt_routine(uint32_t irq_id, irq_hdlr_t isr)
{
rt_hw_interrupt_install(irq_id, (rt_isr_handler_t)isr, NULL, "unknown");
}
rt_inline void enable_interrupt(uint32_t irq_id, uint32_t cpu_id, uint32_t priority)
{
rt_hw_interrupt_umask(irq_id);
}
rt_inline void disable_interrupt(uint32_t irq_id, uint32_t cpu_id)
{
rt_hw_interrupt_mask(irq_id);
}
#endif /* __PLATFORM_H__ */
-183
View File
@@ -1,183 +0,0 @@
/*
* Copyright (c) 2011-2012, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __GIC_H__
#define __GIC_H__
#include "sdk_types.h"
//! @addtogroup gic
//! @{
////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////
//! @brief Options for sending a software generated interrupt.
//!
//! These options are used for the @a filter_list parameter of the gic_send_sgi()
//! function. They control how to select which CPUs that the interrupt is
//! sent to.
enum _gicd_sgi_filter
{
//! Forward the interrupt to the CPU interfaces specified in the @a target_list parameter.
kGicSgiFilter_UseTargetList = 0,
//! Forward the interrupt to all CPU interfaces except that of the processor that requested
//! the interrupt.
kGicSgiFilter_AllOtherCPUs = 1,
//! Forward the interrupt only to the CPU interface of the processor that requested the
//! interrupt.
kGicSgiFilter_OnlyThisCPU = 2
};
////////////////////////////////////////////////////////////////////////////////
// API
////////////////////////////////////////////////////////////////////////////////
#if defined(__cplusplus)
extern "C" {
#endif
//! @name Initialization
//@{
//! @brief Init interrupt handling.
//!
//! This function is intended to be called only by the primary CPU init code, so it will
//! only be called once during system bootup.
//!
//! Also inits the current CPU. You don't need to call gic_init_cpu() separately.
//!
//! @post The interrupt distributor and the current CPU interface are enabled. All interrupts
//! that were pending are cleared, and all interrupts are made secure (group 0).
void gic_init(void);
//! @brief Init the current CPU's GIC interface.
//!
//! @post Enables the CPU interface and sets the priority mask to 255. Interrupt preemption
//! is disabled by setting the Binary Point to a value of 7.
void gic_init_cpu(void);
//@}
//! @name GIC Interrupt Distributor Functions
//@{
//! @brief Enable or disable the GIC Distributor.
//!
//! Enables or disables the GIC distributor passing both secure (group 0) and non-secure
//! (group 1) interrupts to the CPU interfaces.
//!
//! @param enableIt Pass true to enable or false to disable.
void gic_enable(bool enableIt);
//! @brief Set the security mode for an interrupt.
//!
//! @param irqID The interrupt number.
//! @param isSecure Whether the interrupt is taken to secure mode.
void gic_set_irq_security(uint32_t irqID, bool isSecure);
//! @brief Enable or disable an interrupt.
//!
//! @param irqID The number of the interrupt to control.
//! @param isEnabled Pass true to enable or false to disable.
void gic_enable_irq(uint32_t irqID, bool isEnabled);
//! @brief Set whether a CPU will receive a particular interrupt.
//!
//! @param irqID The interrupt number.
//! @param cpuNumber The CPU number. The first CPU core is 0.
//! @param enableIt Whether to send the interrupt to the specified CPU. Pass true to enable
//! or false to disable.
void gic_set_cpu_target(uint32_t irqID, unsigned cpuNumber, bool enableIt);
//! @brief Set an interrupt's priority.
//!
//! @param irq_id The interrupt number.
//! @param priority The priority for the interrupt. In the range of 0 through 0xff, with
//! 0 being the highest priority.
void gic_set_irq_priority(uint32_t irq_id, uint32_t priority);
//! @brief Send a software generated interrupt to a specific CPU.
//!
//! @param irq_id The interrupt number to send.
//! @param target_list Each bit indicates a CPU to which the interrupt will be forwarded.
//! Bit 0 is CPU 0, bit 1 is CPU 1, and so on. If the value is 0, then the interrupt
//! will not be forwarded to any CPUs. This parameter is only used if @a filter_list
//! is set to #kGicSgiFilter_UseTargetList.
//! @param filter_list One of the enums of the #_gicd_sgi_filter enumeration. The selected
//! option determines which CPUs the interrupt will be sent to. If the value
//! is #kGicSgiFilter_UseTargetList, then the @a target_list parameter is used.
void gic_send_sgi(uint32_t irq_id, uint32_t target_list, uint32_t filter_list);
//@}
//! @name GIC CPU Interface Functions
//@{
//! @brief Enable or disable the interface to the GIC for the current CPU.
//!
//! @param enableIt Pass true to enable or false to disable.
void gic_cpu_enable(bool enableIt);
//! @brief Set the mask of which interrupt priorities the CPU will receive.
//!
//! @param priority The lowest priority that will be passed to the current CPU. Pass 0xff to
//! allow all priority interrupts to signal the CPU.
void gic_set_cpu_priority_mask(uint32_t priority);
//! @brief Acknowledge starting of interrupt handling and get the interrupt number.
//!
//! Normally, this function is called at the beginning of the IRQ handler. It tells the GIC
//! that you are starting to handle an interupt, and returns the number of the interrupt you
//! need to handle. After the interrupt is handled, you should call gic_write_end_of_irq()
//! to signal that the interrupt is completely handled.
//!
//! In some cases, a spurious interrupt might happen. One possibility is if another CPU handles
//! the interrupt. When a spurious interrupt occurs, the end of the interrupt should be indicated
//! but nothing else.
//!
//! @return The number for the highest priority interrupt available for the calling CPU. If
//! the return value is 1022 or 1023, a spurious interrupt has occurred.
uint32_t gic_read_irq_ack(void);
//! @brief Signal the end of handling an interrupt.
//!
//! @param irq_id The number of the interrupt for which handling has finished.
void gic_write_end_of_irq(uint32_t irq_id);
//@}
#if defined(__cplusplus)
}
#endif
//! @}
#endif // __GIC_H__
////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////
-101
View File
@@ -1,101 +0,0 @@
/*
* Copyright (c) 2009-2012, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__
#include "sdk_types.h"
#include "irq_numbers.h"
//! @addtogroup diag_interrupt
//! @{
/*!
* @file interrupt.h
* @brief Interface for the interrupt manager.
*/
////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////
//! @brief
typedef enum {
CPU_0,
CPU_1,
CPU_2,
CPU_3,
} cpuid_e;
//! @brief Interrupt service routine.
typedef void (*irq_hdlr_t) (void);
////////////////////////////////////////////////////////////////////////////////
// API
////////////////////////////////////////////////////////////////////////////////
#if defined(__cplusplus)
extern "C" {
#endif
//! @brief Enable an interrupt.
//!
//! Sets the interrupt priority and makes it non-secure. Then the interrupt is
//! enabled on the CPU specified by @a cpu_id.
//!
//! @param irq_id The interrupt number to enable.
//! @param cpu_id The index of the CPU for which the interrupt will be enabled.
//! @param priority The interrupt priority, from 0-255. Lower numbers have higher priority.
void enable_interrupt(uint32_t irq_id, uint32_t cpu_id, uint32_t priority);
//! @brief Disable an interrupt on the specified CPU.
//!
//! @param irq_id The interrupt number to disabled.
//! @param cpu_id The index of the CPU for which the interrupt will be disabled.
void disable_interrupt(uint32_t irq_id, uint32_t cpu_id);
//! @brief Set the interrupt service routine for the specified interrupt.
//!
//! @param irq_id The interrupt number.
//! @param isr Function that will be called to handle the interrupt.
void register_interrupt_routine(uint32_t irq_id, irq_hdlr_t isr);
//! @brief Interrupt handler that simply prints a message.
void default_interrupt_routine(void);
#if defined(__cplusplus)
}
#endif
//! @}
#endif
////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////
+1 -1
View File
@@ -10,7 +10,7 @@ if os.getenv('RTT_CC'):
# only support GNU GCC compiler.
PLATFORM = 'gcc'
EXEC_PATH = '/opt/gcc-arm-none-eabi-4_8-2014q1_gri/bin'
EXEC_PATH = '/usr/bin'
if os.getenv('RTT_EXEC_PATH'):
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
+1
View File
@@ -322,6 +322,7 @@ CONFIG_RT_USING_LWP=y
# CONFIG_PKG_USING_WEBTERMINAL is not set
# CONFIG_PKG_USING_CJSON is not set
# CONFIG_PKG_USING_JSMN is not set
# CONFIG_PKG_USING_LIBMODBUS is not set
# CONFIG_PKG_USING_LJSON is not set
# CONFIG_PKG_USING_EZXML is not set
# CONFIG_PKG_USING_NANOPB is not set
+2 -2
View File
@@ -5,7 +5,7 @@ import rtconfig
if os.getenv('RTT_ROOT'):
RTT_ROOT = os.getenv('RTT_ROOT')
else:
RTT_ROOT = os.path.normpath(os.getcwd() + '/../..')
RTT_ROOT = os.path.join(os.getcwd(), '..', '..')
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
from building import *
@@ -25,7 +25,7 @@ Export('RTT_ROOT')
Export('rtconfig')
# prepare building environment
objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=True)
objs = PrepareBuilding(env, RTT_ROOT)
# make a building
DoBuilding(TARGET, objs)
-17
View File
@@ -1,17 +0,0 @@
Import('rtconfig')
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
if rtconfig.PLATFORM == 'iar':
src += Glob('*_iar.S')
elif rtconfig.PLATFORM == 'gcc':
src += Glob('*_gcc.S')
elif rtconfig.PLATFORM == 'armcc':
src += Glob('*_rvds.S')
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
-64
View File
@@ -1,64 +0,0 @@
#ifndef __ARMV7_H__
#define __ARMV7_H__
/* the exception stack without VFP registers */
struct rt_hw_exp_stack
{
unsigned long r0;
unsigned long r1;
unsigned long r2;
unsigned long r3;
unsigned long r4;
unsigned long r5;
unsigned long r6;
unsigned long r7;
unsigned long r8;
unsigned long r9;
unsigned long r10;
unsigned long fp;
unsigned long ip;
unsigned long sp;
unsigned long lr;
unsigned long pc;
unsigned long cpsr;
};
struct rt_hw_stack
{
unsigned long cpsr;
unsigned long r0;
unsigned long r1;
unsigned long r2;
unsigned long r3;
unsigned long r4;
unsigned long r5;
unsigned long r6;
unsigned long r7;
unsigned long r8;
unsigned long r9;
unsigned long r10;
unsigned long fp;
unsigned long ip;
unsigned long lr;
unsigned long pc;
};
#define USERMODE 0x10
#define FIQMODE 0x11
#define IRQMODE 0x12
#define SVCMODE 0x13
#define MONITORMODE 0x16
#define ABORTMODE 0x17
#define HYPMODE 0x1b
#define UNDEFMODE 0x1b
#define MODEMASK 0x1f
#define NOINT 0xc0
#define T_Bit (1<<5)
#define F_Bit (1<<6)
#define I_Bit (1<<7)
#define A_Bit (1<<8)
#define E_Bit (1<<9)
#define J_Bit (1<<24)
#endif
-198
View File
@@ -1,198 +0,0 @@
/*
* File : context.S
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2013, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2013-07-05 Bernard the first version
* 2018-11-22 Jesven in the smp version, using macro to
* define rt_hw_interrupt_enable and rt_hw_interrupt_disable
* rt_hw_context_switch_interrupt switches to the new thread directly
*/
#include "rtconfig.h"
.section .text, "ax"
#ifdef RT_USING_SMP
#define rt_hw_interrupt_disable rt_hw_local_irq_disable
#define rt_hw_interrupt_enable rt_hw_local_irq_enable
#endif
/*
* rt_base_t rt_hw_interrupt_disable();
*/
.globl rt_hw_interrupt_disable
rt_hw_interrupt_disable:
mrs r0, cpsr
cpsid i
bx lr
/*
* void rt_hw_interrupt_enable(rt_base_t level);
*/
.globl rt_hw_interrupt_enable
rt_hw_interrupt_enable:
msr cpsr, r0
bx lr
/*
* void rt_hw_context_switch_to(rt_uint32 to);
* r0 --> to
*/
.globl rt_hw_context_switch_to
rt_hw_context_switch_to:
ldr sp, [r0] @ get new task stack pointer
#ifdef RT_USING_SMP
mov r0, r1
bl rt_cpus_lock_status_restore
#endif /*RT_USING_SMP*/
#ifdef RT_USING_LWP
ldmfd sp, {r13, r14}^ @ pop usr_sp usr_lr
add sp, #8
#endif
ldmfd sp!, {r4} @ pop new task spsr
msr spsr_cxsf, r4
ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc
.section .bss.share.isr
_guest_switch_lvl:
.word 0
.section .text.isr, "ax"
/*
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
* r0 --> from
* r1 --> to
*/
.globl rt_hw_context_switch
rt_hw_context_switch:
stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC)
stmfd sp!, {r0-r12, lr} @ push lr & register file
mrs r4, cpsr
tst lr, #0x01
orrne r4, r4, #0x20 @ it's thumb code
stmfd sp!, {r4} @ push cpsr
#ifdef RT_USING_LWP
stmfd sp, {r13, r14}^ @ push usr_sp usr_lr
sub sp, #8
#endif
str sp, [r0] @ store sp in preempted tasks TCB
ldr sp, [r1] @ get new task stack pointer
#ifdef RT_USING_SMP
mov r0, r2
bl rt_cpus_lock_status_restore
#endif /*RT_USING_SMP*/
#ifdef RT_USING_LWP
ldmfd sp, {r13, r14}^ @ pop usr_sp usr_lr
add sp, #8
#endif
ldmfd sp!, {r4} @ pop new task cpsr to spsr
msr spsr_cxsf, r4
ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr
/*
* void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
*/
.equ Mode_USR, 0x10
.equ Mode_FIQ, 0x11
.equ Mode_IRQ, 0x12
.equ Mode_SVC, 0x13
.equ Mode_ABT, 0x17
.equ Mode_UND, 0x1B
.equ Mode_SYS, 0x1F
.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled
.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled
.globl rt_thread_switch_interrupt_flag
.globl rt_interrupt_from_thread
.globl rt_interrupt_to_thread
.globl rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt:
#ifdef RT_USING_SMP
/* r0 :irq_mod context
* r1 :addr of from_thread's sp
* r2 :addr of to_thread's sp
* r3 :to_thread's tcb
*/
@ r0 point to {r0-r3} in stack
push {r1 - r3}
mov r1, r0
add r0, r0, #4*4
ldmfd r0!, {r4-r12,lr}@ reload saved registers
mrs r3, spsr @ get cpsr of interrupt thread
sub r2, lr, #4 @ save old task's pc to r2
msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
stmfd sp!, {r2} @ push old task's pc
stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4
ldmfd r1, {r4-r7} @ restore r0-r3 of the interrupt thread
stmfd sp!, {r4-r7} @ push old task's r0-r3
stmfd sp!, {r3} @ push old task's cpsr
#ifdef RT_USING_LWP
stmfd sp, {r13,r14}^ @push usr_sp usr_lr
sub sp, #8
#endif
msr cpsr_c, #I_Bit|F_Bit|Mode_IRQ
pop {r1 - r3}
mov sp, r0
msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
str sp, [r1]
ldr sp, [r2]
mov r0, r3
bl rt_cpus_lock_status_restore
#ifdef RT_USING_LWP
ldmfd sp, {r13,r14}^ @pop usr_sp usr_lr
add sp, #8
#endif
ldmfd sp!, {r4} @ pop new task's cpsr to spsr
msr spsr_cxsf, r4
ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
#else /*RT_USING_SMP*/
ldr r2, =rt_thread_switch_interrupt_flag
ldr r3, [r2]
cmp r3, #1
beq _reswitch
ldr ip, =rt_interrupt_from_thread @ set rt_interrupt_from_thread
mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1
str r0, [ip]
str r3, [r2]
_reswitch:
ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread
str r1, [r2]
bx lr
#endif /*RT_USING_SMP*/
-12
View File
@@ -1,12 +0,0 @@
#ifndef __CP15_H__
#define __CP15_H__
unsigned long rt_cpu_get_smp_id(void);
void rt_cpu_mmu_disable(void);
void rt_cpu_mmu_enable(void);
void rt_cpu_tlb_set(volatile unsigned long*);
void rt_cpu_vector_set_base(unsigned int addr);
#endif
-140
View File
@@ -1,140 +0,0 @@
/*
* File : cp15_gcc.S
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2013, RT-Thread Development Team
* http://www.rt-thread.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2013-07-05 Bernard the first version
*/
.globl rt_cpu_get_smp_id
rt_cpu_get_smp_id:
mrc p15, #0, r0, c0, c0, #5
bx lr
.globl rt_cpu_vector_set_base
rt_cpu_vector_set_base:
mcr p15, #0, r0, c12, c0, #0
dsb
bx lr
.globl rt_hw_cpu_dcache_enable
rt_hw_cpu_dcache_enable:
mrc p15, #0, r0, c1, c0, #0
orr r0, r0, #0x00000004
mcr p15, #0, r0, c1, c0, #0
bx lr
.globl rt_hw_cpu_icache_enable
rt_hw_cpu_icache_enable:
mrc p15, #0, r0, c1, c0, #0
orr r0, r0, #0x00001000
mcr p15, #0, r0, c1, c0, #0
bx lr
_FLD_MAX_WAY:
.word 0x3ff
_FLD_MAX_IDX:
.word 0x7ff
.globl rt_cpu_dcache_clean_flush
rt_cpu_dcache_clean_flush:
push {r4-r11}
dmb
mrc p15, #1, r0, c0, c0, #1 @ read clid register
ands r3, r0, #0x7000000 @ get level of coherency
mov r3, r3, lsr #23
beq finished
mov r10, #0
loop1:
add r2, r10, r10, lsr #1
mov r1, r0, lsr r2
and r1, r1, #7
cmp r1, #2
blt skip
mcr p15, #2, r10, c0, c0, #0
isb
mrc p15, #1, r1, c0, c0, #0
and r2, r1, #7
add r2, r2, #4
ldr r4, _FLD_MAX_WAY
ands r4, r4, r1, lsr #3
clz r5, r4
ldr r7, _FLD_MAX_IDX
ands r7, r7, r1, lsr #13
loop2:
mov r9, r4
loop3:
orr r11, r10, r9, lsl r5
orr r11, r11, r7, lsl r2
mcr p15, #0, r11, c7, c14, #2
subs r9, r9, #1
bge loop3
subs r7, r7, #1
bge loop2
skip:
add r10, r10, #2
cmp r3, r10
bgt loop1
finished:
dsb
isb
pop {r4-r11}
bx lr
.globl rt_hw_cpu_dcache_disable
rt_hw_cpu_dcache_disable:
push {r4-r11, lr}
bl rt_cpu_dcache_clean_flush
mrc p15, #0, r0, c1, c0, #0
bic r0, r0, #0x00000004
mcr p15, #0, r0, c1, c0, #0
pop {r4-r11, lr}
bx lr
.globl rt_hw_cpu_icache_disable
rt_hw_cpu_icache_disable:
mrc p15, #0, r0, c1, c0, #0
bic r0, r0, #0x00001000
mcr p15, #0, r0, c1, c0, #0
bx lr
.globl rt_cpu_mmu_disable
rt_cpu_mmu_disable:
mcr p15, #0, r0, c8, c7, #0 @ invalidate tlb
mrc p15, #0, r0, c1, c0, #0
bic r0, r0, #1
mcr p15, #0, r0, c1, c0, #0 @ clear mmu bit
dsb
bx lr
.globl rt_cpu_mmu_enable
rt_cpu_mmu_enable:
mrc p15, #0, r0, c1, c0, #0
orr r0, r0, #0x001
mcr p15, #0, r0, c1, c0, #0 @ set mmu enable bit
dsb
bx lr
.globl rt_cpu_tlb_set
rt_cpu_tlb_set:
mcr p15, #0, r0, c2, c0, #0
dmb
bx lr
-83
View File
@@ -1,83 +0,0 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2011-09-15 Bernard first version
* 2018-11-22 Jesven add rt_hw_cpu_id()
*/
#include <rthw.h>
#include <rtthread.h>
#include <board.h>
#ifdef RT_USING_SMP
int rt_hw_cpu_id(void)
{
int cpu_id;
__asm__ volatile (
"mrc p15, 0, %0, c0, c0, 5"
:"=r"(cpu_id)
);
cpu_id &= 0xf;
return cpu_id;
};
void rt_hw_spin_lock(rt_hw_spinlock_t *lock)
{
unsigned long tmp;
unsigned long newval;
rt_hw_spinlock_t lockval;
__asm__ __volatile__(
"pld [%0]"
::"r"(&lock->slock)
);
__asm__ __volatile__(
"1: ldrex %0, [%3]\n"
" add %1, %0, %4\n"
" strex %2, %1, [%3]\n"
" teq %2, #0\n"
" bne 1b"
: "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
: "r" (&lock->slock), "I" (1 << 16)
: "cc");
while (lockval.tickets.next != lockval.tickets.owner) {
__asm__ __volatile__("wfe":::"memory");
lockval.tickets.owner = *(volatile unsigned short *)(&lock->tickets.owner);
}
__asm__ volatile ("dmb":::"memory");
}
void rt_hw_spin_unlock(rt_hw_spinlock_t *lock)
{
__asm__ volatile ("dmb":::"memory");
lock->tickets.owner++;
__asm__ volatile ("dsb ishst\nsev":::"memory");
}
#endif /*RT_USING_SMP*/
/**
* @addtogroup ARM CPU
*/
/*@{*/
/** shutdown CPU */
void rt_hw_cpu_shutdown()
{
rt_uint32_t level;
rt_kprintf("shutdown...\n");
level = rt_hw_interrupt_disable();
while (level)
{
RT_ASSERT(0);
}
}
/*@}*/
-108
View File
@@ -1,108 +0,0 @@
/*
* File : interrupt.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2013-2014, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2013-07-06 Bernard first version
* 2018-11-22 Jesven add smp support
*/
#include <rthw.h>
#include <rtthread.h>
#include "realview.h"
#include "gic.h"
#define MAX_HANDLERS NR_IRQS_PBA8
/* exception and interrupt handler table */
struct rt_irq_desc isr_table[MAX_HANDLERS];
#ifndef RT_USING_SMP
/* Those varibles will be accessed in ISR, so we need to share them. */
rt_uint32_t rt_interrupt_from_thread = 0;
rt_uint32_t rt_interrupt_to_thread = 0;
rt_uint32_t rt_thread_switch_interrupt_flag = 0;
#endif
const unsigned int VECTOR_BASE = 0x00;
extern void rt_cpu_vector_set_base(unsigned int addr);
extern int system_vectors;
void rt_hw_vector_init(void)
{
rt_cpu_vector_set_base((unsigned int)&system_vectors);
}
/**
* This function will initialize hardware interrupt
*/
void rt_hw_interrupt_init(void)
{
rt_uint32_t gic_cpu_base;
rt_uint32_t gic_dist_base;
/* initialize vector table */
rt_hw_vector_init();
/* initialize exceptions table */
rt_memset(isr_table, 0x00, sizeof(isr_table));
/* initialize ARM GIC */
gic_dist_base = REALVIEW_GIC_DIST_BASE;
gic_cpu_base = REALVIEW_GIC_CPU_BASE;
arm_gic_dist_init(0, gic_dist_base, 0);
arm_gic_cpu_init(0, gic_cpu_base);
}
/**
* This function will mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_mask(int vector)
{
arm_gic_mask(0, vector);
}
/**
* This function will un-mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_umask(int vector)
{
arm_gic_umask(0, vector);
}
/**
* This function will install a interrupt service routine to a interrupt.
* @param vector the interrupt number
* @param new_handler the interrupt service routine to be installed
* @param old_handler the old interrupt service routine
*/
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name)
{
rt_isr_handler_t old_handler = RT_NULL;
if (vector < MAX_HANDLERS)
{
old_handler = isr_table[vector].handler;
if (handler != RT_NULL)
{
#ifdef RT_USING_INTERRUPT_INFO
rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
#endif /* RT_USING_INTERRUPT_INFO */
isr_table[vector].handler = handler;
isr_table[vector].param = param;
}
}
return old_handler;
}
-25
View File
@@ -1,25 +0,0 @@
/*
* File : interrupt.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2011, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2013-07-06 Bernard first version
*/
#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__
#define INT_IRQ 0x00
#define INT_FIQ 0x01
void rt_hw_interrupt_control(int vector, int priority, int route);
void rt_hw_interrupt_init(void);
#endif
File diff suppressed because it is too large Load Diff
-12
View File
@@ -1,12 +0,0 @@
#include <rtthread.h>
#include "pmu.h"
void rt_hw_pmu_dump_feature(void)
{
unsigned long reg;
reg = rt_hw_pmu_get_control();
rt_kprintf("ARM PMU Implementor: %c, ID code: %02x, %d counters\n",
reg >> 24, (reg >> 16) & 0xff, (reg >> 11) & 0x1f);
RT_ASSERT(ARM_PMU_CNTER_NR == ((reg >> 11) & 0x1f));
}
-151
View File
@@ -1,151 +0,0 @@
#ifndef __PMU_H__
#define __PMU_H__
#include "board.h"
/* Number of counters */
#define ARM_PMU_CNTER_NR 4
enum rt_hw_pmu_event_type {
ARM_PMU_EVENT_PMNC_SW_INCR = 0x00,
ARM_PMU_EVENT_L1_ICACHE_REFILL = 0x01,
ARM_PMU_EVENT_ITLB_REFILL = 0x02,
ARM_PMU_EVENT_L1_DCACHE_REFILL = 0x03,
ARM_PMU_EVENT_L1_DCACHE_ACCESS = 0x04,
ARM_PMU_EVENT_DTLB_REFILL = 0x05,
ARM_PMU_EVENT_MEM_READ = 0x06,
ARM_PMU_EVENT_MEM_WRITE = 0x07,
ARM_PMU_EVENT_INSTR_EXECUTED = 0x08,
ARM_PMU_EVENT_EXC_TAKEN = 0x09,
ARM_PMU_EVENT_EXC_EXECUTED = 0x0A,
ARM_PMU_EVENT_CID_WRITE = 0x0B,
};
/* Enable bit */
#define ARM_PMU_PMCR_E (0x01 << 0)
/* Event counter reset */
#define ARM_PMU_PMCR_P (0x01 << 1)
/* Cycle counter reset */
#define ARM_PMU_PMCR_C (0x01 << 2)
/* Cycle counter divider */
#define ARM_PMU_PMCR_D (0x01 << 3)
#ifdef __GNUC__
rt_inline void rt_hw_pmu_enable_cnt(int divide64)
{
unsigned long pmcr;
unsigned long pmcntenset;
asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
pmcr |= ARM_PMU_PMCR_E | ARM_PMU_PMCR_P | ARM_PMU_PMCR_C;
if (divide64)
pmcr |= ARM_PMU_PMCR_D;
else
pmcr &= ~ARM_PMU_PMCR_D;
asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
/* enable all the counters */
pmcntenset = ~0;
asm volatile ("mcr p15, 0, %0, c9, c12, 1" :: "r"(pmcntenset));
/* clear overflows(just in case) */
asm volatile ("mcr p15, 0, %0, c9, c12, 3" :: "r"(pmcntenset));
}
rt_inline unsigned long rt_hw_pmu_get_control(void)
{
unsigned long pmcr;
asm ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
return pmcr;
}
rt_inline unsigned long rt_hw_pmu_get_ceid(void)
{
unsigned long reg;
/* only PMCEID0 is supported, PMCEID1 is RAZ. */
asm ("mrc p15, 0, %0, c9, c12, 6" : "=r"(reg));
return reg;
}
rt_inline unsigned long rt_hw_pmu_get_cnten(void)
{
unsigned long pmcnt;
asm ("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcnt));
return pmcnt;
}
rt_inline void rt_hw_pmu_reset_cycle(void)
{
unsigned long pmcr;
asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
pmcr |= ARM_PMU_PMCR_C;
asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
asm volatile ("isb");
}
rt_inline void rt_hw_pmu_reset_event(void)
{
unsigned long pmcr;
asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
pmcr |= ARM_PMU_PMCR_P;
asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
asm volatile ("isb");
}
rt_inline unsigned long rt_hw_pmu_get_cycle(void)
{
unsigned long cyc;
asm volatile ("isb");
asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r"(cyc));
return cyc;
}
rt_inline void rt_hw_pmu_select_counter(int idx)
{
RT_ASSERT(idx < ARM_PMU_CNTER_NR);
asm volatile ("mcr p15, 0, %0, c9, c12, 5" : : "r"(idx));
/* Linux add an isb here, don't know why here. */
asm volatile ("isb");
}
rt_inline void rt_hw_pmu_select_event(int idx,
enum rt_hw_pmu_event_type eve)
{
RT_ASSERT(idx < ARM_PMU_CNTER_NR);
rt_hw_pmu_select_counter(idx);
asm volatile ("mcr p15, 0, %0, c9, c13, 1" : : "r"(eve));
}
rt_inline unsigned long rt_hw_pmu_read_counter(int idx)
{
unsigned long reg;
rt_hw_pmu_select_counter(idx);
asm volatile ("isb");
asm volatile ("mrc p15, 0, %0, c9, c13, 2" : "=r"(reg));
return reg;
}
rt_inline unsigned long rt_hw_pmu_get_ovsr(void)
{
unsigned long reg;
asm volatile ("isb");
asm ("mrc p15, 0, %0, c9, c12, 3" : "=r"(reg));
return reg;
}
rt_inline void rt_hw_pmu_clear_ovsr(unsigned long reg)
{
asm ("mcr p15, 0, %0, c9, c12, 3" : : "r"(reg));
asm volatile ("isb");
}
#endif
void rt_hw_pmu_dump_feature(void);
#endif /* end of include guard: __PMU_H__ */
-71
View File
@@ -1,71 +0,0 @@
/*
* File : stack.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2011, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2011-09-23 Bernard the first version
* 2011-10-05 Bernard add thumb mode
*/
#include <rtthread.h>
#include <board.h>
/**
* @addtogroup AM33xx
*/
/*@{*/
/**
* This function will initialize thread stack
*
* @param tentry the entry of thread
* @param parameter the parameter of entry
* @param stack_addr the beginning stack address
* @param texit the function will be called when thread exit
*
* @return stack address
*/
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
rt_uint8_t *stack_addr, void *texit)
{
rt_uint32_t *stk;
stack_addr += sizeof(rt_uint32_t);
stack_addr = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 8);
stk = (rt_uint32_t*)stack_addr;
*(--stk) = (rt_uint32_t)tentry; /* entry point */
*(--stk) = (rt_uint32_t)texit; /* lr */
*(--stk) = 0; /* r12 */
*(--stk) = 0; /* r11 */
*(--stk) = 0; /* r10 */
*(--stk) = 0; /* r9 */
*(--stk) = 0; /* r8 */
*(--stk) = 0; /* r7 */
*(--stk) = 0; /* r6 */
*(--stk) = 0; /* r5 */
*(--stk) = 0; /* r4 */
*(--stk) = 0; /* r3 */
*(--stk) = 0; /* r2 */
*(--stk) = 0; /* r1 */
*(--stk) = (rt_uint32_t)parameter; /* r0 : argument */
/* cpsr */
if ((rt_uint32_t)tentry & 0x01)
*(--stk) = SVCMODE | 0x20; /* thumb mode */
else
*(--stk) = SVCMODE; /* arm mode */
#ifdef RT_USING_LWP
*(--stk) = 0; /* user lr */
*(--stk) = 0; /* user sp*/
#endif
/* return task's current stack address */
return (rt_uint8_t *)stk;
}
/*@}*/
File diff suppressed because it is too large Load Diff
-190
View File
@@ -1,190 +0,0 @@
/*
* File : trap.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2013, RT-Thread Develop Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2013-07-20 Bernard first version
*/
#include <rtthread.h>
#include <rthw.h>
#include <board.h>
#include "armv7.h"
#include "gic.h"
#ifdef RT_USING_FINSH
extern long list_thread(void);
#endif
/**
* this function will show registers of CPU
*
* @param regs the registers point
*/
void rt_hw_show_register(struct rt_hw_exp_stack *regs)
{
rt_kprintf("Execption:\n");
rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3);
rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7);
rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10);
rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip);
rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc);
rt_kprintf("cpsr:0x%08x\n", regs->cpsr);
}
/**
* When comes across an instruction which it cannot handle,
* it takes the undefined instruction trap.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_undef(struct rt_hw_exp_stack *regs)
{
rt_kprintf("undefined instruction:\n");
rt_hw_show_register(regs);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
/**
* The software interrupt instruction (SWI) is used for entering
* Supervisor mode, usually to request a particular supervisor
* function.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_swi(struct rt_hw_exp_stack *regs)
{
rt_kprintf("software interrupt:\n");
rt_hw_show_register(regs);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
/**
* An abort indicates that the current memory access cannot be completed,
* which occurs during an instruction prefetch.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs)
{
rt_kprintf("prefetch abort:\n");
rt_hw_show_register(regs);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
/**
* An abort indicates that the current memory access cannot be completed,
* which occurs during a data access.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs)
{
rt_kprintf("data abort:");
rt_hw_show_register(regs);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
/**
* Normally, system will never reach here
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_resv(struct rt_hw_exp_stack *regs)
{
rt_kprintf("reserved trap:\n");
rt_hw_show_register(regs);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
#define GIC_ACK_INTID_MASK 0x000003ff
void rt_hw_trap_irq(void)
{
void *param;
unsigned long ir;
unsigned long fullir;
rt_isr_handler_t isr_func;
extern struct rt_irq_desc isr_table[];
fullir = arm_gic_get_active_irq(0);
ir = fullir & GIC_ACK_INTID_MASK;
if (ir == 1023)
{
/* Spurious interrupt */
return;
}
/* get interrupt service routine */
isr_func = isr_table[ir].handler;
#ifdef RT_USING_INTERRUPT_INFO
isr_table[ir].counter++;
#endif
if (isr_func)
{
/* Interrupt for myself. */
param = isr_table[ir].param;
/* turn to interrupt service routine */
isr_func(ir, param);
}
/* end of interrupt */
arm_gic_ack(0, fullir);
}
void rt_hw_trap_fiq(void)
{
void *param;
unsigned long ir;
unsigned long fullir;
rt_isr_handler_t isr_func;
extern struct rt_irq_desc isr_table[];
fullir = arm_gic_get_active_irq(0);
ir = fullir & GIC_ACK_INTID_MASK;
/* get interrupt service routine */
isr_func = isr_table[ir].handler;
param = isr_table[ir].param;
/* turn to interrupt service routine */
isr_func(ir, param);
/* end of interrupt */
arm_gic_ack(0, fullir);
}
-65
View File
@@ -1,65 +0,0 @@
/*
* File : vector_gcc.S
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2013, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2013-07-05 Bernard the first version
*/
.section .vectors, "ax"
.code 32
.globl system_vectors
system_vectors:
ldr pc, _vector_reset
ldr pc, _vector_undef
ldr pc, _vector_swi
ldr pc, _vector_pabt
ldr pc, _vector_dabt
ldr pc, _vector_resv
ldr pc, _vector_irq
ldr pc, _vector_fiq
.globl _reset
.globl vector_undef
.globl vector_swi
.globl vector_pabt
.globl vector_dabt
.globl vector_resv
.globl vector_irq
.globl vector_fiq
_vector_reset:
.word _reset
_vector_undef:
.word vector_undef
_vector_swi:
.word SVC_Handler
_vector_pabt:
.word vector_pabt
_vector_dabt:
.word vector_dabt
_vector_resv:
.word vector_resv
_vector_irq:
.word vector_irq
_vector_fiq:
.word vector_fiq
.balignl 16,0xdeadbeef
+9
View File
@@ -17,6 +17,15 @@
#include "board.h"
#include "drv_timer.h"
#include <mmu.h>
struct mem_desc platform_mem_desc[] = {
{0x10000000, 0x50000000, 0x10000000, DEVICE_MEM},
{0x60000000, 0xe0000000, 0x60000000, NORMAL_MEM}
};
const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]);
#define SYS_CTRL __REG32(REALVIEW_SCTL_BASE)
extern void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler);
+13
View File
@@ -0,0 +1,13 @@
from building import *
cwd = GetCurrentDir()
src = Split('''
''')
CPPPATH = [ cwd + '/cpu',
cwd + '/include',
]
group = DefineGroup('Platform', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-03-22 quanzhao first version
*/
#ifndef __PLATFORM_H__
#define __PLATFORM_H__
/* for 'rt_inline' */
#include <rtdef.h>
/* SOC-relative definitions */
#include "realview.h"
/* the maximum entries of the exception table */
#define MAX_HANDLERS NR_IRQS_PBA8
/* the basic constants and interfaces needed by gic */
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
{
return REALVIEW_GIC_DIST_BASE;
}
rt_inline rt_uint32_t platform_get_gic_cpu_base(void)
{
return REALVIEW_GIC_CPU_BASE;
}
#define GIC_IRQ_START 0
#define GIC_ACK_INTID_MASK 0x000003ff
#endif /* __PLATFORM_H__ */
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -2,14 +2,15 @@ import os
# toolchains options
ARCH='arm'
CPU='cortex-a9'
CPU='cortex-a'
CROSS_TOOL='gcc'
if os.getenv('RTT_CC'):
CROSS_TOOL = os.getenv('RTT_CC')
# only support GNU GCC compiler.
PLATFORM = 'gcc'
EXEC_PATH = '/opt/gcc-arm-none-eabi-4_8-2014q1_gri/bin'
EXEC_PATH = '/usr/bin'
if os.getenv('RTT_EXEC_PATH'):
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
+1 -1
View File
@@ -5,7 +5,7 @@ cwd = GetCurrentDir()
src = []
CPPPATH = [cwd]
support_arch = {"arm": ["cortex-m3", "cortex-m4", "cortex-m7", "arm926", "cortex-a9"]}
support_arch = {"arm": ["cortex-m3", "cortex-m4", "cortex-m7", "arm926", "cortex-a"]}
platform_file = {'armcc': 'rvds.S', 'gcc': 'gcc.S', 'iar': 'iar.S'}
if rtconfig.PLATFORM in platform_file.keys(): # support platforms
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-12-10 Jesven first version
*/
#define Mode_USR 0x10
#define Mode_FIQ 0x11
#define Mode_IRQ 0x12
#define Mode_SVC 0x13
#define Mode_MON 0x16
#define Mode_ABT 0x17
#define Mode_UDF 0x1B
#define Mode_SYS 0x1F
#define A_Bit 0x100
#define I_Bit 0x80 @; when I bit is set, IRQ is disabled
#define F_Bit 0x40 @; when F bit is set, FIQ is disabled
#define T_Bit 0x20
.cpu cortex-a9
.syntax unified
.text
/*
* void lwp_user_entry(args, text, data);
*/
.global lwp_user_entry
.type lwp_user_entry, % function
lwp_user_entry:
mrs r9, cpsr
bic r9, #0x1f
orr r9, #Mode_USR
cpsid i
msr spsr, r9
/* set data address. */
mov r9, r2
movs pc, r1
/*
* void SVC_Handler(void);
*/
.global SVC_Handler
.type SVC_Handler, % function
SVC_Handler:
push {lr}
mrs lr, spsr
push {r4, r5, lr}
cpsie i
push {r0 - r3, r12}
and r0, r7, #0xff
bl lwp_get_sys_api
cmp r0, #0 /* r0 = api */
mov lr, r0
pop {r0 - r3, r12}
beq svc_exit
blx lr
svc_exit:
cpsid i
pop {r4, r5, lr}
msr spsr_cxsf, lr
pop {lr}
movs pc, lr
+92
View File
@@ -8,7 +8,14 @@
* 2013-07-05 Bernard the first version
*/
#include "rtconfig.h"
.section .text, "ax"
#ifdef RT_USING_SMP
#define rt_hw_interrupt_disable rt_hw_local_irq_disable
#define rt_hw_interrupt_enable rt_hw_local_irq_enable
#endif
/*
* rt_base_t rt_hw_interrupt_disable();
*/
@@ -34,6 +41,16 @@ rt_hw_interrupt_enable:
rt_hw_context_switch_to:
ldr sp, [r0] @ get new task stack pointer
#ifdef RT_USING_SMP
mov r0, r1
bl rt_cpus_lock_status_restore
#endif /*RT_USING_SMP*/
#ifdef RT_USING_LWP
ldmfd sp, {r13, r14}^ @ pop usr_sp usr_lr
add sp, #8
#endif
ldmfd sp!, {r4} @ pop new task spsr
msr spsr_cxsf, r4
@@ -62,9 +79,24 @@ rt_hw_context_switch:
stmfd sp!, {r4} @ push cpsr
#ifdef RT_USING_LWP
stmfd sp, {r13, r14}^ @ push usr_sp usr_lr
sub sp, #8
#endif
str sp, [r0] @ store sp in preempted tasks TCB
ldr sp, [r1] @ get new task stack pointer
#ifdef RT_USING_SMP
mov r0, r2
bl rt_cpus_lock_status_restore
#endif /*RT_USING_SMP*/
#ifdef RT_USING_LWP
ldmfd sp, {r13, r14}^ @ pop usr_sp usr_lr
add sp, #8
#endif
ldmfd sp!, {r4} @ pop new task cpsr to spsr
msr spsr_cxsf, r4
ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr
@@ -72,11 +104,70 @@ rt_hw_context_switch:
/*
* void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
*/
.equ Mode_USR, 0x10
.equ Mode_FIQ, 0x11
.equ Mode_IRQ, 0x12
.equ Mode_SVC, 0x13
.equ Mode_ABT, 0x17
.equ Mode_UND, 0x1B
.equ Mode_SYS, 0x1F
.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled
.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled
.globl rt_thread_switch_interrupt_flag
.globl rt_interrupt_from_thread
.globl rt_interrupt_to_thread
.globl rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt:
#ifdef RT_USING_SMP
/* r0 :irq_mod context
* r1 :addr of from_thread's sp
* r2 :addr of to_thread's sp
* r3 :to_thread's tcb
*/
@ r0 point to {r0-r3} in stack
push {r1 - r3}
mov r1, r0
add r0, r0, #4*4
ldmfd r0!, {r4-r12,lr}@ reload saved registers
mrs r3, spsr @ get cpsr of interrupt thread
sub r2, lr, #4 @ save old task's pc to r2
msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
stmfd sp!, {r2} @ push old task's pc
stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4
ldmfd r1, {r4-r7} @ restore r0-r3 of the interrupt thread
stmfd sp!, {r4-r7} @ push old task's r0-r3
stmfd sp!, {r3} @ push old task's cpsr
#ifdef RT_USING_LWP
stmfd sp, {r13,r14}^ @push usr_sp usr_lr
sub sp, #8
#endif
msr cpsr_c, #I_Bit|F_Bit|Mode_IRQ
pop {r1 - r3}
mov sp, r0
msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
str sp, [r1]
ldr sp, [r2]
mov r0, r3
bl rt_cpus_lock_status_restore
#ifdef RT_USING_LWP
ldmfd sp, {r13,r14}^ @pop usr_sp usr_lr
add sp, #8
#endif
ldmfd sp!, {r4} @ pop new task's cpsr to spsr
msr spsr_cxsf, r4
ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
#else /*RT_USING_SMP*/
ldr r2, =rt_thread_switch_interrupt_flag
ldr r3, [r2]
cmp r3, #1
@@ -89,3 +180,4 @@ _reswitch:
ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread
str r1, [r2]
bx lr
#endif /*RT_USING_SMP*/
+4
View File
@@ -5,6 +5,7 @@
*
* Change Logs:
* Date Author Notes
* 2018-03-25 quanzhao the first version
*/
#ifndef __CP15_H__
#define __CP15_H__
@@ -15,6 +16,9 @@ void rt_cpu_mmu_disable(void);
void rt_cpu_mmu_enable(void);
void rt_cpu_tlb_set(volatile unsigned long*);
void rt_cpu_dcache_clean_flush(void);
void rt_cpu_icache_flush(void);
void rt_cpu_vector_set_base(unsigned int addr);
#endif
+14 -1
View File
@@ -15,6 +15,11 @@ rt_cpu_get_smp_id:
.globl rt_cpu_vector_set_base
rt_cpu_vector_set_base:
/* clear SCTRL.V to customize the vector address */
mrc p15, #0, r1, c1, c0, #0
bic r1, #(1 << 13)
mcr p15, #0, r1, c1, c0, #0
/* set up the vector address */
mcr p15, #0, r0, c12, c0, #0
dsb
bx lr
@@ -36,7 +41,7 @@ rt_hw_cpu_icache_enable:
_FLD_MAX_WAY:
.word 0x3ff
_FLD_MAX_IDX:
.word 0x7ff
.word 0x7fff
.globl rt_cpu_dcache_clean_flush
rt_cpu_dcache_clean_flush:
@@ -84,6 +89,14 @@ finished:
pop {r4-r11}
bx lr
.globl rt_cpu_icache_flush
rt_cpu_icache_flush:
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
dsb
isb
bx lr
.globl rt_hw_cpu_dcache_disable
rt_hw_cpu_dcache_disable:
push {r4-r11, lr}
+58 -8
View File
@@ -6,28 +6,78 @@
* Change Logs:
* Date Author Notes
* 2011-09-15 Bernard first version
* 2018-11-22 Jesven add rt_hw_cpu_id()
*/
#include <rthw.h>
#include <rtthread.h>
#include <board.h>
#ifdef RT_USING_SMP
int rt_hw_cpu_id(void)
{
int cpu_id;
__asm__ volatile (
"mrc p15, 0, %0, c0, c0, 5"
:"=r"(cpu_id)
);
cpu_id &= 0xf;
return cpu_id;
};
void rt_hw_spin_lock(rt_hw_spinlock_t *lock)
{
unsigned long tmp;
unsigned long newval;
rt_hw_spinlock_t lockval;
__asm__ __volatile__(
"pld [%0]"
::"r"(&lock->slock)
);
__asm__ __volatile__(
"1: ldrex %0, [%3]\n"
" add %1, %0, %4\n"
" strex %2, %1, [%3]\n"
" teq %2, #0\n"
" bne 1b"
: "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
: "r" (&lock->slock), "I" (1 << 16)
: "cc");
while (lockval.tickets.next != lockval.tickets.owner) {
__asm__ __volatile__("wfe":::"memory");
lockval.tickets.owner = *(volatile unsigned short *)(&lock->tickets.owner);
}
__asm__ volatile ("dmb":::"memory");
}
void rt_hw_spin_unlock(rt_hw_spinlock_t *lock)
{
__asm__ volatile ("dmb":::"memory");
lock->tickets.owner++;
__asm__ volatile ("dsb ishst\nsev":::"memory");
}
#endif /*RT_USING_SMP*/
/**
* @addtogroup AM33xx
* @addtogroup ARM CPU
*/
/*@{*/
/** shutdown CPU */
void rt_hw_cpu_shutdown()
{
rt_uint32_t level;
rt_kprintf("shutdown...\n");
rt_uint32_t level;
rt_kprintf("shutdown...\n");
level = rt_hw_interrupt_disable();
while (level)
{
RT_ASSERT(0);
}
level = rt_hw_interrupt_disable();
while (level)
{
RT_ASSERT(0);
}
}
/*@}*/
@@ -1,11 +1,7 @@
/*
* File : gic.c, ARM Generic Interrupt Controller
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2013-2014, RT-Thread Develop Team
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
@@ -17,18 +13,19 @@
#include <rthw.h>
#include <rtthread.h>
#include <board.h>
#include "gic.h"
#include "cp15.h"
struct arm_gic
{
rt_uint32_t offset;
rt_uint32_t offset; /* the first interrupt index in the vector table */
rt_uint32_t dist_hw_base;
rt_uint32_t cpu_hw_base;
rt_uint32_t dist_hw_base; /* the base address of the gic distributor */
rt_uint32_t cpu_hw_base; /* the base addrees of the gic cpu interface */
};
/* 'ARM_GIC_MAX_NR' is the number of cores */
static struct arm_gic _gic_table[ARM_GIC_MAX_NR];
#define GIC_CPU_CTRL(hw_base) __REG32((hw_base) + 0x00)
@@ -118,6 +115,7 @@ void arm_gic_clear_active(rt_uint32_t index, int irq)
GIC_DIST_ACTIVE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
}
/* Set up the cpu mask for the specific interrupt */
void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask)
{
rt_uint32_t old_tgt;
@@ -215,11 +213,12 @@ int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start)
*/
if (_gic_max_irq > 1020)
_gic_max_irq = 1020;
if (_gic_max_irq > ARM_GIC_NR_IRQS)
if (_gic_max_irq > ARM_GIC_NR_IRQS) /* the platform maximum interrupts */
_gic_max_irq = ARM_GIC_NR_IRQS;
cpumask |= cpumask << 8;
cpumask |= cpumask << 16;
cpumask |= cpumask << 24;
GIC_DIST_CTRL(dist_base) = 0x0;
@@ -244,9 +243,11 @@ int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start)
for (i = 0; i < _gic_max_irq; i += 32)
GIC_DIST_IGROUP(dist_base, i) = 0xffffffff;
#endif
for (i = 0; i < _gic_max_irq; i += 32)
GIC_DIST_IGROUP(dist_base, i) = 0;
/* Enable group0 and group1 interrupt forwarding. */
GIC_DIST_CTRL(dist_base) = 0x03;
GIC_DIST_CTRL(dist_base) = 0x01;
return 0;
}
@@ -258,6 +259,7 @@ int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base)
_gic_table[index].cpu_hw_base = cpu_base;
GIC_CPU_PRIMASK(cpu_base) = 0xf0;
GIC_CPU_BINPOINT(cpu_base) = 0x7;
/* Enable CPU interrupt */
GIC_CPU_CTRL(cpu_base) = 0x01;
@@ -1,11 +1,7 @@
/*
* File : gic.h, ARM Generic Interrupt Controller
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2013, RT-Thread Develop Team
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
@@ -15,6 +11,9 @@
#ifndef __GIC_H__
#define __GIC_H__
#include <rthw.h>
#include <platform.h>
int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start);
int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base);
@@ -26,8 +25,11 @@ void arm_gic_set_group(rt_uint32_t index, int vector, int group);
int arm_gic_get_active_irq(rt_uint32_t index);
void arm_gic_ack(rt_uint32_t index, int irq);
void arm_gic_clear_active(rt_uint32_t index, int irq);
void arm_gic_clear_pending(rt_uint32_t index, int irq);
void arm_gic_dump_type(rt_uint32_t index);
void rt_hw_vector_init(void);
void arm_gic_dump(rt_uint32_t index);
#endif
+48 -73
View File
@@ -6,68 +6,32 @@
* Change Logs:
* Date Author Notes
* 2013-07-06 Bernard first version
* 2014-04-03 Grissiom port to VMM
* 2018-11-22 Jesven add smp support
*/
#include <rthw.h>
#include <rtthread.h>
#include "interrupt.h"
#include "gic.h"
#include <irq_numbers.h>
#include <interrupt.h>
#include <gic.h>
#include "cp15.h"
#define MAX_HANDLERS IMX_INTERRUPT_COUNT
extern volatile rt_uint8_t rt_interrupt_nest;
/* exception and interrupt handler table */
struct rt_irq_desc isr_table[MAX_HANDLERS];
rt_uint32_t rt_interrupt_from_thread;
rt_uint32_t rt_interrupt_to_thread;
rt_uint32_t rt_thread_switch_interrupt_flag;
#ifndef RT_USING_SMP
/* Those varibles will be accessed in ISR, so we need to share them. */
rt_uint32_t rt_interrupt_from_thread = 0;
rt_uint32_t rt_interrupt_to_thread = 0;
rt_uint32_t rt_thread_switch_interrupt_flag = 0;
#endif
const unsigned int VECTOR_BASE = 0x00;
extern void rt_cpu_vector_set_base(unsigned int addr);
extern int system_vectors;
/* keep compatible with platform SDK */
void register_interrupt_routine(uint32_t irq_id, irq_hdlr_t isr)
void rt_hw_vector_init(void)
{
rt_hw_interrupt_install(irq_id, (rt_isr_handler_t)isr, NULL, "unknown");
}
void enable_interrupt(uint32_t irq_id, uint32_t cpu_id, uint32_t priority)
{
gic_set_irq_priority(irq_id, priority);
gic_set_irq_security(irq_id, false); // set IRQ as non-secure
gic_set_cpu_target(irq_id, cpu_id, true);
gic_enable_irq(irq_id, true);
}
void disable_interrupt(uint32_t irq_id, uint32_t cpu_id)
{
gic_enable_irq(irq_id, false);
gic_set_cpu_target(irq_id, cpu_id, false);
}
static void rt_hw_vector_init(void)
{
int sctrl;
unsigned int *src = (unsigned int *)&system_vectors;
/* C12-C0 is only active when SCTLR.V = 0 */
asm volatile ("mrc p15, #0, %0, c1, c0, #0"
:"=r" (sctrl));
sctrl &= ~(1 << 13);
asm volatile ("mcr p15, #0, %0, c1, c0, #0"
:
:"r" (sctrl));
asm volatile ("mcr p15, #0, %0, c12, c0, #0"
:
:"r" (src));
rt_cpu_vector_set_base((unsigned int)&system_vectors);
}
/**
@@ -75,14 +39,24 @@ static void rt_hw_vector_init(void)
*/
void rt_hw_interrupt_init(void)
{
rt_hw_vector_init();
gic_init();
rt_uint32_t gic_cpu_base;
rt_uint32_t gic_dist_base;
rt_uint32_t gic_irq_start;
/* init interrupt nest, and context in thread sp */
rt_interrupt_nest = 0;
rt_interrupt_from_thread = 0;
rt_interrupt_to_thread = 0;
rt_thread_switch_interrupt_flag = 0;
/* initialize vector table */
rt_hw_vector_init();
/* initialize exceptions table */
rt_memset(isr_table, 0x00, sizeof(isr_table));
/* initialize ARM GIC */
gic_dist_base = platform_get_gic_dist_base();
gic_cpu_base = platform_get_gic_cpu_base();
gic_irq_start = GIC_IRQ_START;
arm_gic_dist_init(0, gic_dist_base, gic_irq_start);
arm_gic_cpu_init(0, gic_cpu_base);
}
/**
@@ -91,7 +65,7 @@ void rt_hw_interrupt_init(void)
*/
void rt_hw_interrupt_mask(int vector)
{
disable_interrupt(vector, 0);
arm_gic_mask(0, vector);
}
/**
@@ -100,9 +74,26 @@ void rt_hw_interrupt_mask(int vector)
*/
void rt_hw_interrupt_umask(int vector)
{
enable_interrupt(vector, 0, 0);
arm_gic_umask(0, vector);
}
/**
* This function returns the active interrupt number.
* @param none
*/
int rt_hw_interrupt_get_irq(void)
{
return arm_gic_get_active_irq(0) & GIC_ACK_INTID_MASK;
}
/**
* This function acknowledges the interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_ack(int vector)
{
arm_gic_ack(0, vector);
}
/**
* This function will install a interrupt service routine to a interrupt.
* @param vector the interrupt number
@@ -126,23 +117,7 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
isr_table[vector].handler = handler;
isr_table[vector].param = param;
}
// arm_gic_set_cpu(0, vector, 1 << rt_cpu_get_smp_id());
}
return old_handler;
}
/**
* Trigger a software IRQ
*
* Since we are running in single core, the target CPU are always CPU0.
*/
void rt_hw_interrupt_trigger(int vector)
{
// arm_gic_trigger(0, 1, vector);
}
void rt_hw_interrupt_clear(int vector)
{
gic_write_end_of_irq(vector);
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2013-07-06 Bernard first version
*/
#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__
#include <rthw.h>
#include <platform.h>
#define INT_IRQ 0x00
#define INT_FIQ 0x01
void rt_hw_interrupt_control(int vector, int priority, int route);
void rt_hw_interrupt_init(void);
void rt_hw_interrupt_mask(int vector);
void rt_hw_interrupt_umask(int vector);
int rt_hw_interrupt_get_irq(void);
void rt_hw_interrupt_ack(int vector);
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name);
#endif
+14 -35
View File
@@ -13,35 +13,7 @@
#include <board.h>
#include "cp15.h"
#define DESC_SEC (0x2)
#define CB (3<<2) //cache_on, write_back
#define CNB (2<<2) //cache_on, write_through
#define NCB (1<<2) //cache_off,WR_BUF on
#define NCNB (0<<2) //cache_off,WR_BUF off
#define AP_RW (3<<10) //supervisor=RW, user=RW
#define AP_RO (2<<10) //supervisor=RW, user=RO
#define XN (1<<4) // eXecute Never
#define DOMAIN_FAULT (0x0)
#define DOMAIN_CHK (0x1)
#define DOMAIN_NOTCHK (0x3)
#define DOMAIN0 (0x0<<5)
#define DOMAIN1 (0x1<<5)
#define DOMAIN0_ATTR (DOMAIN_CHK<<0)
#define DOMAIN1_ATTR (DOMAIN_FAULT<<2)
/* Read/Write, cache, write back */
#define RW_CB (AP_RW|DOMAIN0|CB|DESC_SEC)
/* Read/Write, cache, write through */
#define RW_CNB (AP_RW|DOMAIN0|CNB|DESC_SEC)
/* Read/Write without cache and write buffer */
#define RW_NCNB (AP_RW|DOMAIN0|NCNB|DESC_SEC)
/* Read/Write without cache and write buffer, no execute */
#define RW_NCNBXN (AP_RW|DOMAIN0|NCNB|DESC_SEC|XN)
/* Read/Write without cache and write buffer */
#define RW_FAULT (AP_RW|DOMAIN1|NCNB|DESC_SEC)
#include "mmu.h"
/* dump 2nd level page table */
void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb)
@@ -178,18 +150,25 @@ unsigned long rt_hw_set_domain_register(unsigned long domain_val)
return old_domain;
}
void rt_hw_init_mmu_table(struct mem_desc *mdesc, rt_uint32_t size)
{
/* set page table */
for(; size > 0; size--)
{
rt_hw_mmu_setmtt(mdesc->vaddr_start, mdesc->vaddr_end,
mdesc->paddr_start, mdesc->attr);
mdesc++;
}
}
void rt_hw_mmu_init(void)
{
rt_cpu_dcache_clean_flush();
rt_cpu_icache_flush();
rt_hw_cpu_dcache_disable();
rt_hw_cpu_icache_disable();
rt_cpu_mmu_disable();
/* set page table */
/* 4G 1:1 memory */
rt_hw_mmu_setmtt(0, 0xffffffff-1, 0, RW_CB);
/* IO memory region */
rt_hw_mmu_setmtt(0x44000000, 0x80000000-1, 0x44000000, RW_NCNBXN);
/*rt_hw_cpu_dump_page_table(MMUTable);*/
rt_hw_set_domain_register(0x55555555);
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-03-25 quanzhao the first version
*/
#ifndef __MMU_H_
#define __MMU_H_
#include <rtthread.h>
#define DESC_SEC (0x2)
#define MEMWB (3<<2) /* write back, no write allocate */
#define MEMWT (2<<2) /* write through, no write allocate */
#define SHAREDEVICE (1<<2) /* shared device */
#define STRONGORDER (0<<2) /* strong ordered */
#define XN (1<<4) /* eXecute Never */
#define AP_RW (3<<10) /* supervisor=RW, user=RW */
#define AP_RO (2<<10) /* supervisor=RW, user=RO */
#define SHARED (1<<16) /* shareable */
#define DOMAIN_FAULT (0x0)
#define DOMAIN_CHK (0x1)
#define DOMAIN_NOTCHK (0x3)
#define DOMAIN0 (0x0<<5)
#define DOMAIN1 (0x1<<5)
#define DOMAIN0_ATTR (DOMAIN_CHK<<0)
#define DOMAIN1_ATTR (DOMAIN_FAULT<<2)
/* device mapping type */
#define DEVICE_MEM (SHARED|AP_RW|DOMAIN0|SHAREDEVICE|DESC_SEC|XN)
/* normal memory mapping type */
#define NORMAL_MEM (SHARED|AP_RW|DOMAIN0|MEMWB|DESC_SEC)
struct mem_desc
{
rt_uint32_t vaddr_start;
rt_uint32_t vaddr_end;
rt_uint32_t paddr_start;
rt_uint32_t attr;
};
#endif
+5 -1
View File
@@ -50,13 +50,17 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
*(--stk) = 0xdeadbeef; /* r2 */
*(--stk) = 0xdeadbeef; /* r1 */
*(--stk) = (rt_uint32_t)parameter; /* r0 : argument */
/* cpsr */
if ((rt_uint32_t)tentry & 0x01)
*(--stk) = SVCMODE | 0x20; /* thumb mode */
else
*(--stk) = SVCMODE; /* arm mode */
#ifdef RT_USING_LWP
*(--stk) = 0; /* user lr */
*(--stk) = 0; /* user sp*/
#endif
/* return task's current stack address */
return (rt_uint8_t *)stk;
}
File diff suppressed because it is too large Load Diff
+36 -34
View File
@@ -10,13 +10,11 @@
#include <rtthread.h>
#include <rthw.h>
#include <board.h>
#include <platform.h>
#include "armv7.h"
#include "interrupt.h"
#include "gic.h"
extern struct rt_thread *rt_current_thread;
#ifdef RT_USING_FINSH
extern long list_thread(void);
#endif
@@ -130,48 +128,52 @@ void rt_hw_trap_resv(struct rt_hw_exp_stack *regs)
void rt_hw_trap_irq(void)
{
void *param;
int ir;
rt_isr_handler_t isr_func;
extern struct rt_irq_desc isr_table[];
// vectNum = RESERVED[31:13] | CPUID[12:10] | INTERRUPT_ID[9:0]
// send ack and get ID source
uint32_t vectNum = gic_read_irq_ack();
ir = rt_hw_interrupt_get_irq();
// Check that INT_ID isn't 1023 or 1022 (spurious interrupt)
if (vectNum & 0x0200)
if (ir == 1023)
{
gic_write_end_of_irq(vectNum); // send end of irq
/* Spurious interrupt */
return;
}
else
{
// copy the local value to the global image of CPUID
unsigned cpu = (vectNum >> 10) & 0x7;
unsigned irq = vectNum & 0x1FF;
/* skip warning */
cpu = cpu;
// Call the service routine stored in the handlers array. If there isn't
// one for this IRQ, then call the default handler.
/* get interrupt service routine */
isr_func = isr_table[irq].handler;
/* get interrupt service routine */
isr_func = isr_table[ir].handler;
#ifdef RT_USING_INTERRUPT_INFO
isr_table[irq].counter++;
isr_table[ir].counter++;
#endif
if (isr_func)
{
/* Interrupt for myself. */
param = isr_table[irq].param;
/* turn to interrupt service routine */
isr_func(irq, param);
}
// Signal the end of the irq.
gic_write_end_of_irq(vectNum);
if (isr_func)
{
/* Interrupt for myself. */
param = isr_table[ir].param;
/* turn to interrupt service routine */
isr_func(ir, param);
}
/* end of interrupt */
rt_hw_interrupt_ack(ir);
}
void rt_hw_trap_fiq(void)
{
/* TODO */
void *param;
int ir;
rt_isr_handler_t isr_func;
extern struct rt_irq_desc isr_table[];
ir = rt_hw_interrupt_get_irq();
/* get interrupt service routine */
isr_func = isr_table[ir].handler;
param = isr_table[ir].param;
/* turn to interrupt service routine */
isr_func(ir, param);
/* end of interrupt */
rt_hw_interrupt_ack(ir);
}