From 72db331e52a37770f9a630eb616c6f33f842c2e4 Mon Sep 17 00:00:00 2001 From: Bernard Xiong Date: Tue, 19 Sep 2017 12:14:52 +0800 Subject: [PATCH] [BSP] Add QEMU/VExpress-A9 bsp. --- bsp/qemu-vexpress-a9/.config | 159 +++++++++ bsp/qemu-vexpress-a9/Kconfig | 20 ++ bsp/qemu-vexpress-a9/README.md | 3 + bsp/qemu-vexpress-a9/SConscript | 14 + bsp/qemu-vexpress-a9/SConstruct | 30 ++ bsp/qemu-vexpress-a9/applications/SConscript | 11 + bsp/qemu-vexpress-a9/applications/main.c | 11 + bsp/qemu-vexpress-a9/cpu/SConscript | 17 + bsp/qemu-vexpress-a9/cpu/armv7.h | 64 ++++ bsp/qemu-vexpress-a9/cpu/context_gcc.S | 103 ++++++ bsp/qemu-vexpress-a9/cpu/cp15.h | 12 + bsp/qemu-vexpress-a9/cpu/cp15_gcc.S | 140 ++++++++ bsp/qemu-vexpress-a9/cpu/cpu.c | 37 +++ bsp/qemu-vexpress-a9/cpu/gic.c | 280 ++++++++++++++++ bsp/qemu-vexpress-a9/cpu/gic.h | 32 ++ bsp/qemu-vexpress-a9/cpu/interrupt.c | 113 +++++++ bsp/qemu-vexpress-a9/cpu/interrupt.h | 25 ++ bsp/qemu-vexpress-a9/cpu/mmu.c | 207 ++++++++++++ bsp/qemu-vexpress-a9/cpu/pmu.c | 12 + bsp/qemu-vexpress-a9/cpu/pmu.h | 151 +++++++++ bsp/qemu-vexpress-a9/cpu/stack.c | 65 ++++ bsp/qemu-vexpress-a9/cpu/start_gcc.S | 246 ++++++++++++++ bsp/qemu-vexpress-a9/cpu/trap.c | 191 +++++++++++ bsp/qemu-vexpress-a9/cpu/vector_gcc.S | 64 ++++ bsp/qemu-vexpress-a9/drivers/Kconfig | 7 + bsp/qemu-vexpress-a9/drivers/SConscript | 13 + bsp/qemu-vexpress-a9/drivers/board.c | 91 ++++++ bsp/qemu-vexpress-a9/drivers/board.h | 32 ++ bsp/qemu-vexpress-a9/drivers/realview.h | 322 +++++++++++++++++++ bsp/qemu-vexpress-a9/drivers/serial.c | 183 +++++++++++ bsp/qemu-vexpress-a9/drivers/serial.h | 39 +++ bsp/qemu-vexpress-a9/link.lds | 91 ++++++ bsp/qemu-vexpress-a9/qemu.bat | 1 + bsp/qemu-vexpress-a9/qemu.sh | 1 + bsp/qemu-vexpress-a9/rtconfig.h | 134 ++++++++ bsp/qemu-vexpress-a9/rtconfig.py | 103 ++++++ 36 files changed, 3024 insertions(+) create mode 100644 bsp/qemu-vexpress-a9/.config create mode 100644 bsp/qemu-vexpress-a9/Kconfig create mode 100644 bsp/qemu-vexpress-a9/README.md create mode 100644 bsp/qemu-vexpress-a9/SConscript create mode 100644 bsp/qemu-vexpress-a9/SConstruct create mode 100644 bsp/qemu-vexpress-a9/applications/SConscript create mode 100644 bsp/qemu-vexpress-a9/applications/main.c create mode 100644 bsp/qemu-vexpress-a9/cpu/SConscript create mode 100644 bsp/qemu-vexpress-a9/cpu/armv7.h create mode 100644 bsp/qemu-vexpress-a9/cpu/context_gcc.S create mode 100644 bsp/qemu-vexpress-a9/cpu/cp15.h create mode 100644 bsp/qemu-vexpress-a9/cpu/cp15_gcc.S create mode 100644 bsp/qemu-vexpress-a9/cpu/cpu.c create mode 100644 bsp/qemu-vexpress-a9/cpu/gic.c create mode 100644 bsp/qemu-vexpress-a9/cpu/gic.h create mode 100644 bsp/qemu-vexpress-a9/cpu/interrupt.c create mode 100644 bsp/qemu-vexpress-a9/cpu/interrupt.h create mode 100644 bsp/qemu-vexpress-a9/cpu/mmu.c create mode 100644 bsp/qemu-vexpress-a9/cpu/pmu.c create mode 100644 bsp/qemu-vexpress-a9/cpu/pmu.h create mode 100644 bsp/qemu-vexpress-a9/cpu/stack.c create mode 100644 bsp/qemu-vexpress-a9/cpu/start_gcc.S create mode 100644 bsp/qemu-vexpress-a9/cpu/trap.c create mode 100644 bsp/qemu-vexpress-a9/cpu/vector_gcc.S create mode 100644 bsp/qemu-vexpress-a9/drivers/Kconfig create mode 100644 bsp/qemu-vexpress-a9/drivers/SConscript create mode 100644 bsp/qemu-vexpress-a9/drivers/board.c create mode 100644 bsp/qemu-vexpress-a9/drivers/board.h create mode 100644 bsp/qemu-vexpress-a9/drivers/realview.h create mode 100644 bsp/qemu-vexpress-a9/drivers/serial.c create mode 100644 bsp/qemu-vexpress-a9/drivers/serial.h create mode 100644 bsp/qemu-vexpress-a9/link.lds create mode 100644 bsp/qemu-vexpress-a9/qemu.bat create mode 100644 bsp/qemu-vexpress-a9/qemu.sh create mode 100644 bsp/qemu-vexpress-a9/rtconfig.h create mode 100644 bsp/qemu-vexpress-a9/rtconfig.py diff --git a/bsp/qemu-vexpress-a9/.config b/bsp/qemu-vexpress-a9/.config new file mode 100644 index 000000000..263636ee8 --- /dev/null +++ b/bsp/qemu-vexpress-a9/.config @@ -0,0 +1,159 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Project Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +CONFIG_RT_ALIGN_SIZE=4 +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_DEBUG=y +CONFIG_RT_USING_OVERFLOW_CHECK=y +# CONFIG_RT_DEBUG_INIT is not set +# CONFIG_RT_DEBUG_THREAD is not set +CONFIG_RT_USING_HOOK=y +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +CONFIG_RT_USING_MEMHEAP=y +CONFIG_RT_USING_HEAP=y +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" +# CONFIG_RT_USING_MODULE is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_USING_DESCRIPTION=y +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_DEFAULT_PASSWORD="rtthread" +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_USING_MSH_DEFAULT=y +# CONFIG_FINSH_USING_MSH_ONLY is not set + +# +# Device virtual file system +# +CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_WORKDIR=y +CONFIG_DFS_FILESYSTEMS_MAX=2 +CONFIG_DFS_FD_MAX=4 +CONFIG_RT_USING_DFS_ELMFAT=y +CONFIG_RT_DFS_ELM_CODE_PAGE=437 +CONFIG_RT_DFS_ELM_MAX_LFN=256 +CONFIG_RT_DFS_ELM_DRIVES=2 +CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512 +# CONFIG_RT_DFS_ELM_USE_ERASE is not set +CONFIG_RT_DFS_ELM_REENTRANT=y +CONFIG_RT_USING_DFS_DEVFS=y +# CONFIG_RT_USING_DFS_NET is not set +# CONFIG_RT_USING_DFS_NFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_USING_SERIAL=y +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_I2C is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# libc +# +CONFIG_RT_USING_LIBC=y +CONFIG_RT_USING_PTHREADS=y + +# +# Network stack +# + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# Modbus master and slave stack +# +# CONFIG_RT_USING_MODBUS is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# + +# +# language packages +# + +# +# miscellaneous packages +# +CONFIG_PKG_USING_HELLO=y +CONFIG_PKG_HELLO_PATH="/packages/misc/hello" +CONFIG_PKG_HELLO_VER="v1.0.0" + +# +# multimedia packages +# + +# +# security packages +# + +# +# system packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +CONFIG_RT_USING_UART0=y +CONFIG_RT_USING_UART1=y diff --git a/bsp/qemu-vexpress-a9/Kconfig b/bsp/qemu-vexpress-a9/Kconfig new file mode 100644 index 000000000..2e1b00877 --- /dev/null +++ b/bsp/qemu-vexpress-a9/Kconfig @@ -0,0 +1,20 @@ +mainmenu "RT-Thread Project Configuration" + +config $BSP_DIR + string + option env="BSP_ROOT" + default "." + +config $RTT_DIR + string + option env="RTT_ROOT" + default "../.." + +config $PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/KConfig" +source "$PKGS_DIR/KConfig" +source "$BSP_DIR/drivers/Kconfig" diff --git a/bsp/qemu-vexpress-a9/README.md b/bsp/qemu-vexpress-a9/README.md new file mode 100644 index 000000000..9eb71f3bf --- /dev/null +++ b/bsp/qemu-vexpress-a9/README.md @@ -0,0 +1,3 @@ +RT-Thread for QEMU/vexpress-a9 + +The shell of RT-Thread is on serial0. diff --git a/bsp/qemu-vexpress-a9/SConscript b/bsp/qemu-vexpress-a9/SConscript new file mode 100644 index 000000000..fe0ae941a --- /dev/null +++ b/bsp/qemu-vexpress-a9/SConscript @@ -0,0 +1,14 @@ +# for module compiling +import os +Import('RTT_ROOT') + +cwd = str(Dir('#')) +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/qemu-vexpress-a9/SConstruct b/bsp/qemu-vexpress-a9/SConstruct new file mode 100644 index 000000000..61af0ee62 --- /dev/null +++ b/bsp/qemu-vexpress-a9/SConstruct @@ -0,0 +1,30 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +from building import * + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +Export('RTT_ROOT') +Export('rtconfig') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=True) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/qemu-vexpress-a9/applications/SConscript b/bsp/qemu-vexpress-a9/applications/SConscript new file mode 100644 index 000000000..01eb940df --- /dev/null +++ b/bsp/qemu-vexpress-a9/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/qemu-vexpress-a9/applications/main.c b/bsp/qemu-vexpress-a9/applications/main.c new file mode 100644 index 000000000..d59513bce --- /dev/null +++ b/bsp/qemu-vexpress-a9/applications/main.c @@ -0,0 +1,11 @@ +#include +#include +#include + +int main(void) +{ + printf("hello rt-thread\n"); + + return 0; +} + diff --git a/bsp/qemu-vexpress-a9/cpu/SConscript b/bsp/qemu-vexpress-a9/cpu/SConscript new file mode 100644 index 000000000..b45f95cc1 --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/SConscript @@ -0,0 +1,17 @@ +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') diff --git a/bsp/qemu-vexpress-a9/cpu/armv7.h b/bsp/qemu-vexpress-a9/cpu/armv7.h new file mode 100644 index 000000000..69c556eb3 --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/armv7.h @@ -0,0 +1,64 @@ +#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 diff --git a/bsp/qemu-vexpress-a9/cpu/context_gcc.S b/bsp/qemu-vexpress-a9/cpu/context_gcc.S new file mode 100644 index 000000000..86efcede9 --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/context_gcc.S @@ -0,0 +1,103 @@ +/* + * 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 + */ + +.section .text, "ax" +/* + * 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 + + 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 + + str sp, [r0] @ store sp in preempted tasks TCB + ldr sp, [r1] @ get new task stack pointer + + 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_uint32 from, rt_uint32 to); + */ +.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: + 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 diff --git a/bsp/qemu-vexpress-a9/cpu/cp15.h b/bsp/qemu-vexpress-a9/cpu/cp15.h new file mode 100644 index 000000000..ebea3f0fe --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/cp15.h @@ -0,0 +1,12 @@ +#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 diff --git a/bsp/qemu-vexpress-a9/cpu/cp15_gcc.S b/bsp/qemu-vexpress-a9/cpu/cp15_gcc.S new file mode 100644 index 000000000..f1ed6492a --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/cp15_gcc.S @@ -0,0 +1,140 @@ +/* + * 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 diff --git a/bsp/qemu-vexpress-a9/cpu/cpu.c b/bsp/qemu-vexpress-a9/cpu/cpu.c new file mode 100644 index 000000000..426da965a --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/cpu.c @@ -0,0 +1,37 @@ +/* + * File : cpu.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, 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 + * 2011-09-15 Bernard first version + */ + +#include +#include +#include + +/** + * @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); + } +} + +/*@}*/ diff --git a/bsp/qemu-vexpress-a9/cpu/gic.c b/bsp/qemu-vexpress-a9/cpu/gic.c new file mode 100644 index 000000000..cbef00af2 --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/gic.c @@ -0,0 +1,280 @@ +/* + * File : gic.c, ARM Generic Interrupt Controller + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2013-2014, 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 + * 2014-04-03 Grissiom many enhancements + */ + +#include +#include + +#include "gic.h" +#include "cp15.h" + +struct arm_gic +{ + rt_uint32_t offset; + + rt_uint32_t dist_hw_base; + rt_uint32_t cpu_hw_base; +}; +static struct arm_gic _gic_table[ARM_GIC_MAX_NR]; + +#define GIC_CPU_CTRL(hw_base) __REG32((hw_base) + 0x00) +#define GIC_CPU_PRIMASK(hw_base) __REG32((hw_base) + 0x04) +#define GIC_CPU_BINPOINT(hw_base) __REG32((hw_base) + 0x08) +#define GIC_CPU_INTACK(hw_base) __REG32((hw_base) + 0x0c) +#define GIC_CPU_EOI(hw_base) __REG32((hw_base) + 0x10) +#define GIC_CPU_RUNNINGPRI(hw_base) __REG32((hw_base) + 0x14) +#define GIC_CPU_HIGHPRI(hw_base) __REG32((hw_base) + 0x18) + +#define GIC_DIST_CTRL(hw_base) __REG32((hw_base) + 0x000) +#define GIC_DIST_TYPE(hw_base) __REG32((hw_base) + 0x004) +#define GIC_DIST_IGROUP(hw_base, n) __REG32((hw_base) + 0x080 + ((n)/32) * 4) +#define GIC_DIST_ENABLE_SET(hw_base, n) __REG32((hw_base) + 0x100 + ((n)/32) * 4) +#define GIC_DIST_ENABLE_CLEAR(hw_base, n) __REG32((hw_base) + 0x180 + ((n)/32) * 4) +#define GIC_DIST_PENDING_SET(hw_base, n) __REG32((hw_base) + 0x200 + ((n)/32) * 4) +#define GIC_DIST_PENDING_CLEAR(hw_base, n) __REG32((hw_base) + 0x280 + ((n)/32) * 4) +#define GIC_DIST_ACTIVE_SET(hw_base, n) __REG32((hw_base) + 0x300 + ((n)/32) * 4) +#define GIC_DIST_ACTIVE_CLEAR(hw_base, n) __REG32((hw_base) + 0x380 + ((n)/32) * 4) +#define GIC_DIST_PRI(hw_base, n) __REG32((hw_base) + 0x400 + ((n)/4) * 4) +#define GIC_DIST_TARGET(hw_base, n) __REG32((hw_base) + 0x800 + ((n)/4) * 4) +#define GIC_DIST_CONFIG(hw_base, n) __REG32((hw_base) + 0xc00 + ((n)/16) * 4) +#define GIC_DIST_SOFTINT(hw_base) __REG32((hw_base) + 0xf00) +#define GIC_DIST_CPENDSGI(hw_base, n) __REG32((hw_base) + 0xf10 + ((n)/4) * 4) +#define GIC_DIST_ICPIDR2(hw_base) __REG32((hw_base) + 0xfe8) + +static unsigned int _gic_max_irq; + +int arm_gic_get_active_irq(rt_uint32_t index) +{ + int irq; + + RT_ASSERT(index < ARM_GIC_MAX_NR); + + irq = GIC_CPU_INTACK(_gic_table[index].cpu_hw_base); + irq += _gic_table[index].offset; + return irq; +} + +void arm_gic_ack(rt_uint32_t index, int irq) +{ + rt_uint32_t mask = 1 << (irq % 32); + + RT_ASSERT(index < ARM_GIC_MAX_NR); + + irq = irq - _gic_table[index].offset; + RT_ASSERT(irq >= 0); + + GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask; + GIC_CPU_EOI(_gic_table[index].cpu_hw_base) = irq; + GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask; +} + +void arm_gic_mask(rt_uint32_t index, int irq) +{ + rt_uint32_t mask = 1 << (irq % 32); + + RT_ASSERT(index < ARM_GIC_MAX_NR); + + irq = irq - _gic_table[index].offset; + RT_ASSERT(irq >= 0); + + GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask; +} + +void arm_gic_clear_pending(rt_uint32_t index, int irq) +{ + rt_uint32_t mask = 1 << (irq % 32); + + RT_ASSERT(index < ARM_GIC_MAX_NR); + + irq = irq - _gic_table[index].offset; + RT_ASSERT(irq >= 0); + + GIC_DIST_PENDING_CLEAR(_gic_table[index].dist_hw_base, irq) = mask; +} + +void arm_gic_clear_active(rt_uint32_t index, int irq) +{ + rt_uint32_t mask = 1 << (irq % 32); + + RT_ASSERT(index < ARM_GIC_MAX_NR); + + irq = irq - _gic_table[index].offset; + RT_ASSERT(irq >= 0); + + GIC_DIST_ACTIVE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask; +} + +void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask) +{ + rt_uint32_t old_tgt; + + RT_ASSERT(index < ARM_GIC_MAX_NR); + + irq = irq - _gic_table[index].offset; + RT_ASSERT(irq >= 0); + + old_tgt = GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq); + + old_tgt &= ~(0x0FFUL << ((irq % 4)*8)); + old_tgt |= cpumask << ((irq % 4)*8); + + GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) = old_tgt; +} + +void arm_gic_umask(rt_uint32_t index, int irq) +{ + rt_uint32_t mask = 1 << (irq % 32); + + RT_ASSERT(index < ARM_GIC_MAX_NR); + + irq = irq - _gic_table[index].offset; + RT_ASSERT(irq >= 0); + + GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask; +} + +void arm_gic_dump_type(rt_uint32_t index) +{ + unsigned int gic_type; + + gic_type = GIC_DIST_TYPE(_gic_table[index].dist_hw_base); + rt_kprintf("GICv%d on %p, max IRQs: %d, %s security extension(%08x)\n", + (GIC_DIST_ICPIDR2(_gic_table[index].dist_hw_base) >> 4) & 0xf, + _gic_table[index].dist_hw_base, + _gic_max_irq, + gic_type & (1 << 10) ? "has" : "no", + gic_type); +} + +void arm_gic_dump(rt_uint32_t index) +{ + unsigned int i, k; + + k = GIC_CPU_HIGHPRI(_gic_table[index].cpu_hw_base); + rt_kprintf("--- high pending priority: %d(%08x)\n", k, k); + rt_kprintf("--- hw mask ---\n"); + for (i = 0; i < _gic_max_irq / 32; i++) + { + rt_kprintf("0x%08x, ", + GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, + i * 32)); + } + rt_kprintf("\n--- hw pending ---\n"); + for (i = 0; i < _gic_max_irq / 32; i++) + { + rt_kprintf("0x%08x, ", + GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, + i * 32)); + } + rt_kprintf("\n--- hw active ---\n"); + for (i = 0; i < _gic_max_irq / 32; i++) + { + rt_kprintf("0x%08x, ", + GIC_DIST_ACTIVE_SET(_gic_table[index].dist_hw_base, + i * 32)); + } + rt_kprintf("\n"); +} +#ifdef RT_USING_FINSH +#include +FINSH_FUNCTION_EXPORT_ALIAS(arm_gic_dump, gic, show gic status); +#endif + +int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start) +{ + unsigned int gic_type, i; + rt_uint32_t cpumask = 1 << 0; + + RT_ASSERT(index < ARM_GIC_MAX_NR); + + _gic_table[index].dist_hw_base = dist_base; + _gic_table[index].offset = irq_start; + + /* Find out how many interrupts are supported. */ + gic_type = GIC_DIST_TYPE(dist_base); + _gic_max_irq = ((gic_type & 0x1f) + 1) * 32; + + /* + * The GIC only supports up to 1020 interrupt sources. + * Limit this to either the architected maximum, or the + * platform maximum. + */ + if (_gic_max_irq > 1020) + _gic_max_irq = 1020; + if (_gic_max_irq > ARM_GIC_NR_IRQS) + _gic_max_irq = ARM_GIC_NR_IRQS; + + cpumask |= cpumask << 8; + cpumask |= cpumask << 16; + + GIC_DIST_CTRL(dist_base) = 0x0; + + /* Set all global interrupts to be level triggered, active low. */ + for (i = 32; i < _gic_max_irq; i += 16) + GIC_DIST_CONFIG(dist_base, i) = 0x0; + + /* Set all global interrupts to this CPU only. */ + for (i = 32; i < _gic_max_irq; i += 4) + GIC_DIST_TARGET(dist_base, i) = cpumask; + + /* Set priority on all interrupts. */ + for (i = 0; i < _gic_max_irq; i += 4) + GIC_DIST_PRI(dist_base, i) = 0xa0a0a0a0; + + /* Disable all interrupts. */ + for (i = 0; i < _gic_max_irq; i += 32) + GIC_DIST_ENABLE_CLEAR(dist_base, i) = 0xffffffff; + +#if 0 + /* All interrupts defaults to IGROUP1(IRQ). */ + for (i = 0; i < _gic_max_irq; i += 32) + GIC_DIST_IGROUP(dist_base, i) = 0xffffffff; +#endif + + /* Enable group0 and group1 interrupt forwarding. */ + GIC_DIST_CTRL(dist_base) = 0x03; + + return 0; +} + +int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base) +{ + RT_ASSERT(index < ARM_GIC_MAX_NR); + + _gic_table[index].cpu_hw_base = cpu_base; + + GIC_CPU_PRIMASK(cpu_base) = 0xf0; + /* Enable CPU interrupt */ + GIC_CPU_CTRL(cpu_base) = 0x01; + + return 0; +} + +void arm_gic_set_group(rt_uint32_t index, int vector, int group) +{ + /* As for GICv2, there are only group0 and group1. */ + RT_ASSERT(group <= 1); + RT_ASSERT(vector < _gic_max_irq); + + if (group == 0) + { + GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, + vector) &= ~(1 << (vector % 32)); + } + else if (group == 1) + { + GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, + vector) |= (1 << (vector % 32)); + } +} diff --git a/bsp/qemu-vexpress-a9/cpu/gic.h b/bsp/qemu-vexpress-a9/cpu/gic.h new file mode 100644 index 000000000..42c061dc1 --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/gic.h @@ -0,0 +1,32 @@ +/* + * File : gic.h, ARM Generic Interrupt Controller + * 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 + */ + +#ifndef __GIC_H__ +#define __GIC_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); + +void arm_gic_mask(rt_uint32_t index, int irq); +void arm_gic_umask(rt_uint32_t index, int irq); +void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask); +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_dump_type(rt_uint32_t index); + +#endif + diff --git a/bsp/qemu-vexpress-a9/cpu/interrupt.c b/bsp/qemu-vexpress-a9/cpu/interrupt.c new file mode 100644 index 000000000..e66f74604 --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/interrupt.c @@ -0,0 +1,113 @@ +/* + * 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 + */ + +#include +#include +#include "realview.h" +#include "gic.h" + +#define MAX_HANDLERS NR_IRQS_PBA8 + +extern volatile rt_uint8_t rt_interrupt_nest; + +/* exception and interrupt handler table */ +struct rt_irq_desc isr_table[MAX_HANDLERS]; + +/* Those varibles will be accessed in ISR, so we need to share them. */ +rt_uint32_t rt_interrupt_from_thread; +rt_uint32_t rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrupt_flag; + +const unsigned int VECTOR_BASE = 0x00; +extern void rt_cpu_vector_set_base(unsigned int addr); +extern int system_vectors; + +static 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); + + /* 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; +} + +/** + * 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, 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; +} diff --git a/bsp/qemu-vexpress-a9/cpu/interrupt.h b/bsp/qemu-vexpress-a9/cpu/interrupt.h new file mode 100644 index 000000000..045246b21 --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/interrupt.h @@ -0,0 +1,25 @@ +/* + * 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 diff --git a/bsp/qemu-vexpress-a9/cpu/mmu.c b/bsp/qemu-vexpress-a9/cpu/mmu.c new file mode 100644 index 000000000..b2503e426 --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/mmu.c @@ -0,0 +1,207 @@ +/* + * File : mmu.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, 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 + * 2012-01-10 bernard porting to AM1808 + */ + +#include +#include +#include + +#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) + +/* dump 2nd level page table */ +void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb) +{ + int i; + int fcnt = 0; + + for (i = 0; i < 256; i++) + { + rt_uint32_t pte2 = ptb[i]; + if ((pte2 & 0x3) == 0) + { + if (fcnt == 0) + rt_kprintf(" "); + rt_kprintf("%04x: ", i); + fcnt++; + if (fcnt == 16) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + continue; + } + if (fcnt != 0) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + + rt_kprintf(" %04x: %x: ", i, pte2); + if ((pte2 & 0x3) == 0x1) + { + rt_kprintf("L,ap:%x,xn:%d,texcb:%02x\n", + ((pte2 >> 7) | (pte2 >> 4))& 0xf, + (pte2 >> 15) & 0x1, + ((pte2 >> 10) | (pte2 >> 2)) & 0x1f); + } + else + { + rt_kprintf("S,ap:%x,xn:%d,texcb:%02x\n", + ((pte2 >> 7) | (pte2 >> 4))& 0xf, pte2 & 0x1, + ((pte2 >> 4) | (pte2 >> 2)) & 0x1f); + } + } +} + +void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb) +{ + int i; + int fcnt = 0; + + rt_kprintf("page table@%p\n", ptb); + for (i = 0; i < 1024*4; i++) + { + rt_uint32_t pte1 = ptb[i]; + if ((pte1 & 0x3) == 0) + { + rt_kprintf("%03x: ", i); + fcnt++; + if (fcnt == 16) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + continue; + } + if (fcnt != 0) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + + rt_kprintf("%03x: %08x: ", i, pte1); + if ((pte1 & 0x3) == 0x3) + { + rt_kprintf("LPAE\n"); + } + else if ((pte1 & 0x3) == 0x1) + { + rt_kprintf("pte,ns:%d,domain:%d\n", + (pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf); + /* + *rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000) + * - 0x80000000 + 0xC0000000)); + */ + } + else if (pte1 & (1 << 18)) + { + rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n", + (pte1 >> 19) & 0x1, + ((pte1 >> 13) | (pte1 >> 10))& 0xf, + (pte1 >> 4) & 0x1, + ((pte1 >> 10) | (pte1 >> 2)) & 0x1f); + } + else + { + rt_kprintf("section,ns:%d,ap:%x," + "xn:%d,texcb:%02x,domain:%d\n", + (pte1 >> 19) & 0x1, + ((pte1 >> 13) | (pte1 >> 10))& 0xf, + (pte1 >> 4) & 0x1, + (((pte1 & (0x7 << 12)) >> 10) | + ((pte1 & 0x0c) >> 2)) & 0x1f, + (pte1 >> 5) & 0xf); + } + } +} + +/* level1 page table, each entry for 1MB memory. */ +volatile static unsigned long MMUTable[4*1024] __attribute__((aligned(16*1024))); +void rt_hw_mmu_setmtt(rt_uint32_t vaddrStart, + rt_uint32_t vaddrEnd, + rt_uint32_t paddrStart, + rt_uint32_t attr) +{ + volatile rt_uint32_t *pTT; + volatile int i, nSec; + pTT = (rt_uint32_t *)MMUTable + (vaddrStart >> 20); + nSec = (vaddrEnd >> 20) - (vaddrStart >> 20); + for(i = 0; i <= nSec; i++) + { + *pTT = attr | (((paddrStart >> 20) + i) << 20); + pTT++; + } +} + +unsigned long rt_hw_set_domain_register(unsigned long domain_val) +{ + unsigned long old_domain; + + asm volatile ("mrc p15, 0, %0, c3, c0\n" : "=r" (old_domain)); + asm volatile ("mcr p15, 0, %0, c3, c0\n" : :"r" (domain_val) : "memory"); + + return old_domain; +} + +void rt_hw_mmu_init(void) +{ + 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); + + rt_cpu_tlb_set(MMUTable); + + rt_cpu_mmu_enable(); + + rt_hw_cpu_icache_enable(); + rt_hw_cpu_dcache_enable(); +} + diff --git a/bsp/qemu-vexpress-a9/cpu/pmu.c b/bsp/qemu-vexpress-a9/cpu/pmu.c new file mode 100644 index 000000000..07911a2db --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/pmu.c @@ -0,0 +1,12 @@ +#include +#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)); +} diff --git a/bsp/qemu-vexpress-a9/cpu/pmu.h b/bsp/qemu-vexpress-a9/cpu/pmu.h new file mode 100644 index 000000000..05c1420dd --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/pmu.h @@ -0,0 +1,151 @@ +#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__ */ + diff --git a/bsp/qemu-vexpress-a9/cpu/stack.c b/bsp/qemu-vexpress-a9/cpu/stack.c new file mode 100644 index 000000000..4ae1536a2 --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/stack.c @@ -0,0 +1,65 @@ +/* + * 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 +#include + +/** + * @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; + + 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 */ + + /* return task's current stack address */ + return (rt_uint8_t *)stk; +} + +/*@}*/ diff --git a/bsp/qemu-vexpress-a9/cpu/start_gcc.S b/bsp/qemu-vexpress-a9/cpu/start_gcc.S new file mode 100644 index 000000000..4ab8a4149 --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/start_gcc.S @@ -0,0 +1,246 @@ +/* + * File : start_gcc.S + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2013-2014, 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 + */ + +.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 + +.equ UND_Stack_Size, 0x00000000 +.equ SVC_Stack_Size, 0x00000100 +.equ ABT_Stack_Size, 0x00000000 +.equ RT_FIQ_STACK_PGSZ, 0x00000000 +.equ RT_IRQ_STACK_PGSZ, 0x00000100 +.equ USR_Stack_Size, 0x00000100 + +#define ISR_Stack_Size (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \ + RT_FIQ_STACK_PGSZ + RT_IRQ_STACK_PGSZ) + +.section .data.share.isr +/* stack */ +.globl stack_start +.globl stack_top + +stack_start: +.rept ISR_Stack_Size +.byte 0 +.endr +stack_top: + +.text +/* reset entry */ +.globl _reset +_reset: + /* set the cpu to SVC32 mode and disable interrupt */ + mrs r0, cpsr + bic r0, r0, #0x1f + orr r0, r0, #0x13 + msr cpsr_c, r0 + + /* setup stack */ + bl stack_setup + + /* clear .bss */ + mov r0,#0 /* get a zero */ + ldr r1,=__bss_start /* bss start */ + ldr r2,=__bss_end /* bss end */ + +bss_loop: + cmp r1,r2 /* check if data to clear */ + strlo r0,[r1],#4 /* clear 4 bytes */ + blo bss_loop /* loop until done */ + + /* call C++ constructors of global objects */ + ldr r0, =__ctors_start__ + ldr r1, =__ctors_end__ + +ctor_loop: + cmp r0, r1 + beq ctor_end + ldr r2, [r0], #4 + stmfd sp!, {r0-r1} + mov lr, pc + bx r2 + ldmfd sp!, {r0-r1} + b ctor_loop +ctor_end: + + /* start RT-Thread Kernel */ + ldr pc, _rtthread_startup +_rtthread_startup: + .word rtthread_startup + +stack_setup: + ldr r0, =stack_top + + @ Set the startup stack for svc + mov sp, r0 + + @ Enter Undefined Instruction Mode and set its Stack Pointer + msr cpsr_c, #Mode_UND|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #UND_Stack_Size + + @ Enter Abort Mode and set its Stack Pointer + msr cpsr_c, #Mode_ABT|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #ABT_Stack_Size + + @ Enter FIQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #RT_FIQ_STACK_PGSZ + + @ Enter IRQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #RT_IRQ_STACK_PGSZ + + /* come back to SVC mode */ + msr cpsr_c, #Mode_SVC|I_Bit|F_Bit + bx lr + +/* exception handlers: undef, swi, padt, dabt, resv, irq, fiq */ +.section .text.isr, "ax" + .align 5 +.globl vector_fiq +vector_fiq: + stmfd sp!,{r0-r7,lr} + bl rt_hw_trap_fiq + ldmfd sp!,{r0-r7,lr} + subs pc, lr, #4 + +.globl rt_interrupt_enter +.globl rt_interrupt_leave +.globl rt_thread_switch_interrupt_flag +.globl rt_interrupt_from_thread +.globl rt_interrupt_to_thread + +.globl rt_current_thread + + .align 5 +.globl vector_irq +vector_irq: + stmfd sp!, {r0-r12,lr} + + bl rt_interrupt_enter + bl rt_hw_trap_irq + bl rt_interrupt_leave + + @ if rt_thread_switch_interrupt_flag set, jump to + @ rt_hw_context_switch_interrupt_do and don't return + ldr r0, =rt_thread_switch_interrupt_flag + ldr r1, [r0] + cmp r1, #1 + beq rt_hw_context_switch_interrupt_do + + ldmfd sp!, {r0-r12,lr} + subs pc, lr, #4 + +rt_hw_context_switch_interrupt_do: + mov r1, #0 @ clear flag + str r1, [r0] + + mov r1, sp @ r1 point to {r0-r3} in stack + add sp, sp, #4*4 + ldmfd sp!, {r4-r12,lr}@ reload saved registers + mrs r0, spsr @ get cpsr of interrupt thread + sub r2, lr, #4 @ save old task's pc to r2 + + @ Switch to SVC mode with no interrupt. If the usr mode guest is + @ interrupted, this will just switch to the stack of kernel space. + @ save the registers in kernel space won't trigger data abort. + 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, {r1-r4} @ restore r0-r3 of the interrupt thread + stmfd sp!, {r1-r4} @ push old task's r0-r3 + stmfd sp!, {r0} @ push old task's cpsr + + ldr r4, =rt_interrupt_from_thread + ldr r5, [r4] + str sp, [r5] @ store sp in preempted tasks's TCB + + ldr r6, =rt_interrupt_to_thread + ldr r6, [r6] + ldr sp, [r6] @ get new task's stack pointer + + 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 + +.macro push_svc_reg + sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */ + stmia sp, {r0 - r12} @/* Calling r0-r12 */ + mov r0, sp + mrs r6, spsr @/* Save CPSR */ + str lr, [r0, #15*4] @/* Push PC */ + str r6, [r0, #16*4] @/* Push CPSR */ + cps #Mode_SVC + str sp, [r0, #13*4] @/* Save calling SP */ + str lr, [r0, #14*4] @/* Save calling PC */ +.endm + + .align 5 + .globl vector_swi +vector_swi: + push_svc_reg + bl rt_hw_trap_swi + b . + + .align 5 + .globl vector_undef +vector_undef: + push_svc_reg + bl rt_hw_trap_undef + b . + + .align 5 + .globl vector_pabt +vector_pabt: + push_svc_reg + bl rt_hw_trap_pabt + b . + + .align 5 + .globl vector_dabt +vector_dabt: + push_svc_reg + bl rt_hw_trap_dabt + b . + + .align 5 + .globl vector_resv +vector_resv: + push_svc_reg + bl rt_hw_trap_resv + b . diff --git a/bsp/qemu-vexpress-a9/cpu/trap.c b/bsp/qemu-vexpress-a9/cpu/trap.c new file mode 100644 index 000000000..e3283d7e7 --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/trap.c @@ -0,0 +1,191 @@ +/* + * 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 +#include +#include + +#include "armv7.h" + +#include "gic.h" + +extern struct rt_thread *rt_current_thread; +#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); +} + diff --git a/bsp/qemu-vexpress-a9/cpu/vector_gcc.S b/bsp/qemu-vexpress-a9/cpu/vector_gcc.S new file mode 100644 index 000000000..cbe9bc687 --- /dev/null +++ b/bsp/qemu-vexpress-a9/cpu/vector_gcc.S @@ -0,0 +1,64 @@ +/* + * 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 vector_swi +_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 diff --git a/bsp/qemu-vexpress-a9/drivers/Kconfig b/bsp/qemu-vexpress-a9/drivers/Kconfig new file mode 100644 index 000000000..db0a59d4d --- /dev/null +++ b/bsp/qemu-vexpress-a9/drivers/Kconfig @@ -0,0 +1,7 @@ +config RT_USING_UART0 + bool "Enable UART0" + default y + +config RT_USING_UART1 + bool "Enable UART1" + default y diff --git a/bsp/qemu-vexpress-a9/drivers/SConscript b/bsp/qemu-vexpress-a9/drivers/SConscript new file mode 100644 index 000000000..9987f53e4 --- /dev/null +++ b/bsp/qemu-vexpress-a9/drivers/SConscript @@ -0,0 +1,13 @@ +import copy +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + +CPPPATH = [cwd] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/qemu-vexpress-a9/drivers/board.c b/bsp/qemu-vexpress-a9/drivers/board.c new file mode 100644 index 000000000..4c63b297d --- /dev/null +++ b/bsp/qemu-vexpress-a9/drivers/board.c @@ -0,0 +1,91 @@ +/* + * File : board.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2012, 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 + * 2012-11-20 Bernard the first version + */ + +#include +#include +#include + +#include "board.h" + +#define TIMER_LOAD(hw_base) __REG32(hw_base + 0x00) +#define TIMER_VALUE(hw_base) __REG32(hw_base + 0x04) +#define TIMER_CTRL(hw_base) __REG32(hw_base + 0x08) +#define TIMER_CTRL_ONESHOT (1 << 0) +#define TIMER_CTRL_32BIT (1 << 1) +#define TIMER_CTRL_DIV1 (0 << 2) +#define TIMER_CTRL_DIV16 (1 << 2) +#define TIMER_CTRL_DIV256 (2 << 2) +#define TIMER_CTRL_IE (1 << 5) /* Interrupt Enable (versatile only) */ +#define TIMER_CTRL_PERIODIC (1 << 6) +#define TIMER_CTRL_ENABLE (1 << 7) + +#define TIMER_INTCLR(hw_base) __REG32(hw_base + 0x0c) +#define TIMER_RIS(hw_base) __REG32(hw_base + 0x10) +#define TIMER_MIS(hw_base) __REG32(hw_base + 0x14) +#define TIMER_BGLOAD(hw_base) __REG32(hw_base + 0x18) + +#define SYS_CTRL __REG32(REALVIEW_SCTL_BASE) + +#define TIMER_HW_BASE REALVIEW_TIMER2_3_BASE + +static void rt_hw_timer_isr(int vector, void *param) +{ + rt_tick_increase(); + /* clear interrupt */ + TIMER_INTCLR(TIMER_HW_BASE) = 0x01; +} + +int rt_hw_timer_init(void) +{ + rt_uint32_t val; + + SYS_CTRL |= REALVIEW_REFCLK; + + /* Setup Timer0 for generating irq */ + val = TIMER_CTRL(TIMER_HW_BASE); + val &= ~TIMER_CTRL_ENABLE; + val |= (TIMER_CTRL_32BIT | TIMER_CTRL_PERIODIC | TIMER_CTRL_IE); + TIMER_CTRL(TIMER_HW_BASE) = val; + + TIMER_LOAD(TIMER_HW_BASE) = 1000; + + /* enable timer */ + TIMER_CTRL(TIMER_HW_BASE) |= TIMER_CTRL_ENABLE; + + rt_hw_interrupt_install(IRQ_PBA8_TIMER2_3, rt_hw_timer_isr, RT_NULL, "tick"); + rt_hw_interrupt_umask(IRQ_PBA8_TIMER2_3); + + return 0; +} +INIT_BOARD_EXPORT(rt_hw_timer_init); + +void idle_wfi(void) +{ + asm volatile ("wfi"); +} + +/** + * This function will initialize beaglebone board + */ +void rt_hw_board_init(void) +{ + /* initialzie hardware interrupt */ + rt_hw_interrupt_init(); + rt_system_heap_init(HEAP_BEGIN, HEAP_END); + + rt_components_board_init(); + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); + + rt_thread_idle_sethook(idle_wfi); +} diff --git a/bsp/qemu-vexpress-a9/drivers/board.h b/bsp/qemu-vexpress-a9/drivers/board.h new file mode 100644 index 000000000..2d3d87fdb --- /dev/null +++ b/bsp/qemu-vexpress-a9/drivers/board.h @@ -0,0 +1,32 @@ +/* + * File : board.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2013, 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 the first version + */ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include + +#if defined(__CC_ARM) +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN ((void*)&Image$$RW_IRAM1$$ZI$$Limit) +#elif defined(__GNUC__) +extern int __bss_end; +#define HEAP_BEGIN ((void*)&__bss_end) +#endif + +#define HEAP_END (void*)(0x60000000 + 8 * 1024 * 1024) + +void rt_hw_board_init(void); + +#endif diff --git a/bsp/qemu-vexpress-a9/drivers/realview.h b/bsp/qemu-vexpress-a9/drivers/realview.h new file mode 100644 index 000000000..2e950b1bc --- /dev/null +++ b/bsp/qemu-vexpress-a9/drivers/realview.h @@ -0,0 +1,322 @@ +#ifndef __AM33XX_H__ +#define __AM33XX_H__ + +#define __REG32(x) (*((volatile unsigned int *)(x))) +#define __REG16(x) (*((volatile unsigned short *)(x))) + +/* + * Peripheral addresses + */ +#define REALVIEW_UART0_BASE 0x10009000 /* UART 0 */ +#define REALVIEW_UART1_BASE 0x1000A000 /* UART 1 */ +#define REALVIEW_UART2_BASE 0x1000B000 /* UART 2 */ +#define REALVIEW_UART3_BASE 0x1000C000 /* UART 3 */ +#define REALVIEW_SSP_BASE 0x1000D000 /* Synchronous Serial Port */ +#define REALVIEW_WATCHDOG0_BASE 0x1000F000 /* Watchdog 0 */ +#define REALVIEW_WATCHDOG_BASE 0x10010000 /* watchdog interface */ +#define REALVIEW_TIMER0_1_BASE 0x10011000 /* Timer 0 and 1 */ +#define REALVIEW_TIMER2_3_BASE 0x10012000 /* Timer 2 and 3 */ +#define REALVIEW_GPIO0_BASE 0x10013000 /* GPIO port 0 */ +#define REALVIEW_RTC_BASE 0x10017000 /* Real Time Clock */ +#define REALVIEW_TIMER4_5_BASE 0x10018000 /* Timer 4/5 */ +#define REALVIEW_TIMER6_7_BASE 0x10019000 /* Timer 6/7 */ +#define REALVIEW_SCTL_BASE 0x10001000 /* System Controller */ +#define REALVIEW_CLCD_BASE 0x10020000 /* CLCD */ +#define REALVIEW_ONB_SRAM_BASE 0x10060000 /* On-board SRAM */ +#define REALVIEW_DMC_BASE 0x100E0000 /* DMC configuration */ +#define REALVIEW_SMC_BASE 0x100E1000 /* SMC configuration */ +#define REALVIEW_CAN_BASE 0x100E2000 /* CAN bus */ +#define REALVIEW_GIC_CPU_BASE 0x1E000100 /* Generic interrupt controller CPU interface */ +#define REALVIEW_FLASH0_BASE 0x40000000 +#define REALVIEW_FLASH0_SIZE SZ_64M +#define REALVIEW_FLASH1_BASE 0x44000000 +#define REALVIEW_FLASH1_SIZE SZ_64M + +#define VEXPRESS_SRAM_BASE 0x48000000 + +#define REALVIEW_ETH_BASE 0x4E000000 /* Ethernet */ +#define REALVIEW_USB_BASE 0x4F000000 /* USB */ +#define REALVIEW_GIC_DIST_BASE 0x1E001000 /* Generic interrupt controller distributor */ +#define REALVIEW_LT_BASE 0xC0000000 /* Logic Tile expansion */ +#define REALVIEW_SDRAM6_BASE 0x70000000 /* SDRAM bank 6 256MB */ +#define REALVIEW_SDRAM7_BASE 0x80000000 /* SDRAM bank 7 256MB */ + +#define REALVIEW_SYS_PLD_CTRL1 0x74 + +/* + * PCI regions + */ +#define REALVIEW_PCI_BASE 0x90040000 /* PCI-X Unit base */ +#define REALVIEW_PCI_IO_BASE 0x90050000 /* IO Region on AHB */ +#define REALVIEW_PCI_MEM_BASE 0xA0000000 /* MEM Region on AHB */ + +#define REALVIEW_PCI_BASE_SIZE 0x10000 /* 16 Kb */ +#define REALVIEW_PCI_IO_SIZE 0x1000 /* 4 Kb */ +#define REALVIEW_PCI_MEM_SIZE 0x20000000 /* 512 MB */ + +/* + * Memory definitions + */ +#define REALVIEW_BOOT_ROM_LO 0x30000000 /* DoC Base (64Mb)... */ +#define REALVIEW_BOOT_ROM_HI 0x30000000 +#define REALVIEW_BOOT_ROM_BASE REALVIEW_BOOT_ROM_HI /* Normal position */ +#define REALVIEW_BOOT_ROM_SIZE SZ_64M + +#define REALVIEW_SSRAM_BASE /* REALVIEW_SSMC_BASE ? */ +#define REALVIEW_SSRAM_SIZE SZ_2M + +/* + * SDRAM + */ +#define REALVIEW_SDRAM_BASE 0x00000000 + +/* + * Logic expansion modules + * + */ +#define IRQ_PBA8_GIC_START 32 + +/* + * PB-A8 on-board gic irq sources + */ +#define IRQ_PBA8_WATCHDOG (IRQ_PBA8_GIC_START + 0) /* Watchdog timer */ +#define IRQ_PBA8_SOFT (IRQ_PBA8_GIC_START + 1) /* Software interrupt */ +#define IRQ_PBA8_TIMER0_1 (IRQ_PBA8_GIC_START + 2) /* Timer 0/1 (default timer) */ +#define IRQ_PBA8_TIMER2_3 (IRQ_PBA8_GIC_START + 3) /* Timer 2/3 */ +#define IRQ_PBA8_RTC (IRQ_PBA8_GIC_START + 4) /* Timer 2/3 */ + +#define IRQ_PBA8_UART0 (IRQ_PBA8_GIC_START + 5) /* UART 0 on development chip */ +#define IRQ_PBA8_UART1 (IRQ_PBA8_GIC_START + 6) /* UART 1 on development chip */ +#define IRQ_PBA8_UART2 (IRQ_PBA8_GIC_START + 7) /* UART 2 on development chip */ +#define IRQ_PBA8_UART3 (IRQ_PBA8_GIC_START + 8) /* UART 3 on development chip */ + +/* 9 reserved */ +#define IRQ_PBA8_SSP (IRQ_PBA8_GIC_START + 11) /* Synchronous Serial Port */ +#define IRQ_PBA8_SCI (IRQ_PBA8_GIC_START + 16) /* Smart Card Interface */ +#define IRQ_PBA8_MMCI0A (IRQ_PBA8_GIC_START + 17) /* Multimedia Card 0A */ +#define IRQ_PBA8_MMCI0B (IRQ_PBA8_GIC_START + 18) /* Multimedia Card 0B */ +#define IRQ_PBA8_AACI (IRQ_PBA8_GIC_START + 19) /* Audio Codec */ +#define IRQ_PBA8_KMI0 (IRQ_PBA8_GIC_START + 20) /* Keyboard/Mouse port 0 */ +#define IRQ_PBA8_KMI1 (IRQ_PBA8_GIC_START + 21) /* Keyboard/Mouse port 1 */ +#define IRQ_PBA8_CHARLCD (IRQ_PBA8_GIC_START + 22) /* Character LCD */ +#define IRQ_PBA8_CLCD (IRQ_PBA8_GIC_START + 23) /* CLCD controller */ +#define IRQ_PBA8_DMAC (IRQ_PBA8_GIC_START + 24) /* DMA controller */ +#define IRQ_PBA8_PWRFAIL (IRQ_PBA8_GIC_START + 25) /* Power failure */ +#define IRQ_PBA8_PISMO (IRQ_PBA8_GIC_START + 26) /* PISMO interface */ +#define IRQ_PBA8_DoC (IRQ_PBA8_GIC_START + 27) /* Disk on Chip memory controller */ +#define IRQ_PBA8_ETH (IRQ_PBA8_GIC_START + 28) /* Ethernet controller */ +#define IRQ_PBA8_USB (IRQ_PBA8_GIC_START + 29) /* USB controller */ +#define IRQ_PBA8_TSPEN (IRQ_PBA8_GIC_START + 30) /* Touchscreen pen */ +#define IRQ_PBA8_TSKPAD (IRQ_PBA8_GIC_START + 31) /* Touchscreen keypad */ + +#define IRQ_PBA8_PMU (IRQ_PBA8_GIC_START + 47) /* Cortex-A8 PMU */ + +/* ... */ +#define IRQ_PBA8_PCI0 (IRQ_PBA8_GIC_START + 50) +#define IRQ_PBA8_PCI1 (IRQ_PBA8_GIC_START + 51) +#define IRQ_PBA8_PCI2 (IRQ_PBA8_GIC_START + 52) +#define IRQ_PBA8_PCI3 (IRQ_PBA8_GIC_START + 53) + +#define IRQ_PBA8_SMC -1 +#define IRQ_PBA8_SCTL -1 + +#define NR_GIC_PBA8 1 + +/* + * Only define NR_IRQS if less than NR_IRQS_PBA8 + */ +#define NR_IRQS_PBA8 (IRQ_PBA8_GIC_START + 64) + +/* ------------------------------------------------------------------------ + * RealView Registers + * ------------------------------------------------------------------------ + * + */ +#define REALVIEW_SYS_ID_OFFSET 0x00 +#define REALVIEW_SYS_SW_OFFSET 0x04 +#define REALVIEW_SYS_LED_OFFSET 0x08 +#define REALVIEW_SYS_OSC0_OFFSET 0x0C + +#define REALVIEW_SYS_OSC1_OFFSET 0x10 +#define REALVIEW_SYS_OSC2_OFFSET 0x14 +#define REALVIEW_SYS_OSC3_OFFSET 0x18 +#define REALVIEW_SYS_OSC4_OFFSET 0x1C /* OSC1 for RealView/AB */ + +#define REALVIEW_SYS_LOCK_OFFSET 0x20 +#define REALVIEW_SYS_100HZ_OFFSET 0x24 +#define REALVIEW_SYS_CFGDATA1_OFFSET 0x28 +#define REALVIEW_SYS_CFGDATA2_OFFSET 0x2C +#define REALVIEW_SYS_FLAGS_OFFSET 0x30 +#define REALVIEW_SYS_FLAGSSET_OFFSET 0x30 +#define REALVIEW_SYS_FLAGSCLR_OFFSET 0x34 +#define REALVIEW_SYS_NVFLAGS_OFFSET 0x38 +#define REALVIEW_SYS_NVFLAGSSET_OFFSET 0x38 +#define REALVIEW_SYS_NVFLAGSCLR_OFFSET 0x3C +#define REALVIEW_SYS_RESETCTL_OFFSET 0x40 +#define REALVIEW_SYS_PCICTL_OFFSET 0x44 +#define REALVIEW_SYS_MCI_OFFSET 0x48 +#define REALVIEW_SYS_FLASH_OFFSET 0x4C +#define REALVIEW_SYS_CLCD_OFFSET 0x50 +#define REALVIEW_SYS_CLCDSER_OFFSET 0x54 +#define REALVIEW_SYS_BOOTCS_OFFSET 0x58 +#define REALVIEW_SYS_24MHz_OFFSET 0x5C +#define REALVIEW_SYS_MISC_OFFSET 0x60 +#define REALVIEW_SYS_IOSEL_OFFSET 0x70 +#define REALVIEW_SYS_PROCID_OFFSET 0x84 +#define REALVIEW_SYS_TEST_OSC0_OFFSET 0xC0 +#define REALVIEW_SYS_TEST_OSC1_OFFSET 0xC4 +#define REALVIEW_SYS_TEST_OSC2_OFFSET 0xC8 +#define REALVIEW_SYS_TEST_OSC3_OFFSET 0xCC +#define REALVIEW_SYS_TEST_OSC4_OFFSET 0xD0 + +#define REALVIEW_SYS_BASE 0x10000000 +#define REALVIEW_SYS_ID (REALVIEW_SYS_BASE + REALVIEW_SYS_ID_OFFSET) +#define REALVIEW_SYS_SW (REALVIEW_SYS_BASE + REALVIEW_SYS_SW_OFFSET) +#define REALVIEW_SYS_LED (REALVIEW_SYS_BASE + REALVIEW_SYS_LED_OFFSET) +#define REALVIEW_SYS_OSC0 (REALVIEW_SYS_BASE + REALVIEW_SYS_OSC0_OFFSET) +#define REALVIEW_SYS_OSC1 (REALVIEW_SYS_BASE + REALVIEW_SYS_OSC1_OFFSET) + +#define REALVIEW_SYS_LOCK (REALVIEW_SYS_BASE + REALVIEW_SYS_LOCK_OFFSET) +#define REALVIEW_SYS_100HZ (REALVIEW_SYS_BASE + REALVIEW_SYS_100HZ_OFFSET) +#define REALVIEW_SYS_CFGDATA1 (REALVIEW_SYS_BASE + REALVIEW_SYS_CFGDATA1_OFFSET) +#define REALVIEW_SYS_CFGDATA2 (REALVIEW_SYS_BASE + REALVIEW_SYS_CFGDATA2_OFFSET) +#define REALVIEW_SYS_FLAGS (REALVIEW_SYS_BASE + REALVIEW_SYS_FLAGS_OFFSET) +#define REALVIEW_SYS_FLAGSSET (REALVIEW_SYS_BASE + REALVIEW_SYS_FLAGSSET_OFFSET) +#define REALVIEW_SYS_FLAGSCLR (REALVIEW_SYS_BASE + REALVIEW_SYS_FLAGSCLR_OFFSET) +#define REALVIEW_SYS_NVFLAGS (REALVIEW_SYS_BASE + REALVIEW_SYS_NVFLAGS_OFFSET) +#define REALVIEW_SYS_NVFLAGSSET (REALVIEW_SYS_BASE + REALVIEW_SYS_NVFLAGSSET_OFFSET) +#define REALVIEW_SYS_NVFLAGSCLR (REALVIEW_SYS_BASE + REALVIEW_SYS_NVFLAGSCLR_OFFSET) +#define REALVIEW_SYS_RESETCTL (REALVIEW_SYS_BASE + REALVIEW_SYS_RESETCTL_OFFSET) +#define REALVIEW_SYS_PCICTL (REALVIEW_SYS_BASE + REALVIEW_SYS_PCICTL_OFFSET) +#define REALVIEW_SYS_MCI (REALVIEW_SYS_BASE + REALVIEW_SYS_MCI_OFFSET) +#define REALVIEW_SYS_FLASH (REALVIEW_SYS_BASE + REALVIEW_SYS_FLASH_OFFSET) +#define REALVIEW_SYS_CLCD (REALVIEW_SYS_BASE + REALVIEW_SYS_CLCD_OFFSET) +#define REALVIEW_SYS_CLCDSER (REALVIEW_SYS_BASE + REALVIEW_SYS_CLCDSER_OFFSET) +#define REALVIEW_SYS_BOOTCS (REALVIEW_SYS_BASE + REALVIEW_SYS_BOOTCS_OFFSET) +#define REALVIEW_SYS_24MHz (REALVIEW_SYS_BASE + REALVIEW_SYS_24MHz_OFFSET) +#define REALVIEW_SYS_MISC (REALVIEW_SYS_BASE + REALVIEW_SYS_MISC_OFFSET) +#define REALVIEW_SYS_IOSEL (REALVIEW_SYS_BASE + REALVIEW_SYS_IOSEL_OFFSET) +#define REALVIEW_SYS_PROCID (REALVIEW_SYS_BASE + REALVIEW_SYS_PROCID_OFFSET) +#define REALVIEW_SYS_TEST_OSC0 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC0_OFFSET) +#define REALVIEW_SYS_TEST_OSC1 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC1_OFFSET) +#define REALVIEW_SYS_TEST_OSC2 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC2_OFFSET) +#define REALVIEW_SYS_TEST_OSC3 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC3_OFFSET) +#define REALVIEW_SYS_TEST_OSC4 (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC4_OFFSET) + +#define REALVIEW_SYS_CTRL_LED (1 << 0) + +/* ------------------------------------------------------------------------ + * RealView control registers + * ------------------------------------------------------------------------ + */ + +/* + * REALVIEW_IDFIELD + * + * 31:24 = manufacturer (0x41 = ARM) + * 23:16 = architecture (0x08 = AHB system bus, ASB processor bus) + * 15:12 = FPGA (0x3 = XVC600 or XVC600E) + * 11:4 = build value + * 3:0 = revision number (0x1 = rev B (AHB)) + */ + +/* + * REALVIEW_SYS_LOCK + * control access to SYS_OSCx, SYS_CFGDATAx, SYS_RESETCTL, + * SYS_CLD, SYS_BOOTCS + */ +#define REALVIEW_SYS_LOCK_LOCKED (1 << 16) +#define REALVIEW_SYS_LOCKVAL 0xA05F +#define REALVIEW_SYS_LOCKVAL_MASK 0xFFFF /* write 0xA05F to enable write access */ + +/* + * REALVIEW_SYS_FLASH + */ +#define REALVIEW_FLASHPROG_FLVPPEN (1 << 0) /* Enable writing to flash */ + +/* + * REALVIEW_INTREG + * - used to acknowledge and control MMCI and UART interrupts + */ +#define REALVIEW_INTREG_WPROT 0x00 /* MMC protection status (no interrupt generated) */ +#define REALVIEW_INTREG_RI0 0x01 /* Ring indicator UART0 is asserted, */ +#define REALVIEW_INTREG_CARDIN 0x08 /* MMCI card in detect */ +/* write 1 to acknowledge and clear */ +#define REALVIEW_INTREG_RI1 0x02 /* Ring indicator UART1 is asserted, */ +#define REALVIEW_INTREG_CARDINSERT 0x03 /* Signal insertion of MMC card */ + +/* + * LED settings, bits [7:0] + */ +#define REALVIEW_SYS_LED0 (1 << 0) +#define REALVIEW_SYS_LED1 (1 << 1) +#define REALVIEW_SYS_LED2 (1 << 2) +#define REALVIEW_SYS_LED3 (1 << 3) +#define REALVIEW_SYS_LED4 (1 << 4) +#define REALVIEW_SYS_LED5 (1 << 5) +#define REALVIEW_SYS_LED6 (1 << 6) +#define REALVIEW_SYS_LED7 (1 << 7) + +#define ALL_LEDS 0xFF + +#define LED_BANK REALVIEW_SYS_LED + +/* + * Control registers + */ +#define REALVIEW_IDFIELD_OFFSET 0x0 /* RealView build information */ +#define REALVIEW_FLASHPROG_OFFSET 0x4 /* Flash devices */ +#define REALVIEW_INTREG_OFFSET 0x8 /* Interrupt control */ +#define REALVIEW_DECODE_OFFSET 0xC /* Fitted logic modules */ + +/* + * Clean base - dummy + * + */ +#define CLEAN_BASE REALVIEW_BOOT_ROM_HI + +/* + * System controller bit assignment + */ +#define REALVIEW_REFCLK 0 +#define REALVIEW_TIMCLK 1 + +#define REALVIEW_TIMER1_EnSel 15 +#define REALVIEW_TIMER2_EnSel 17 +#define REALVIEW_TIMER3_EnSel 19 +#define REALVIEW_TIMER4_EnSel 21 + +struct rt_hw_register +{ + 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; + unsigned long ORIG_r0; +}; + +#include + +/* Interrupt Control Interface */ +#define ARM_GIC_CPU_BASE 0x1E000000 + +/* number of interrupts on board */ +#define ARM_GIC_NR_IRQS 96 +/* only one GIC available */ +#define ARM_GIC_MAX_NR 1 + +#endif + diff --git a/bsp/qemu-vexpress-a9/drivers/serial.c b/bsp/qemu-vexpress-a9/drivers/serial.c new file mode 100644 index 000000000..786a26a4b --- /dev/null +++ b/bsp/qemu-vexpress-a9/drivers/serial.c @@ -0,0 +1,183 @@ +/* + * serial.c UART driver + * + * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd + * + * This file is part of RT-Thread (http://www.rt-thread.org) + * Maintainer: bernard.xiong + * + * All rights reserved. + * + * 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-03-30 Bernard the first verion + */ + +#include +#include + +#include "serial.h" + +struct hw_uart_device +{ + rt_uint32_t hw_base; + rt_uint32_t irqno; +}; + +#define UART_DR(base) __REG32(base + 0x00) +#define UART_FR(base) __REG32(base + 0x18) +#define UART_CR(base) __REG32(base + 0x30) +#define UART_IMSC(base) __REG32(base + 0x38) +#define UART_ICR(base) __REG32(base + 0x44) + +#define UARTFR_RXFE 0x10 +#define UARTFR_TXFF 0x20 +#define UARTIMSC_RXIM 0x10 +#define UARTIMSC_TXIM 0x20 +#define UARTICR_RXIC 0x10 +#define UARTICR_TXIC 0x20 + +static void rt_hw_uart_isr(int irqno, void *param) +{ + struct rt_serial_device *serial = (struct rt_serial_device *)param; + + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); +} + +static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + return RT_EOK; +} + +static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct hw_uart_device *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct hw_uart_device *)serial->parent.user_data; + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + /* disable rx irq */ + UART_IMSC(uart->hw_base) &= ~UARTIMSC_RXIM; + break; + + case RT_DEVICE_CTRL_SET_INT: + /* enable rx irq */ + UART_IMSC(uart->hw_base) |= UARTIMSC_RXIM; + rt_hw_interrupt_umask(uart->irqno); + break; + } + + return RT_EOK; +} + +static int uart_putc(struct rt_serial_device *serial, char c) +{ + struct hw_uart_device *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct hw_uart_device *)serial->parent.user_data; + + while (UART_FR(uart->hw_base) & UARTFR_TXFF); + UART_DR(uart->hw_base) = c; + + return 1; +} + +static int uart_getc(struct rt_serial_device *serial) +{ + int ch; + struct hw_uart_device *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct hw_uart_device *)serial->parent.user_data; + + ch = -1; + if (!(UART_FR(uart->hw_base) & UARTFR_RXFE)) + { + ch = UART_DR(uart->hw_base) & 0xff; + } + + return ch; +} + +static const struct rt_uart_ops _uart_ops = +{ + uart_configure, + uart_control, + uart_putc, + uart_getc, +}; + +#ifdef RT_USING_UART0 +/* UART device driver structure */ +static struct hw_uart_device _uart0_device = +{ + REALVIEW_UART0_BASE, + IRQ_PBA8_UART0, +}; +static struct rt_serial_device _serial0; +#endif + +#ifdef RT_USING_UART1 +/* UART1 device driver structure */ +static struct hw_uart_device _uart1_device = +{ + REALVIEW_UART1_BASE, + IRQ_PBA8_UART1, +}; +static struct rt_serial_device _serial1; +#endif + +int rt_hw_uart_init(void) +{ + struct hw_uart_device *uart; + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + +#ifdef RT_USING_UART0 + uart = &_uart0_device; + + _serial0.ops = &_uart_ops; + _serial0.config = config; + + /* register UART1 device */ + rt_hw_serial_register(&_serial0, "uart0", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + uart); + rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial0, "uart0"); + /* enable Rx and Tx of UART */ + UART_CR(uart->hw_base) = (1 << 0) | (1 << 8) | (1 << 9); +#endif + +#ifdef RT_USING_UART1 + uart = &_uart1_device; + _serial1.ops = &_uart_ops; + _serial1.config = config; + + /* register UART1 device */ + rt_hw_serial_register(&_serial1, "uart1", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); + /* enable Rx and Tx of UART */ + UART_CR(uart->hw_base) = (1 << 0) | (1 << 8) | (1 << 9); + rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial1, "uart1"); +#endif + + return 0; +} +INIT_BOARD_EXPORT(rt_hw_uart_init); diff --git a/bsp/qemu-vexpress-a9/drivers/serial.h b/bsp/qemu-vexpress-a9/drivers/serial.h new file mode 100644 index 000000000..52e6f07ea --- /dev/null +++ b/bsp/qemu-vexpress-a9/drivers/serial.h @@ -0,0 +1,39 @@ +/* + * UART driver + * + * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd + * + * This file is part of RT-Thread (http://www.rt-thread.org) + * Maintainer: bernard.xiong + * + * All rights reserved. + * + * 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-03-30 Bernard the first verion + */ + +#ifndef __UART_H__ +#define __UART_H__ + +#include + +int rt_hw_uart_init(void); + +#endif + + diff --git a/bsp/qemu-vexpress-a9/link.lds b/bsp/qemu-vexpress-a9/link.lds new file mode 100644 index 000000000..4a30d56a2 --- /dev/null +++ b/bsp/qemu-vexpress-a9/link.lds @@ -0,0 +1,91 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SECTIONS +{ + . = 0x60000000; + + __text_start = .; + .text : + { + *(.vectors) + *(.text) + *(.text.*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for modules */ + . = ALIGN(4); + __rtmsymtab_start = .; + KEEP(*(RTMSymTab)) + __rtmsymtab_end = .; + + /* section information for initialization */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + } =0 + __text_end = .; + + __rodata_start = .; + .rodata : { *(.rodata) *(.rodata.*) } + __rodata_end = .; + + . = ALIGN(4); + .ctors : + { + PROVIDE(__ctors_start__ = .); + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + PROVIDE(__ctors_end__ = .); + } + + .dtors : + { + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + } + + __data_start = .; + . = ALIGN(4); + .data : + { + *(.data) + *(.data.*) + } + __data_end = .; + + . = ALIGN(4); + __bss_start = __data_end; + .bss : + { + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + } + . = ALIGN(4); + __bss_end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + _end = .; +} diff --git a/bsp/qemu-vexpress-a9/qemu.bat b/bsp/qemu-vexpress-a9/qemu.bat new file mode 100644 index 000000000..33cae43db --- /dev/null +++ b/bsp/qemu-vexpress-a9/qemu.bat @@ -0,0 +1 @@ +qemu-system-arm -M vexpress-a9 -kernel rtthread.elf -serial vc -serial vc diff --git a/bsp/qemu-vexpress-a9/qemu.sh b/bsp/qemu-vexpress-a9/qemu.sh new file mode 100644 index 000000000..e9568fa26 --- /dev/null +++ b/bsp/qemu-vexpress-a9/qemu.sh @@ -0,0 +1 @@ +qemu-system-arm -M vexpress-a9 -kernel rtthread.elf -serial vc -serial vc diff --git a/bsp/qemu-vexpress-a9/rtconfig.h b/bsp/qemu-vexpress-a9/rtconfig.h new file mode 100644 index 000000000..80fa9f83c --- /dev/null +++ b/bsp/qemu-vexpress-a9/rtconfig.h @@ -0,0 +1,134 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Project Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_DEBUG +#define RT_USING_OVERFLOW_CHECK +/* RT_DEBUG_INIT is not set */ +/* RT_DEBUG_THREAD is not set */ +#define RT_USING_HOOK +/* RT_USING_TIMER_SOFT is not set */ + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_MEMHEAP +#define RT_USING_HEAP +#define RT_USING_SMALL_MEM +/* RT_USING_SLAB is not set */ + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart0" +/* RT_USING_MODULE is not set */ + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN + +/* C++ features */ + +/* RT_USING_CPLUSPLUS is not set */ + +/* Command shell */ + +#define RT_USING_FINSH +#define FINSH_USING_SYMTAB +#define FINSH_USING_DESCRIPTION +#define FINSH_THREAD_STACK_SIZE 4096 +/* FINSH_USING_AUTH is not set */ +#define FINSH_DEFAULT_PASSWORD "rtthread" +#define FINSH_USING_MSH +#define FINSH_USING_MSH_DEFAULT +/* FINSH_USING_MSH_ONLY is not set */ + +/* Device virtual file system */ + +#define RT_USING_DFS +#define DFS_USING_WORKDIR +#define DFS_FILESYSTEMS_MAX 2 +#define DFS_FD_MAX 4 +#define RT_USING_DFS_ELMFAT +#define RT_DFS_ELM_CODE_PAGE 437 +#define RT_DFS_ELM_MAX_LFN 256 +#define RT_DFS_ELM_DRIVES 2 +#define RT_DFS_ELM_MAX_SECTOR_SIZE 512 +/* RT_DFS_ELM_USE_ERASE is not set */ +#define RT_DFS_ELM_REENTRANT +#define RT_USING_DFS_DEVFS +/* RT_USING_DFS_NET is not set */ +/* RT_USING_DFS_NFS is not set */ + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_USING_SERIAL +/* RT_USING_CAN is not set */ +/* RT_USING_HWTIMER is not set */ +/* RT_USING_I2C is not set */ +#define RT_USING_PIN +/* RT_USING_MTD_NOR is not set */ +/* RT_USING_MTD_NAND is not set */ +/* RT_USING_RTC is not set */ +/* RT_USING_SDIO is not set */ +/* RT_USING_SPI is not set */ +/* RT_USING_WDT is not set */ +/* RT_USING_USB_HOST is not set */ +/* RT_USING_USB_DEVICE is not set */ + +/* libc */ + +#define RT_USING_LIBC +#define RT_USING_PTHREADS + +/* Network stack */ + +/* light weight TCP/IP stack */ + +/* RT_USING_LWIP is not set */ + +/* Modbus master and slave stack */ + +/* RT_USING_MODBUS is not set */ + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + +/* language packages */ + +/* miscellaneous packages */ + +#define PKG_USING_HELLO + +/* multimedia packages */ + +/* security packages */ + +/* system packages */ + +/* PKG_USING_CMBACKTRACE is not set */ +#define RT_USING_UART0 +#define RT_USING_UART1 + +#endif diff --git a/bsp/qemu-vexpress-a9/rtconfig.py b/bsp/qemu-vexpress-a9/rtconfig.py new file mode 100644 index 000000000..d11f0aa43 --- /dev/null +++ b/bsp/qemu-vexpress-a9/rtconfig.py @@ -0,0 +1,103 @@ +import os + +# toolchains options +ARCH='arm' +CPU='vexpress-a9' +CROSS_TOOL='gcc' + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') + +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = '/opt/gcc-arm-none-eabi-4_8-2014q1_gri/bin' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = 'C:/Keil' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + CXX = PREFIX + 'g++' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -march=armv7-a -marm -msoft-float' + CFLAGS = DEVICE + ' -Wall' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__' + LINK_SCRIPT = 'link.lds' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors'+\ + ' -T %s' % LINK_SCRIPT + + CPATH = '' + LPATH = '' + + # generate debug info in all cases + AFLAGS += ' -gdwarf-2' + CFLAGS += ' -g -gdwarf-2' + + if BUILD == 'debug': + CFLAGS += ' -O0' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' +\ + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --device DARMP' + CFLAGS = DEVICE + ' --apcs=interwork' + AFLAGS = DEVICE + LFLAGS = DEVICE + ' --info sizes --info totals --info unused --info veneers --list rtthread.map --scatter rtthread.sct' + + CFLAGS += ' -I' + EXEC_PATH + '/ARM/RV31/INC' + LFLAGS += ' --libpath ' + EXEC_PATH + '/ARM/RV31/LIB' + + EXEC_PATH += '/arm/bin40/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = ' --cpu DARMP' + + CFLAGS = '' + AFLAGS = '' + LFLAGS = ' --config rtthread.icf' + + EXEC_PATH += '/arm/bin/' + RT_USING_MINILIBC = False + POST_ACTION = ''