├── .gitignore ├── README.md ├── boot ├── .gitignore ├── SConscript ├── SConstruct ├── applications │ ├── SConscript │ ├── application.c │ └── startup.c ├── build.sh ├── cpu │ ├── SConscript │ ├── armv7.h │ ├── context_gcc.S │ ├── cp15.h │ ├── cp15_gcc.S │ ├── cpu.c │ ├── gic.c │ ├── gic.h │ ├── interrupt.c │ ├── interrupt.h │ ├── mmu.c │ ├── pmu.c │ ├── pmu.h │ ├── stack.c │ ├── start_gcc.S │ ├── trap.c │ └── vector_gcc.S ├── drivers │ ├── SConscript │ ├── board.c │ ├── board.h │ ├── realview.h │ ├── serial.c │ └── serial.h ├── rtconfig.h ├── rtconfig.py └── vexpress.lds ├── build.sh ├── buildroot_config ├── dn_prepare.sh ├── env.sh ├── gemini.sh ├── linux-apps ├── Makefile └── vecho.c ├── prepare.sh ├── rtloader ├── .gitignore ├── Makefile ├── build.sh ├── loader.c ├── vbus │ ├── Makefile.in │ ├── gic_emuint.c │ ├── linux_driver.c │ ├── linux_driver.h │ ├── prio_queue.c │ ├── prio_queue.h │ ├── rt_vbus_user.h │ ├── vbus_chn0.c │ ├── vbus_chnx.c │ ├── vbus_chnx.h │ ├── watermark_queue.c │ └── watermark_queue.h ├── vbus_conf.h └── vbus_layout.h ├── rtthread_vbus.patch └── vexpress ├── .gitignore ├── SConscript ├── SConstruct ├── applications ├── SConscript ├── application.c ├── startup.c └── vbus_echo.c ├── build.sh ├── cpu ├── SConscript ├── armv7.h ├── context_gcc.S ├── cp15.h ├── cp15_gcc.S ├── cpu.c ├── gic.c ├── gic.h ├── interrupt.c ├── interrupt.h ├── mmu.c ├── pmu.c ├── pmu.h ├── stack.c ├── start_gcc.S ├── trap.c └── vector_gcc.S ├── drivers ├── SConscript ├── board.c ├── board.h ├── realview.h ├── serial.c ├── serial.h ├── vbus_conf.h ├── vbus_drv.c ├── vbus_hw.h └── vbus_local_conf.h ├── qemu.sh ├── rtconfig.h ├── rtconfig.py └── vexpress.lds /.gitignore: -------------------------------------------------------------------------------- 1 | rt-thread 2 | linux-3.18.16* 3 | gcc-linaro-4.9-2014.11* 4 | buildroot* 5 | arm-2012.09* 6 | build 7 | *.o 8 | *~ 9 | *.elf 10 | *.map 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gemini 2 | The Gemini system of RT-Thread/Linux on Dual CPU core. 3 | 4 | ## Build 5 | 6 | Please fork this git repo in your coding.net. Then enter your WebIDE, which is a 7 | Ubuntu VM. Please prepare the building environment in your Ubuntu VM first time: 8 | 9 | sh ./prepare.sh 10 | 11 | This prepare.sh script will download RT-Thread code, toolchain and Linux kernel 12 | code etc.. 13 | 14 | Then you can use following command to build Gemini system: 15 | 16 | source ./env.sh 17 | sh ./build.sh 18 | 19 | ## Run it on QEMU 20 | 21 | TODO. 22 | -------------------------------------------------------------------------------- /boot/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | rt-thread 3 | *.pyc 4 | *.o 5 | *~ 6 | *.map 7 | *.bin 8 | .sconsign.dblite 9 | 10 | -------------------------------------------------------------------------------- /boot/SConscript: -------------------------------------------------------------------------------- 1 | # for module compiling 2 | import os 3 | Import('RTT_ROOT') 4 | 5 | cwd = str(Dir('#')) 6 | objs = [] 7 | list = os.listdir(cwd) 8 | 9 | for d in list: 10 | path = os.path.join(cwd, d) 11 | if os.path.isfile(os.path.join(path, 'SConscript')): 12 | objs = objs + SConscript(os.path.join(d, 'SConscript')) 13 | 14 | Return('objs') 15 | -------------------------------------------------------------------------------- /boot/SConstruct: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import rtconfig 4 | 5 | if os.getenv('RTT_ROOT'): 6 | RTT_ROOT = os.getenv('RTT_ROOT') 7 | else: 8 | RTT_ROOT = os.path.normpath(os.getcwd() + '/rt-thread') 9 | 10 | sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] 11 | from building import * 12 | 13 | TARGET = 'rtthread-boot.' + rtconfig.TARGET_EXT 14 | 15 | env = Environment(tools = ['mingw'], 16 | AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, 17 | CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, 18 | AR = rtconfig.AR, ARFLAGS = '-rc', 19 | LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) 20 | env.PrependENVPath('PATH', rtconfig.EXEC_PATH) 21 | 22 | Export('RTT_ROOT') 23 | Export('rtconfig') 24 | 25 | # prepare building environment 26 | objs = PrepareBuilding(env, RTT_ROOT,has_libcpu=True) 27 | 28 | # make a building 29 | DoBuilding(TARGET, objs) 30 | -------------------------------------------------------------------------------- /boot/applications/SConscript: -------------------------------------------------------------------------------- 1 | Import('RTT_ROOT') 2 | Import('rtconfig') 3 | from building import * 4 | 5 | cwd = os.path.join(str(Dir('#')), 'applications') 6 | src = Glob('*.c') 7 | CPPPATH = [cwd, str(Dir('#'))] 8 | 9 | group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) 10 | 11 | Return('group') 12 | -------------------------------------------------------------------------------- /boot/applications/application.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : application.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2012, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2012-11-20 Bernard the first version 13 | */ 14 | 15 | #include 16 | 17 | int rt_application_init() 18 | { 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /boot/applications/startup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : startup.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2006, RT-Thread Develop Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2012-12-05 Bernard the first version 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | extern void rt_hw_board_init(void); 21 | 22 | #define RTT_BASE_ADDR 0x6fc00000 23 | typedef void (*func_t)(void); 24 | 25 | /** 26 | * This function will startup RT-Thread RTOS. 27 | */ 28 | void rtthread_startup(void) 29 | { 30 | func_t func; 31 | 32 | /* initialize board */ 33 | rt_hw_board_init(); 34 | 35 | func = (func_t)RTT_BASE_ADDR; 36 | func(); 37 | 38 | /* never reach here */ 39 | return ; 40 | } 41 | 42 | int main(void) 43 | { 44 | /* disable interrupt first */ 45 | rt_hw_interrupt_disable(); 46 | 47 | /* invoke rtthread_startup */ 48 | rtthread_startup(); 49 | 50 | return 0; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /boot/build.sh: -------------------------------------------------------------------------------- 1 | scons 2 | cp boot.bin $MO_DIR 3 | -------------------------------------------------------------------------------- /boot/cpu/SConscript: -------------------------------------------------------------------------------- 1 | Import('rtconfig') 2 | from building import * 3 | 4 | cwd = GetCurrentDir() 5 | src = Glob('*.c') 6 | CPPPATH = [cwd] 7 | 8 | if rtconfig.PLATFORM == 'iar': 9 | src += Glob('*_iar.S') 10 | elif rtconfig.PLATFORM == 'gcc': 11 | src += Glob('*_gcc.S') 12 | elif rtconfig.PLATFORM == 'armcc': 13 | src += Glob('*_rvds.S') 14 | 15 | group = DefineGroup('AM335x', src, depend = [''], CPPPATH = CPPPATH) 16 | 17 | Return('group') 18 | -------------------------------------------------------------------------------- /boot/cpu/armv7.h: -------------------------------------------------------------------------------- 1 | #ifndef __ARMV7_H__ 2 | #define __ARMV7_H__ 3 | 4 | /* the exception stack without VFP registers */ 5 | struct rt_hw_exp_stack 6 | { 7 | unsigned long r0; 8 | unsigned long r1; 9 | unsigned long r2; 10 | unsigned long r3; 11 | unsigned long r4; 12 | unsigned long r5; 13 | unsigned long r6; 14 | unsigned long r7; 15 | unsigned long r8; 16 | unsigned long r9; 17 | unsigned long r10; 18 | unsigned long fp; 19 | unsigned long ip; 20 | unsigned long sp; 21 | unsigned long lr; 22 | unsigned long pc; 23 | unsigned long cpsr; 24 | }; 25 | 26 | struct rt_hw_stack 27 | { 28 | unsigned long cpsr; 29 | unsigned long r0; 30 | unsigned long r1; 31 | unsigned long r2; 32 | unsigned long r3; 33 | unsigned long r4; 34 | unsigned long r5; 35 | unsigned long r6; 36 | unsigned long r7; 37 | unsigned long r8; 38 | unsigned long r9; 39 | unsigned long r10; 40 | unsigned long fp; 41 | unsigned long ip; 42 | unsigned long lr; 43 | unsigned long pc; 44 | }; 45 | 46 | #define USERMODE 0x10 47 | #define FIQMODE 0x11 48 | #define IRQMODE 0x12 49 | #define SVCMODE 0x13 50 | #define MONITORMODE 0x16 51 | #define ABORTMODE 0x17 52 | #define HYPMODE 0x1b 53 | #define UNDEFMODE 0x1b 54 | #define MODEMASK 0x1f 55 | #define NOINT 0xc0 56 | 57 | #define T_Bit (1<<5) 58 | #define F_Bit (1<<6) 59 | #define I_Bit (1<<7) 60 | #define A_Bit (1<<8) 61 | #define E_Bit (1<<9) 62 | #define J_Bit (1<<24) 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /boot/cpu/context_gcc.S: -------------------------------------------------------------------------------- 1 | /* 2 | * File : context.S 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Development Team 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Change Logs: 21 | * Date Author Notes 22 | * 2013-07-05 Bernard the first version 23 | */ 24 | 25 | .section .text, "ax" 26 | /* 27 | * rt_base_t rt_hw_interrupt_disable(); 28 | */ 29 | .globl rt_hw_interrupt_disable 30 | rt_hw_interrupt_disable: 31 | mrs r0, cpsr 32 | cpsid i 33 | bx lr 34 | 35 | /* 36 | * void rt_hw_interrupt_enable(rt_base_t level); 37 | */ 38 | .globl rt_hw_interrupt_enable 39 | rt_hw_interrupt_enable: 40 | msr cpsr, r0 41 | bx lr 42 | 43 | /* 44 | * void rt_hw_context_switch_to(rt_uint32 to); 45 | * r0 --> to 46 | */ 47 | .globl rt_hw_context_switch_to 48 | rt_hw_context_switch_to: 49 | ldr sp, [r0] @ get new task stack pointer 50 | 51 | ldmfd sp!, {r4} @ pop new task spsr 52 | msr spsr_cxsf, r4 53 | 54 | ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc 55 | 56 | .section .bss.share.isr 57 | _guest_switch_lvl: 58 | .word 0 59 | 60 | .globl vmm_virq_update 61 | 62 | .section .text.isr, "ax" 63 | /* 64 | * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); 65 | * r0 --> from 66 | * r1 --> to 67 | */ 68 | .globl rt_hw_context_switch 69 | rt_hw_context_switch: 70 | stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) 71 | stmfd sp!, {r0-r12, lr} @ push lr & register file 72 | 73 | mrs r4, cpsr 74 | tst lr, #0x01 75 | orrne r4, r4, #0x20 @ it's thumb code 76 | 77 | stmfd sp!, {r4} @ push cpsr 78 | 79 | str sp, [r0] @ store sp in preempted tasks TCB 80 | ldr sp, [r1] @ get new task stack pointer 81 | 82 | ldmfd sp!, {r4} @ pop new task cpsr to spsr 83 | msr spsr_cxsf, r4 84 | ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr 85 | 86 | /* 87 | * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); 88 | */ 89 | .globl rt_thread_switch_interrupt_flag 90 | .globl rt_interrupt_from_thread 91 | .globl rt_interrupt_to_thread 92 | .globl rt_hw_context_switch_interrupt 93 | rt_hw_context_switch_interrupt: 94 | ldr r2, =rt_thread_switch_interrupt_flag 95 | ldr r3, [r2] 96 | cmp r3, #1 97 | beq _reswitch 98 | ldr ip, =rt_interrupt_from_thread @ set rt_interrupt_from_thread 99 | mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 100 | str r0, [ip] 101 | str r3, [r2] 102 | _reswitch: 103 | ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread 104 | str r1, [r2] 105 | bx lr 106 | -------------------------------------------------------------------------------- /boot/cpu/cp15.h: -------------------------------------------------------------------------------- 1 | #ifndef __CP15_H__ 2 | #define __CP15_H__ 3 | 4 | unsigned long rt_cpu_get_smp_id(void); 5 | 6 | void rt_cpu_mmu_disable(void); 7 | void rt_cpu_mmu_enable(void); 8 | void rt_cpu_tlb_set(volatile unsigned long*); 9 | 10 | void rt_cpu_vector_set_base(unsigned int addr); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /boot/cpu/cp15_gcc.S: -------------------------------------------------------------------------------- 1 | /* 2 | * File : cp15_gcc.S 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Development Team 5 | * http://www.rt-thread.org 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Change Logs: 22 | * Date Author Notes 23 | * 2013-07-05 Bernard the first version 24 | */ 25 | 26 | .globl rt_cpu_get_smp_id 27 | rt_cpu_get_smp_id: 28 | mrc p15, #0, r0, c0, c0, #5 29 | bx lr 30 | 31 | .globl rt_cpu_vector_set_base 32 | rt_cpu_vector_set_base: 33 | mcr p15, #0, r0, c12, c0, #0 34 | dsb 35 | bx lr 36 | 37 | .globl rt_hw_cpu_dcache_enable 38 | rt_hw_cpu_dcache_enable: 39 | mrc p15, #0, r0, c1, c0, #0 40 | orr r0, r0, #0x00000004 41 | mcr p15, #0, r0, c1, c0, #0 42 | bx lr 43 | 44 | .globl rt_hw_cpu_icache_enable 45 | rt_hw_cpu_icache_enable: 46 | mrc p15, #0, r0, c1, c0, #0 47 | orr r0, r0, #0x00001000 48 | mcr p15, #0, r0, c1, c0, #0 49 | bx lr 50 | 51 | _FLD_MAX_WAY: 52 | .word 0x3ff 53 | _FLD_MAX_IDX: 54 | .word 0x7ff 55 | 56 | .globl rt_cpu_dcache_clean_flush 57 | rt_cpu_dcache_clean_flush: 58 | push {r4-r11} 59 | dmb 60 | mrc p15, #1, r0, c0, c0, #1 @ read clid register 61 | ands r3, r0, #0x7000000 @ get level of coherency 62 | mov r3, r3, lsr #23 63 | beq finished 64 | mov r10, #0 65 | loop1: 66 | add r2, r10, r10, lsr #1 67 | mov r1, r0, lsr r2 68 | and r1, r1, #7 69 | cmp r1, #2 70 | blt skip 71 | mcr p15, #2, r10, c0, c0, #0 72 | isb 73 | mrc p15, #1, r1, c0, c0, #0 74 | and r2, r1, #7 75 | add r2, r2, #4 76 | ldr r4, _FLD_MAX_WAY 77 | ands r4, r4, r1, lsr #3 78 | clz r5, r4 79 | ldr r7, _FLD_MAX_IDX 80 | ands r7, r7, r1, lsr #13 81 | loop2: 82 | mov r9, r4 83 | loop3: 84 | orr r11, r10, r9, lsl r5 85 | orr r11, r11, r7, lsl r2 86 | mcr p15, #0, r11, c7, c14, #2 87 | subs r9, r9, #1 88 | bge loop3 89 | subs r7, r7, #1 90 | bge loop2 91 | skip: 92 | add r10, r10, #2 93 | cmp r3, r10 94 | bgt loop1 95 | 96 | finished: 97 | dsb 98 | isb 99 | pop {r4-r11} 100 | bx lr 101 | 102 | .globl rt_hw_cpu_dcache_disable 103 | rt_hw_cpu_dcache_disable: 104 | push {r4-r11, lr} 105 | bl rt_cpu_dcache_clean_flush 106 | mrc p15, #0, r0, c1, c0, #0 107 | bic r0, r0, #0x00000004 108 | mcr p15, #0, r0, c1, c0, #0 109 | pop {r4-r11, lr} 110 | bx lr 111 | 112 | .globl rt_hw_cpu_icache_disable 113 | rt_hw_cpu_icache_disable: 114 | mrc p15, #0, r0, c1, c0, #0 115 | bic r0, r0, #0x00001000 116 | mcr p15, #0, r0, c1, c0, #0 117 | bx lr 118 | 119 | .globl rt_cpu_mmu_disable 120 | rt_cpu_mmu_disable: 121 | mcr p15, #0, r0, c8, c7, #0 @ invalidate tlb 122 | mrc p15, #0, r0, c1, c0, #0 123 | bic r0, r0, #1 124 | mcr p15, #0, r0, c1, c0, #0 @ clear mmu bit 125 | dsb 126 | bx lr 127 | 128 | .globl rt_cpu_mmu_enable 129 | rt_cpu_mmu_enable: 130 | mrc p15, #0, r0, c1, c0, #0 131 | orr r0, r0, #0x001 132 | mcr p15, #0, r0, c1, c0, #0 @ set mmu enable bit 133 | dsb 134 | bx lr 135 | 136 | .globl rt_cpu_tlb_set 137 | rt_cpu_tlb_set: 138 | mcr p15, #0, r0, c2, c0, #0 139 | dmb 140 | bx lr 141 | 142 | .globl rt_cpu_tlb_get 143 | rt_cpu_tlb_get: 144 | mrc p15, #0, r0, c2, c0, #0 145 | bx lr 146 | -------------------------------------------------------------------------------- /boot/cpu/cpu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : cpu.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2006, RT-Thread Develop Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2011-09-15 Bernard first version 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | /** 20 | * @addtogroup AM33xx 21 | */ 22 | /*@{*/ 23 | 24 | /** shutdown CPU */ 25 | void rt_hw_cpu_shutdown() 26 | { 27 | rt_uint32_t level; 28 | rt_kprintf("shutdown...\n"); 29 | 30 | level = rt_hw_interrupt_disable(); 31 | while (level) 32 | { 33 | RT_ASSERT(0); 34 | } 35 | } 36 | 37 | /*@}*/ 38 | -------------------------------------------------------------------------------- /boot/cpu/gic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File : gic.h, ARM Generic Interrupt Controller 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Develop Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2013-07-20 Bernard first version 13 | */ 14 | 15 | #ifndef __GIC_H__ 16 | #define __GIC_H__ 17 | 18 | int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start); 19 | int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base); 20 | 21 | void arm_gic_mask(rt_uint32_t index, int irq); 22 | void arm_gic_umask(rt_uint32_t index, int irq); 23 | void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask); 24 | void arm_gic_set_group(rt_uint32_t index, int vector, int group); 25 | 26 | int arm_gic_get_active_irq(rt_uint32_t index); 27 | void arm_gic_ack(rt_uint32_t index, int irq); 28 | 29 | void arm_gic_trigger(rt_uint32_t index, int target_cpu, int irq); 30 | void arm_gic_clear_sgi(rt_uint32_t index, int target_cpu, int irq); 31 | 32 | void arm_gic_dump_type(rt_uint32_t index); 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /boot/cpu/interrupt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : interrupt.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013-2014, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2013-07-06 Bernard first version 13 | * 2014-04-03 Grissiom port to VMM 14 | */ 15 | 16 | #include 17 | #include 18 | #include "realview.h" 19 | #include "gic.h" 20 | 21 | #ifdef RT_USING_VMM 22 | #include 23 | #endif 24 | 25 | #define MAX_HANDLERS NR_IRQS_PBA8 26 | 27 | extern volatile rt_uint8_t rt_interrupt_nest; 28 | 29 | /* exception and interrupt handler table */ 30 | struct rt_irq_desc isr_table[MAX_HANDLERS]; 31 | 32 | rt_uint32_t rt_interrupt_from_thread; 33 | rt_uint32_t rt_interrupt_to_thread; 34 | rt_uint32_t rt_thread_switch_interrupt_flag; 35 | 36 | extern void rt_cpu_vector_set_base(unsigned int addr); 37 | extern int system_vectors; 38 | 39 | static void rt_hw_vector_init(void) 40 | { 41 | rt_cpu_vector_set_base((unsigned int)&system_vectors); 42 | } 43 | 44 | /** 45 | * This function will initialize hardware interrupt 46 | */ 47 | void rt_hw_interrupt_init(void) 48 | { 49 | rt_uint32_t gic_cpu_base; 50 | rt_uint32_t gic_dist_base; 51 | 52 | /* initialize vector table */ 53 | rt_hw_vector_init(); 54 | 55 | /* initialize exceptions table */ 56 | rt_memset(isr_table, 0x00, sizeof(isr_table)); 57 | 58 | /* initialize ARM GIC */ 59 | gic_dist_base = REALVIEW_GIC_DIST_BASE; 60 | gic_cpu_base = REALVIEW_GIC_CPU_BASE; 61 | arm_gic_dist_init(0, gic_dist_base, 0); 62 | arm_gic_cpu_init(0, gic_cpu_base); 63 | /*arm_gic_dump_type(0);*/ 64 | 65 | /* init interrupt nest, and context in thread sp */ 66 | rt_interrupt_nest = 0; 67 | rt_interrupt_from_thread = 0; 68 | rt_interrupt_to_thread = 0; 69 | rt_thread_switch_interrupt_flag = 0; 70 | } 71 | 72 | /** 73 | * This function will mask a interrupt. 74 | * @param vector the interrupt number 75 | */ 76 | void rt_hw_interrupt_mask(int vector) 77 | { 78 | arm_gic_mask(0, vector); 79 | } 80 | 81 | /** 82 | * This function will un-mask a interrupt. 83 | * @param vector the interrupt number 84 | */ 85 | void rt_hw_interrupt_umask(int vector) 86 | { 87 | arm_gic_umask(0, vector); 88 | } 89 | 90 | /** 91 | * This function will install a interrupt service routine to a interrupt. 92 | * @param vector the interrupt number 93 | * @param new_handler the interrupt service routine to be installed 94 | * @param old_handler the old interrupt service routine 95 | */ 96 | rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, 97 | void *param, char *name) 98 | { 99 | rt_isr_handler_t old_handler = RT_NULL; 100 | 101 | if (vector < MAX_HANDLERS) 102 | { 103 | old_handler = isr_table[vector].handler; 104 | 105 | if (handler != RT_NULL) 106 | { 107 | #ifdef RT_USING_INTERRUPT_INFO 108 | rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX); 109 | #endif /* RT_USING_INTERRUPT_INFO */ 110 | isr_table[vector].handler = handler; 111 | isr_table[vector].param = param; 112 | } 113 | } 114 | 115 | return old_handler; 116 | } 117 | 118 | /** 119 | * Trigger a software IRQ 120 | * 121 | * Since we are running in single core, the target CPU are always CPU0. 122 | */ 123 | void rt_hw_interrupt_trigger(int vector) 124 | { 125 | arm_gic_trigger(0, 1, vector); 126 | } 127 | 128 | void rt_hw_interrupt_clear(int vector) 129 | { 130 | arm_gic_clear_sgi(0, 1, vector); 131 | } 132 | -------------------------------------------------------------------------------- /boot/cpu/interrupt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File : interrupt.h 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2011, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2013-07-06 Bernard first version 13 | */ 14 | 15 | #ifndef __INTERRUPT_H__ 16 | #define __INTERRUPT_H__ 17 | 18 | #define INT_IRQ 0x00 19 | #define INT_FIQ 0x01 20 | 21 | #define INTC_REVISION(hw_base) REG32((hw_base) + 0x0) 22 | #define INTC_SYSCONFIG(hw_base) REG32((hw_base) + 0x10) 23 | #define INTC_SYSSTATUS(hw_base) REG32((hw_base) + 0x14) 24 | #define INTC_SIR_IRQ(hw_base) REG32((hw_base) + 0x40) 25 | #define INTC_SIR_FIQ(hw_base) REG32((hw_base) + 0x44) 26 | #define INTC_CONTROL(hw_base) REG32((hw_base) + 0x48) 27 | #define INTC_PROTECTION(hw_base) REG32((hw_base) + 0x4c) 28 | #define INTC_IDLE(hw_base) REG32((hw_base) + 0x50) 29 | #define INTC_IRQ_PRIORITY(hw_base) REG32((hw_base) + 0x60) 30 | #define INTC_FIQ_PRIORITY(hw_base) REG32((hw_base) + 0x64) 31 | #define INTC_THRESHOLD(hw_base) REG32((hw_base) + 0x68) 32 | #define INTC_SICR(hw_base) REG32((hw_base) + 0x6c) 33 | #define INTC_SCR(hw_base, n) REG32((hw_base) + 0x70 + ((n) * 0x04)) 34 | #define INTC_ITR(hw_base, n) REG32((hw_base) + 0x80 + ((n) * 0x20)) 35 | #define INTC_MIR(hw_base, n) REG32((hw_base) + 0x84 + ((n) * 0x20)) 36 | #define INTC_MIR_CLEAR(hw_base, n) REG32((hw_base) + 0x88 + ((n) * 0x20)) 37 | #define INTC_MIR_SET(hw_base, n) REG32((hw_base) + 0x8c + ((n) * 0x20)) 38 | #define INTC_ISR_SET(hw_base, n) REG32((hw_base) + 0x90 + ((n) * 0x20)) 39 | #define INTC_ISR_CLEAR(hw_base, n) REG32((hw_base) + 0x94 + ((n) * 0x20)) 40 | #define INTC_PENDING_IRQ(hw_base, n) REG32((hw_base) + 0x98 + ((n) * 0x20)) 41 | #define INTC_PENDING_FIQ(hw_base, n) REG32((hw_base) + 0x9c + ((n) * 0x20)) 42 | #define INTC_ILR(hw_base, n) REG32((hw_base) + 0x100 + ((n) * 0x04)) 43 | 44 | void rt_hw_interrupt_control(int vector, int priority, int route); 45 | int rt_hw_interrupt_get_active(int fiq_irq); 46 | void rt_hw_interrupt_ack(int fiq_irq); 47 | void rt_hw_interrupt_trigger(int vector); 48 | void rt_hw_interrupt_clear(int vector); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /boot/cpu/mmu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : mmu.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2006, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2012-01-10 bernard porting to AM1808 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "cp15.h" 20 | 21 | #define DESC_SEC (0x2) 22 | #define CB (3<<2) //cache_on, write_back 23 | #define CNB (2<<2) //cache_on, write_through 24 | #define NCB (1<<2) //cache_off,WR_BUF on 25 | #define NCNB (0<<2) //cache_off,WR_BUF off 26 | #define AP_RW (3<<10) //supervisor=RW, user=RW 27 | #define AP_RO (2<<10) //supervisor=RW, user=RO 28 | #define XN (1<<4) // eXecute Never 29 | 30 | #define DOMAIN_FAULT (0x0) 31 | #define DOMAIN_CHK (0x1) 32 | #define DOMAIN_NOTCHK (0x3) 33 | #define DOMAIN0 (0x0<<5) 34 | #define DOMAIN1 (0x1<<5) 35 | 36 | #define DOMAIN0_ATTR (DOMAIN_CHK<<0) 37 | #define DOMAIN1_ATTR (DOMAIN_FAULT<<2) 38 | 39 | /* Read/Write, cache, write back */ 40 | #define RW_CB (AP_RW|DOMAIN0|CB|DESC_SEC) 41 | /* Read/Write, cache, write through */ 42 | #define RW_CNB (AP_RW|DOMAIN0|CNB|DESC_SEC) 43 | /* Read/Write without cache and write buffer */ 44 | #define RW_NCNB (AP_RW|DOMAIN0|NCNB|DESC_SEC) 45 | /* Read/Write without cache and write buffer, no execute */ 46 | #define RW_NCNBXN (AP_RW|DOMAIN0|NCNB|DESC_SEC|XN) 47 | /* Read/Write without cache and write buffer */ 48 | #define RW_FAULT (AP_RW|DOMAIN1|NCNB|DESC_SEC) 49 | 50 | /* dump 2nd level page table */ 51 | void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb) 52 | { 53 | int i; 54 | int fcnt = 0; 55 | 56 | for (i = 0; i < 256; i++) 57 | { 58 | rt_uint32_t pte2 = ptb[i]; 59 | if ((pte2 & 0x3) == 0) 60 | { 61 | if (fcnt == 0) 62 | rt_kprintf(" "); 63 | rt_kprintf("%04x: ", i); 64 | fcnt++; 65 | if (fcnt == 16) 66 | { 67 | rt_kprintf("fault\n"); 68 | fcnt = 0; 69 | } 70 | continue; 71 | } 72 | if (fcnt != 0) 73 | { 74 | rt_kprintf("fault\n"); 75 | fcnt = 0; 76 | } 77 | 78 | rt_kprintf(" %04x: %x: ", i, pte2); 79 | if ((pte2 & 0x3) == 0x1) 80 | { 81 | rt_kprintf("L,ap:%x,xn:%d,texcb:%02x\n", 82 | ((pte2 >> 7) | (pte2 >> 4))& 0xf, 83 | (pte2 >> 15) & 0x1, 84 | ((pte2 >> 10) | (pte2 >> 2)) & 0x1f); 85 | } 86 | else 87 | { 88 | rt_kprintf("S,ap:%x,xn:%d,texcb:%02x\n", 89 | ((pte2 >> 7) | (pte2 >> 4))& 0xf, pte2 & 0x1, 90 | ((pte2 >> 4) | (pte2 >> 2)) & 0x1f); 91 | } 92 | } 93 | } 94 | 95 | void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb) 96 | { 97 | int i; 98 | int fcnt = 0; 99 | 100 | rt_kprintf("page table@%p\n", ptb); 101 | for (i = 0; i < 1024*4; i++) 102 | { 103 | rt_uint32_t pte1 = ptb[i]; 104 | if ((pte1 & 0x3) == 0) 105 | { 106 | rt_kprintf("%03x: ", i); 107 | fcnt++; 108 | if (fcnt == 16) 109 | { 110 | rt_kprintf("fault\n"); 111 | fcnt = 0; 112 | } 113 | continue; 114 | } 115 | if (fcnt != 0) 116 | { 117 | rt_kprintf("fault\n"); 118 | fcnt = 0; 119 | } 120 | 121 | rt_kprintf("%03x: %08x: ", i, pte1); 122 | if ((pte1 & 0x3) == 0x3) 123 | { 124 | rt_kprintf("LPAE\n"); 125 | } 126 | else if ((pte1 & 0x3) == 0x1) 127 | { 128 | rt_kprintf("pte,ns:%d,domain:%d\n", 129 | (pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf); 130 | /* 131 | *rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000) 132 | * - 0x80000000 + 0xC0000000)); 133 | */ 134 | } 135 | else if (pte1 & (1 << 18)) 136 | { 137 | rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n", 138 | (pte1 >> 19) & 0x1, 139 | ((pte1 >> 13) | (pte1 >> 10))& 0xf, 140 | (pte1 >> 4) & 0x1, 141 | ((pte1 >> 10) | (pte1 >> 2)) & 0x1f); 142 | } 143 | else 144 | { 145 | rt_kprintf("section,ns:%d,ap:%x," 146 | "xn:%d,texcb:%02x,domain:%d\n", 147 | (pte1 >> 19) & 0x1, 148 | ((pte1 >> 13) | (pte1 >> 10))& 0xf, 149 | (pte1 >> 4) & 0x1, 150 | (((pte1 & (0x7 << 12)) >> 10) | 151 | ((pte1 & 0x0c) >> 2)) & 0x1f, 152 | (pte1 >> 5) & 0xf); 153 | } 154 | } 155 | } 156 | 157 | /* level1 page table, each entry for 1MB memory. */ 158 | volatile static unsigned long MMUTable[4*1024] __attribute__((aligned(16*1024))); 159 | void rt_hw_mmu_setmtt(rt_uint32_t vaddrStart, 160 | rt_uint32_t vaddrEnd, 161 | rt_uint32_t paddrStart, 162 | rt_uint32_t attr) 163 | { 164 | volatile rt_uint32_t *pTT; 165 | volatile int i, nSec; 166 | pTT = (rt_uint32_t *)MMUTable + (vaddrStart >> 20); 167 | nSec = (vaddrEnd >> 20) - (vaddrStart >> 20); 168 | for(i = 0; i <= nSec; i++) 169 | { 170 | *pTT = attr | (((paddrStart >> 20) + i) << 20); 171 | pTT++; 172 | } 173 | } 174 | 175 | unsigned long rt_hw_set_domain_register(unsigned long domain_val) 176 | { 177 | unsigned long old_domain; 178 | 179 | asm volatile ("mrc p15, 0, %0, c3, c0\n" : "=r" (old_domain)); 180 | asm volatile ("mcr p15, 0, %0, c3, c0\n" : :"r" (domain_val) : "memory"); 181 | 182 | return old_domain; 183 | } 184 | 185 | void rt_hw_mmu_init(void) 186 | { 187 | rt_hw_cpu_dcache_disable(); 188 | rt_hw_cpu_icache_disable(); 189 | // rt_cpu_mmu_disable(); 190 | 191 | /* set page table */ 192 | /* 4G 1:1 memory */ 193 | rt_hw_mmu_setmtt(0x8fB00000, 0x90000000-1, 0x6fB00000, RW_CB); 194 | rt_hw_mmu_setmtt(0x6fC00000, 0x70000000-1, 0x6fC00000, RW_CB); 195 | 196 | rt_hw_set_domain_register(0x55555555); 197 | rt_cpu_tlb_set((unsigned long *)((unsigned int)MMUTable - (0x8fB00000 - 0x6fB00000))); 198 | 199 | // rt_cpu_mmu_enable(); 200 | 201 | // rt_hw_cpu_icache_enable(); 202 | // rt_hw_cpu_dcache_enable(); 203 | } 204 | -------------------------------------------------------------------------------- /boot/cpu/pmu.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pmu.h" 3 | 4 | void rt_hw_pmu_dump_feature(void) 5 | { 6 | unsigned long reg; 7 | 8 | reg = rt_hw_pmu_get_control(); 9 | rt_kprintf("ARM PMU Implementor: %c, ID code: %02x, %d counters\n", 10 | reg >> 24, (reg >> 16) & 0xff, (reg >> 11) & 0x1f); 11 | RT_ASSERT(ARM_PMU_CNTER_NR == ((reg >> 11) & 0x1f)); 12 | } 13 | -------------------------------------------------------------------------------- /boot/cpu/pmu.h: -------------------------------------------------------------------------------- 1 | #ifndef __PMU_H__ 2 | #define __PMU_H__ 3 | 4 | #include "board.h" 5 | 6 | /* Number of counters */ 7 | #define ARM_PMU_CNTER_NR 4 8 | 9 | enum rt_hw_pmu_event_type { 10 | ARM_PMU_EVENT_PMNC_SW_INCR = 0x00, 11 | ARM_PMU_EVENT_L1_ICACHE_REFILL = 0x01, 12 | ARM_PMU_EVENT_ITLB_REFILL = 0x02, 13 | ARM_PMU_EVENT_L1_DCACHE_REFILL = 0x03, 14 | ARM_PMU_EVENT_L1_DCACHE_ACCESS = 0x04, 15 | ARM_PMU_EVENT_DTLB_REFILL = 0x05, 16 | ARM_PMU_EVENT_MEM_READ = 0x06, 17 | ARM_PMU_EVENT_MEM_WRITE = 0x07, 18 | ARM_PMU_EVENT_INSTR_EXECUTED = 0x08, 19 | ARM_PMU_EVENT_EXC_TAKEN = 0x09, 20 | ARM_PMU_EVENT_EXC_EXECUTED = 0x0A, 21 | ARM_PMU_EVENT_CID_WRITE = 0x0B, 22 | }; 23 | 24 | /* Enable bit */ 25 | #define ARM_PMU_PMCR_E (0x01 << 0) 26 | /* Event counter reset */ 27 | #define ARM_PMU_PMCR_P (0x01 << 1) 28 | /* Cycle counter reset */ 29 | #define ARM_PMU_PMCR_C (0x01 << 2) 30 | /* Cycle counter divider */ 31 | #define ARM_PMU_PMCR_D (0x01 << 3) 32 | 33 | #ifdef __GNUC__ 34 | rt_inline void rt_hw_pmu_enable_cnt(int divide64) 35 | { 36 | unsigned long pmcr; 37 | unsigned long pmcntenset; 38 | 39 | asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr)); 40 | pmcr |= ARM_PMU_PMCR_E | ARM_PMU_PMCR_P | ARM_PMU_PMCR_C; 41 | if (divide64) 42 | pmcr |= ARM_PMU_PMCR_D; 43 | else 44 | pmcr &= ~ARM_PMU_PMCR_D; 45 | asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr)); 46 | 47 | /* enable all the counters */ 48 | pmcntenset = ~0; 49 | asm volatile ("mcr p15, 0, %0, c9, c12, 1" :: "r"(pmcntenset)); 50 | /* clear overflows(just in case) */ 51 | asm volatile ("mcr p15, 0, %0, c9, c12, 3" :: "r"(pmcntenset)); 52 | } 53 | 54 | rt_inline unsigned long rt_hw_pmu_get_control(void) 55 | { 56 | unsigned long pmcr; 57 | asm ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr)); 58 | return pmcr; 59 | } 60 | 61 | rt_inline unsigned long rt_hw_pmu_get_ceid(void) 62 | { 63 | unsigned long reg; 64 | /* only PMCEID0 is supported, PMCEID1 is RAZ. */ 65 | asm ("mrc p15, 0, %0, c9, c12, 6" : "=r"(reg)); 66 | return reg; 67 | } 68 | 69 | rt_inline unsigned long rt_hw_pmu_get_cnten(void) 70 | { 71 | unsigned long pmcnt; 72 | asm ("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcnt)); 73 | return pmcnt; 74 | } 75 | 76 | rt_inline void rt_hw_pmu_reset_cycle(void) 77 | { 78 | unsigned long pmcr; 79 | 80 | asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr)); 81 | pmcr |= ARM_PMU_PMCR_C; 82 | asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr)); 83 | asm volatile ("isb"); 84 | } 85 | 86 | rt_inline void rt_hw_pmu_reset_event(void) 87 | { 88 | unsigned long pmcr; 89 | 90 | asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr)); 91 | pmcr |= ARM_PMU_PMCR_P; 92 | asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr)); 93 | asm volatile ("isb"); 94 | } 95 | 96 | rt_inline unsigned long rt_hw_pmu_get_cycle(void) 97 | { 98 | unsigned long cyc; 99 | asm volatile ("isb"); 100 | asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r"(cyc)); 101 | return cyc; 102 | } 103 | 104 | rt_inline void rt_hw_pmu_select_counter(int idx) 105 | { 106 | RT_ASSERT(idx < ARM_PMU_CNTER_NR); 107 | 108 | asm volatile ("mcr p15, 0, %0, c9, c12, 5" : : "r"(idx)); 109 | /* Linux add an isb here, don't know why here. */ 110 | asm volatile ("isb"); 111 | } 112 | 113 | rt_inline void rt_hw_pmu_select_event(int idx, 114 | enum rt_hw_pmu_event_type eve) 115 | { 116 | RT_ASSERT(idx < ARM_PMU_CNTER_NR); 117 | 118 | rt_hw_pmu_select_counter(idx); 119 | asm volatile ("mcr p15, 0, %0, c9, c13, 1" : : "r"(eve)); 120 | } 121 | 122 | rt_inline unsigned long rt_hw_pmu_read_counter(int idx) 123 | { 124 | unsigned long reg; 125 | 126 | rt_hw_pmu_select_counter(idx); 127 | asm volatile ("isb"); 128 | asm volatile ("mrc p15, 0, %0, c9, c13, 2" : "=r"(reg)); 129 | return reg; 130 | } 131 | 132 | rt_inline unsigned long rt_hw_pmu_get_ovsr(void) 133 | { 134 | unsigned long reg; 135 | asm volatile ("isb"); 136 | asm ("mrc p15, 0, %0, c9, c12, 3" : "=r"(reg)); 137 | return reg; 138 | } 139 | 140 | rt_inline void rt_hw_pmu_clear_ovsr(unsigned long reg) 141 | { 142 | asm ("mcr p15, 0, %0, c9, c12, 3" : : "r"(reg)); 143 | asm volatile ("isb"); 144 | } 145 | 146 | #endif 147 | 148 | void rt_hw_pmu_dump_feature(void); 149 | 150 | #endif /* end of include guard: __PMU_H__ */ 151 | 152 | -------------------------------------------------------------------------------- /boot/cpu/stack.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : stack.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2011, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2011-09-23 Bernard the first version 13 | * 2011-10-05 Bernard add thumb mode 14 | */ 15 | #include 16 | #include 17 | 18 | /** 19 | * @addtogroup AM33xx 20 | */ 21 | /*@{*/ 22 | 23 | /** 24 | * This function will initialize thread stack 25 | * 26 | * @param tentry the entry of thread 27 | * @param parameter the parameter of entry 28 | * @param stack_addr the beginning stack address 29 | * @param texit the function will be called when thread exit 30 | * 31 | * @return stack address 32 | */ 33 | rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, 34 | rt_uint8_t *stack_addr, void *texit) 35 | { 36 | rt_uint32_t *stk; 37 | 38 | stk = (rt_uint32_t*)stack_addr; 39 | *(stk) = (rt_uint32_t)tentry; /* entry point */ 40 | *(--stk) = (rt_uint32_t)texit; /* lr */ 41 | *(--stk) = 0; /* r12 */ 42 | *(--stk) = 0; /* r11 */ 43 | *(--stk) = 0; /* r10 */ 44 | *(--stk) = 0; /* r9 */ 45 | *(--stk) = 0; /* r8 */ 46 | *(--stk) = 0; /* r7 */ 47 | *(--stk) = 0; /* r6 */ 48 | *(--stk) = 0; /* r5 */ 49 | *(--stk) = 0; /* r4 */ 50 | *(--stk) = 0; /* r3 */ 51 | *(--stk) = 0; /* r2 */ 52 | *(--stk) = 0; /* r1 */ 53 | *(--stk) = (rt_uint32_t)parameter; /* r0 : argument */ 54 | 55 | /* cpsr */ 56 | if ((rt_uint32_t)tentry & 0x01) 57 | *(--stk) = SVCMODE | 0x20; /* thumb mode */ 58 | else 59 | *(--stk) = SVCMODE; /* arm mode */ 60 | 61 | /* return task's current stack address */ 62 | return (rt_uint8_t *)stk; 63 | } 64 | 65 | /*@}*/ 66 | -------------------------------------------------------------------------------- /boot/cpu/start_gcc.S: -------------------------------------------------------------------------------- 1 | /* 2 | * File : start_gcc.S 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013-2014, RT-Thread Development Team 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Change Logs: 21 | * Date Author Notes 22 | * 2013-07-05 Bernard the first version 23 | */ 24 | 25 | .equ Mode_USR, 0x10 26 | .equ Mode_FIQ, 0x11 27 | .equ Mode_IRQ, 0x12 28 | .equ Mode_SVC, 0x13 29 | .equ Mode_ABT, 0x17 30 | .equ Mode_UND, 0x1B 31 | .equ Mode_SYS, 0x1F 32 | 33 | .equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled 34 | .equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled 35 | 36 | .equ UND_Stack_Size, 0x00000000 37 | .equ SVC_Stack_Size, 0x00000100 38 | .equ ABT_Stack_Size, 0x00000000 39 | .equ RT_FIQ_STACK_PGSZ, 0x00000000 40 | .equ RT_IRQ_STACK_PGSZ, 0x00000100 41 | .equ USR_Stack_Size, 0x00000100 42 | 43 | #define ISR_Stack_Size (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \ 44 | RT_FIQ_STACK_PGSZ + RT_IRQ_STACK_PGSZ) 45 | 46 | .section .data.share.isr 47 | /* stack */ 48 | .globl stack_start 49 | .globl stack_top 50 | 51 | stack_start: 52 | .rept ISR_Stack_Size 53 | .byte 0 54 | .endr 55 | stack_top: 56 | 57 | .text 58 | /* reset entry */ 59 | .globl _reset 60 | _reset: 61 | /* set the cpu to SVC32 mode and disable interrupt */ 62 | mrs r0, cpsr 63 | bic r0, r0, #0x1f 64 | orr r0, r0, #0x13 65 | msr cpsr_c, r0 66 | 67 | /* setup stack */ 68 | bl stack_setup 69 | 70 | /* clear .bss */ 71 | mov r0,#0 /* get a zero */ 72 | ldr r1,=__bss_start /* bss start */ 73 | ldr r2,=__bss_end /* bss end */ 74 | 75 | bss_loop: 76 | cmp r1,r2 /* check if data to clear */ 77 | strlo r0,[r1],#4 /* clear 4 bytes */ 78 | blo bss_loop /* loop until done */ 79 | 80 | /* call C++ constructors of global objects */ 81 | ldr r0, =__ctors_start__ 82 | ldr r1, =__ctors_end__ 83 | 84 | ctor_loop: 85 | cmp r0, r1 86 | beq ctor_end 87 | ldr r2, [r0], #4 88 | stmfd sp!, {r0-r1} 89 | mov lr, pc 90 | bx r2 91 | ldmfd sp!, {r0-r1} 92 | b ctor_loop 93 | ctor_end: 94 | 95 | /* start RT-Thread Kernel */ 96 | ldr pc, _rtthread_startup 97 | _rtthread_startup: 98 | .word rtthread_startup 99 | 100 | stack_setup: 101 | ldr r0, =stack_top 102 | 103 | @ Set the startup stack for svc 104 | mov sp, r0 105 | 106 | @ Enter Undefined Instruction Mode and set its Stack Pointer 107 | msr cpsr_c, #Mode_UND|I_Bit|F_Bit 108 | mov sp, r0 109 | sub r0, r0, #UND_Stack_Size 110 | 111 | @ Enter Abort Mode and set its Stack Pointer 112 | msr cpsr_c, #Mode_ABT|I_Bit|F_Bit 113 | mov sp, r0 114 | sub r0, r0, #ABT_Stack_Size 115 | 116 | @ Enter FIQ Mode and set its Stack Pointer 117 | msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit 118 | mov sp, r0 119 | sub r0, r0, #RT_FIQ_STACK_PGSZ 120 | 121 | @ Enter IRQ Mode and set its Stack Pointer 122 | msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit 123 | mov sp, r0 124 | sub r0, r0, #RT_IRQ_STACK_PGSZ 125 | 126 | /* come back to SVC mode */ 127 | msr cpsr_c, #Mode_SVC|I_Bit|F_Bit 128 | bx lr 129 | 130 | /* exception handlers: undef, swi, padt, dabt, resv, irq, fiq */ 131 | .section .text.isr, "ax" 132 | .align 5 133 | .globl vector_fiq 134 | vector_fiq: 135 | stmfd sp!,{r0-r7,lr} 136 | bl rt_hw_trap_fiq 137 | ldmfd sp!,{r0-r7,lr} 138 | subs pc, lr, #4 139 | 140 | .globl rt_interrupt_enter 141 | .globl rt_interrupt_leave 142 | .globl rt_thread_switch_interrupt_flag 143 | .globl rt_interrupt_from_thread 144 | .globl rt_interrupt_to_thread 145 | 146 | .globl rt_current_thread 147 | .globl vmm_thread 148 | .globl vmm_virq_check 149 | 150 | .align 5 151 | .globl vector_irq 152 | vector_irq: 153 | stmfd sp!, {r0-r12,lr} 154 | 155 | bl rt_interrupt_enter 156 | bl rt_hw_trap_irq 157 | bl rt_interrupt_leave 158 | 159 | @ if rt_thread_switch_interrupt_flag set, jump to 160 | @ rt_hw_context_switch_interrupt_do and don't return 161 | ldr r0, =rt_thread_switch_interrupt_flag 162 | ldr r1, [r0] 163 | cmp r1, #1 164 | beq rt_hw_context_switch_interrupt_do 165 | 166 | ldmfd sp!, {r0-r12,lr} 167 | subs pc, lr, #4 168 | 169 | rt_hw_context_switch_interrupt_do: 170 | mov r1, #0 @ clear flag 171 | str r1, [r0] 172 | 173 | mov r1, sp @ r1 point to {r0-r3} in stack 174 | add sp, sp, #4*4 175 | ldmfd sp!, {r4-r12,lr}@ reload saved registers 176 | mrs r0, spsr @ get cpsr of interrupt thread 177 | sub r2, lr, #4 @ save old task's pc to r2 178 | 179 | @ Switch to SVC mode with no interrupt. If the usr mode guest is 180 | @ interrupted, this will just switch to the stack of kernel space. 181 | @ save the registers in kernel space won't trigger data abort. 182 | msr cpsr_c, #I_Bit|F_Bit|Mode_SVC 183 | 184 | stmfd sp!, {r2} @ push old task's pc 185 | stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4 186 | ldmfd r1, {r1-r4} @ restore r0-r3 of the interrupt thread 187 | stmfd sp!, {r1-r4} @ push old task's r0-r3 188 | stmfd sp!, {r0} @ push old task's cpsr 189 | 190 | ldr r4, =rt_interrupt_from_thread 191 | ldr r5, [r4] 192 | str sp, [r5] @ store sp in preempted tasks's TCB 193 | 194 | ldr r6, =rt_interrupt_to_thread 195 | ldr r6, [r6] 196 | ldr sp, [r6] @ get new task's stack pointer 197 | 198 | ldmfd sp!, {r4} @ pop new task's cpsr to spsr 199 | msr spsr_cxsf, r4 200 | 201 | ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr 202 | 203 | .macro push_svc_reg 204 | sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */ 205 | stmia sp, {r0 - r12} @/* Calling r0-r12 */ 206 | mov r0, sp 207 | mrs r6, spsr @/* Save CPSR */ 208 | str lr, [r0, #15*4] @/* Push PC */ 209 | str r6, [r0, #16*4] @/* Push CPSR */ 210 | cps #Mode_SVC 211 | str sp, [r0, #13*4] @/* Save calling SP */ 212 | str lr, [r0, #14*4] @/* Save calling PC */ 213 | .endm 214 | 215 | .align 5 216 | .globl vector_swi 217 | vector_swi: 218 | push_svc_reg 219 | bl rt_hw_trap_swi 220 | b . 221 | 222 | .align 5 223 | .globl vector_undef 224 | vector_undef: 225 | push_svc_reg 226 | bl rt_hw_trap_undef 227 | b . 228 | 229 | .align 5 230 | .globl vector_pabt 231 | vector_pabt: 232 | push_svc_reg 233 | bl rt_hw_trap_pabt 234 | b . 235 | 236 | .align 5 237 | .globl vector_dabt 238 | vector_dabt: 239 | push_svc_reg 240 | bl rt_hw_trap_dabt 241 | b . 242 | 243 | .align 5 244 | .globl vector_resv 245 | vector_resv: 246 | push_svc_reg 247 | bl rt_hw_trap_resv 248 | b . 249 | -------------------------------------------------------------------------------- /boot/cpu/trap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : trap.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Develop Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2013-07-20 Bernard first version 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "armv7.h" 20 | 21 | #ifdef RT_USING_VMM 22 | #include 23 | #endif 24 | 25 | #include "gic.h" 26 | 27 | extern struct rt_thread *rt_current_thread; 28 | #ifdef RT_USING_FINSH 29 | extern long list_thread(void); 30 | #endif 31 | 32 | /** 33 | * this function will show registers of CPU 34 | * 35 | * @param regs the registers point 36 | */ 37 | void rt_hw_show_register(struct rt_hw_exp_stack *regs) 38 | { 39 | rt_kprintf("Execption:\n"); 40 | rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3); 41 | rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7); 42 | rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10); 43 | rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip); 44 | rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc); 45 | rt_kprintf("cpsr:0x%08x\n", regs->cpsr); 46 | } 47 | 48 | /** 49 | * When comes across an instruction which it cannot handle, 50 | * it takes the undefined instruction trap. 51 | * 52 | * @param regs system registers 53 | * 54 | * @note never invoke this function in application 55 | */ 56 | void rt_hw_trap_undef(struct rt_hw_exp_stack *regs) 57 | { 58 | rt_kprintf("undefined instruction:\n"); 59 | rt_hw_show_register(regs); 60 | #ifdef RT_USING_FINSH 61 | list_thread(); 62 | #endif 63 | rt_hw_cpu_shutdown(); 64 | } 65 | 66 | /** 67 | * The software interrupt instruction (SWI) is used for entering 68 | * Supervisor mode, usually to request a particular supervisor 69 | * function. 70 | * 71 | * @param regs system registers 72 | * 73 | * @note never invoke this function in application 74 | */ 75 | void rt_hw_trap_swi(struct rt_hw_exp_stack *regs) 76 | { 77 | rt_kprintf("software interrupt:\n"); 78 | rt_hw_show_register(regs); 79 | #ifdef RT_USING_FINSH 80 | list_thread(); 81 | #endif 82 | rt_hw_cpu_shutdown(); 83 | } 84 | 85 | /** 86 | * An abort indicates that the current memory access cannot be completed, 87 | * which occurs during an instruction prefetch. 88 | * 89 | * @param regs system registers 90 | * 91 | * @note never invoke this function in application 92 | */ 93 | void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs) 94 | { 95 | rt_kprintf("prefetch abort:\n"); 96 | rt_hw_show_register(regs); 97 | #ifdef RT_USING_FINSH 98 | list_thread(); 99 | #endif 100 | rt_hw_cpu_shutdown(); 101 | } 102 | 103 | /** 104 | * An abort indicates that the current memory access cannot be completed, 105 | * which occurs during a data access. 106 | * 107 | * @param regs system registers 108 | * 109 | * @note never invoke this function in application 110 | */ 111 | void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs) 112 | { 113 | rt_kprintf("data abort:"); 114 | rt_hw_show_register(regs); 115 | #ifdef RT_USING_FINSH 116 | list_thread(); 117 | #endif 118 | rt_hw_cpu_shutdown(); 119 | } 120 | 121 | /** 122 | * Normally, system will never reach here 123 | * 124 | * @param regs system registers 125 | * 126 | * @note never invoke this function in application 127 | */ 128 | void rt_hw_trap_resv(struct rt_hw_exp_stack *regs) 129 | { 130 | rt_kprintf("reserved trap:\n"); 131 | rt_hw_show_register(regs); 132 | #ifdef RT_USING_FINSH 133 | list_thread(); 134 | #endif 135 | rt_hw_cpu_shutdown(); 136 | } 137 | 138 | #define GIC_ACK_INTID_MASK 0x000003ff 139 | 140 | void rt_hw_trap_irq(void) 141 | { 142 | void *param; 143 | unsigned long ir; 144 | unsigned long fullir; 145 | rt_isr_handler_t isr_func; 146 | extern struct rt_irq_desc isr_table[]; 147 | 148 | fullir = arm_gic_get_active_irq(0); 149 | ir = fullir & GIC_ACK_INTID_MASK; 150 | 151 | if (ir == 1023) 152 | { 153 | /* Spurious interrupt */ 154 | return; 155 | } 156 | 157 | /* get interrupt service routine */ 158 | isr_func = isr_table[ir].handler; 159 | #ifdef RT_USING_INTERRUPT_INFO 160 | isr_table[ir].counter++; 161 | #endif 162 | if (isr_func) 163 | { 164 | /* Interrupt for myself. */ 165 | param = isr_table[ir].param; 166 | /* turn to interrupt service routine */ 167 | isr_func(ir, param); 168 | } 169 | #ifdef RT_USING_VMM 170 | else 171 | { 172 | /* We have to EOI before masking the interrupts */ 173 | arm_gic_ack(0, fullir); 174 | vmm_virq_pending(ir); 175 | return; 176 | } 177 | #endif 178 | 179 | /* end of interrupt */ 180 | arm_gic_ack(0, fullir); 181 | } 182 | 183 | void rt_hw_trap_fiq(void) 184 | { 185 | void *param; 186 | unsigned long ir; 187 | unsigned long fullir; 188 | rt_isr_handler_t isr_func; 189 | extern struct rt_irq_desc isr_table[]; 190 | 191 | fullir = arm_gic_get_active_irq(0); 192 | ir = fullir & GIC_ACK_INTID_MASK; 193 | 194 | /* get interrupt service routine */ 195 | isr_func = isr_table[ir].handler; 196 | param = isr_table[ir].param; 197 | 198 | /* turn to interrupt service routine */ 199 | isr_func(ir, param); 200 | 201 | /* end of interrupt */ 202 | arm_gic_ack(0, fullir); 203 | } 204 | 205 | -------------------------------------------------------------------------------- /boot/cpu/vector_gcc.S: -------------------------------------------------------------------------------- 1 | /* 2 | * File : vector_gcc.S 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Development Team 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Change Logs: 21 | * Date Author Notes 22 | * 2013-07-05 Bernard the first version 23 | */ 24 | 25 | .section .vectors, "ax" 26 | .code 32 27 | 28 | .globl system_vectors 29 | system_vectors: 30 | ldr pc, _vector_reset 31 | ldr pc, _vector_undef 32 | ldr pc, _vector_swi 33 | ldr pc, _vector_pabt 34 | ldr pc, _vector_dabt 35 | ldr pc, _vector_resv 36 | ldr pc, _vector_irq 37 | ldr pc, _vector_fiq 38 | 39 | .globl _reset 40 | .globl vector_undef 41 | .globl vector_swi 42 | .globl vector_pabt 43 | .globl vector_dabt 44 | .globl vector_resv 45 | .globl vector_irq 46 | .globl vector_fiq 47 | 48 | _vector_reset: 49 | .word _reset 50 | _vector_undef: 51 | .word vector_undef 52 | _vector_swi: 53 | .word vector_swi 54 | _vector_pabt: 55 | .word vector_pabt 56 | _vector_dabt: 57 | .word vector_dabt 58 | _vector_resv: 59 | .word vector_resv 60 | _vector_irq: 61 | .word vector_irq 62 | _vector_fiq: 63 | .word vector_fiq 64 | 65 | .balignl 16,0xdeadbeef 66 | -------------------------------------------------------------------------------- /boot/drivers/SConscript: -------------------------------------------------------------------------------- 1 | import copy 2 | Import('RTT_ROOT') 3 | Import('rtconfig') 4 | from building import * 5 | 6 | cwd = GetCurrentDir() 7 | src = Glob('*.c') 8 | 9 | CPPPATH = [cwd] 10 | 11 | group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) 12 | 13 | Return('group') 14 | -------------------------------------------------------------------------------- /boot/drivers/board.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : board.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2012, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2012-11-20 Bernard the first version 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | #include "board.h" 19 | #include "serial.h" 20 | 21 | extern void rt_hw_mmu_init(void); 22 | 23 | /** 24 | * This function will initialize EVB board 25 | */ 26 | void rt_hw_board_init(void) 27 | { 28 | // rt_hw_uart_init(); 29 | // rt_console_set_device(RT_CONSOLE_DEVICE_NAME); 30 | 31 | /* MMU */ 32 | rt_hw_mmu_init(); 33 | } 34 | 35 | /*@}*/ 36 | -------------------------------------------------------------------------------- /boot/drivers/board.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File : board.h 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2013-07-06 Bernard the first version 13 | */ 14 | 15 | #ifndef __BOARD_H__ 16 | #define __BOARD_H__ 17 | 18 | #include 19 | 20 | #if defined(__CC_ARM) 21 | extern int Image$$RW_IRAM1$$ZI$$Limit; 22 | #define HEAP_BEGIN ((void*)&Image$$RW_IRAM1$$ZI$$Limit) 23 | #elif defined(__GNUC__) 24 | extern int __bss_end; 25 | #define HEAP_BEGIN ((void*)&__bss_end) 26 | #endif 27 | 28 | #define HEAP_END (void*)(0x90000000) 29 | 30 | void rt_hw_board_init(void); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /boot/drivers/serial.c: -------------------------------------------------------------------------------- 1 | /* 2 | * serial.c UART driver 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * Maintainer: bernard.xiong 8 | * 9 | * All rights reserved. 10 | * 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation; either version 2 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License along 22 | * with this program; if not, write to the Free Software Foundation, Inc., 23 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 24 | * 25 | * Change Logs: 26 | * Date Author Notes 27 | * 2013-03-30 Bernard the first verion 28 | */ 29 | 30 | #include 31 | #include 32 | 33 | #include "serial.h" 34 | 35 | struct hw_uart_device 36 | { 37 | rt_uint32_t hw_base; 38 | rt_uint32_t irqno; 39 | }; 40 | 41 | #define UART_DR(base) __REG32(base + 0x00) 42 | #define UART_FR(base) __REG32(base + 0x18) 43 | #define UART_CR(base) __REG32(base + 0x30) 44 | #define UART_IMSC(base) __REG32(base + 0x38) 45 | #define UART_ICR(base) __REG32(base + 0x44) 46 | 47 | #define UARTFR_RXFE 0x10 48 | #define UARTFR_TXFF 0x20 49 | #define UARTIMSC_RXIM 0x10 50 | #define UARTIMSC_TXIM 0x20 51 | #define UARTICR_RXIC 0x10 52 | #define UARTICR_TXIC 0x20 53 | 54 | static void rt_hw_uart_isr(int irqno, void *param) 55 | { 56 | struct rt_serial_device *serial = (struct rt_serial_device *)param; 57 | 58 | rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); 59 | } 60 | 61 | static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) 62 | { 63 | return RT_EOK; 64 | } 65 | 66 | static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg) 67 | { 68 | struct hw_uart_device *uart; 69 | 70 | RT_ASSERT(serial != RT_NULL); 71 | uart = (struct hw_uart_device *)serial->parent.user_data; 72 | 73 | switch (cmd) 74 | { 75 | case RT_DEVICE_CTRL_CLR_INT: 76 | /* disable rx irq */ 77 | UART_IMSC(uart->hw_base) &= ~UARTIMSC_RXIM; 78 | break; 79 | 80 | case RT_DEVICE_CTRL_SET_INT: 81 | /* enable rx irq */ 82 | UART_IMSC(uart->hw_base) |= UARTIMSC_RXIM; 83 | rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, serial, "uart"); 84 | rt_hw_interrupt_umask(uart->irqno); 85 | break; 86 | } 87 | 88 | return RT_EOK; 89 | } 90 | 91 | static int uart_putc(struct rt_serial_device *serial, char c) 92 | { 93 | struct hw_uart_device *uart; 94 | 95 | RT_ASSERT(serial != RT_NULL); 96 | uart = (struct hw_uart_device *)serial->parent.user_data; 97 | 98 | while (UART_FR(uart->hw_base) & UARTFR_TXFF); 99 | UART_DR(uart->hw_base) = c; 100 | 101 | return 1; 102 | } 103 | 104 | static int uart_getc(struct rt_serial_device *serial) 105 | { 106 | int ch; 107 | struct hw_uart_device *uart; 108 | 109 | RT_ASSERT(serial != RT_NULL); 110 | uart = (struct hw_uart_device *)serial->parent.user_data; 111 | 112 | ch = -1; 113 | if (!(UART_FR(uart->hw_base) & UARTFR_RXFE)) 114 | { 115 | ch = UART_DR(uart->hw_base) & 0xff; 116 | } 117 | 118 | return ch; 119 | } 120 | 121 | static const struct rt_uart_ops _uart_ops = 122 | { 123 | uart_configure, 124 | uart_control, 125 | uart_putc, 126 | uart_getc, 127 | }; 128 | 129 | #ifdef RT_USING_UART0 130 | /* UART device driver structure */ 131 | static struct hw_uart_device _uart0_device = 132 | { 133 | REALVIEW_UART0_BASE, 134 | IRQ_PBA8_UART0, 135 | }; 136 | static struct rt_serial_device _serial0; 137 | #endif 138 | 139 | #ifdef RT_USING_UART1 140 | /* UART1 device driver structure */ 141 | static struct hw_uart_device _uart1_device = 142 | { 143 | REALVIEW_UART1_BASE, 144 | IRQ_PBA8_UART1, 145 | }; 146 | static struct rt_serial_device _serial1; 147 | #endif 148 | 149 | int uart_isr_test(void) 150 | { 151 | return uart_getc(&_serial1); 152 | } 153 | 154 | int rt_hw_uart_init(void) 155 | { 156 | struct hw_uart_device *uart; 157 | struct serial_configure config; 158 | 159 | config.baud_rate = BAUD_RATE_115200; 160 | config.bit_order = BIT_ORDER_LSB; 161 | config.data_bits = DATA_BITS_8; 162 | config.parity = PARITY_NONE; 163 | config.stop_bits = STOP_BITS_1; 164 | config.invert = NRZ_NORMAL; 165 | config.bufsz = RT_SERIAL_RB_BUFSZ; 166 | 167 | #ifdef RT_USING_UART0 168 | uart = &_uart0_device; 169 | 170 | _serial0.ops = &_uart_ops; 171 | _serial0.config = config; 172 | 173 | /* register UART1 device */ 174 | rt_hw_serial_register(&_serial0, "uart0", 175 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, 176 | uart); 177 | /* enable Rx and Tx of UART */ 178 | UART_CR(uart->hw_base) = (1 << 0) | (1 << 8) | (1 << 9); 179 | #endif 180 | 181 | #ifdef RT_USING_UART1 182 | uart = &_uart1_device; 183 | _serial1.ops = &_uart_ops; 184 | _serial1.config = config; 185 | 186 | /* register UART1 device */ 187 | rt_hw_serial_register(&_serial1, "uart1", 188 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); 189 | /* enable Rx and Tx of UART */ 190 | UART_CR(uart->hw_base) = (1 << 0) | (1 << 8) | (1 << 9); 191 | #endif 192 | 193 | return 0; 194 | } 195 | INIT_BOARD_EXPORT(rt_hw_uart_init); 196 | -------------------------------------------------------------------------------- /boot/drivers/serial.h: -------------------------------------------------------------------------------- 1 | /* 2 | * UART driver 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * Maintainer: bernard.xiong 8 | * 9 | * All rights reserved. 10 | * 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation; either version 2 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License along 22 | * with this program; if not, write to the Free Software Foundation, Inc., 23 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 24 | * 25 | * Change Logs: 26 | * Date Author Notes 27 | * 2013-03-30 Bernard the first verion 28 | */ 29 | 30 | #ifndef __UART_H__ 31 | #define __UART_H__ 32 | 33 | #include 34 | 35 | int rt_hw_uart_init(void); 36 | 37 | #endif 38 | 39 | 40 | -------------------------------------------------------------------------------- /boot/rtconfig.h: -------------------------------------------------------------------------------- 1 | /* RT-Thread config file */ 2 | #ifndef __RTTHREAD_CFG_H__ 3 | #define __RTTHREAD_CFG_H__ 4 | 5 | // 6 | 7 | // 8 | #define RT_NAME_MAX 6 9 | // 10 | #define RT_ALIGN_SIZE 4 11 | // 12 | // 8 13 | // 32 14 | // 256 15 | // 16 | #define RT_THREAD_PRIORITY_MAX 32 17 | // 18 | #define RT_TICK_PER_SECOND 1000 19 | // 20 | #define IDLE_THREAD_STACK_SIZE 512 21 | //
22 | // #define RT_DEBUG 23 | // 24 | // #define RT_DEBUG_SCHEDULER 1 25 | // 26 | #define RT_USING_OVERFLOW_CHECK 27 | //
28 | 29 | // 30 | #define RT_USING_HOOK 31 | //
32 | // #define RT_USING_TIMER_SOFT 33 | // 34 | #define RT_TIMER_THREAD_PRIO 4 35 | // 36 | #define RT_TIMER_THREAD_STACK_SIZE 512 37 | // 38 | #define RT_TIMER_TICK_PER_SECOND 10 39 | //
40 | 41 | //
42 | // 43 | #define RT_USING_SEMAPHORE 44 | // 45 | #define RT_USING_MUTEX 46 | // 47 | #define RT_USING_EVENT 48 | // 49 | #define RT_USING_MAILBOX 50 | // 51 | #define RT_USING_MESSAGEQUEUE 52 | //
53 | 54 | //
55 | // 56 | #define RT_USING_MEMPOOL 57 | // 58 | //#define RT_USING_MEMHEAP 59 | // 60 | #define RT_USING_HEAP 61 | // 62 | // #define RT_USING_MEMHEAP_AS_HEAP 63 | // 64 | #define RT_USING_SMALL_MEM 65 | // 66 | // #define RT_USING_SLAB 67 | //
68 | 69 | //
70 | #define RT_USING_DEVICE 71 | // 72 | #define RT_USING_DEVICE_IPC 73 | // 74 | #define RT_USING_SERIAL 75 | // 76 | #define RT_UART_RX_BUFFER_SIZE 64 77 | // 78 | #define RT_USING_INTERRUPT_INFO 79 | // 80 | // #define RT_USING_UART0 81 | // 82 | #define RT_USING_UART1 83 | //
84 | 85 | //
86 | #define RT_USING_CONSOLE 87 | // 88 | #define RT_CONSOLEBUF_SIZE 128 89 | // 90 | #define RT_CONSOLE_DEVICE_NAME "uart1" 91 | //
92 | 93 | // 94 | // #define RT_USING_COMPONENTS_INIT 95 | //
96 | // #define RT_USING_FINSH 97 | // 98 | #define FINSH_USING_MSH 99 | // 100 | #define FINSH_USING_MSH_DEFAULT 101 | // 102 | #define FINSH_USING_SYMTAB 103 | // 104 | #define FINSH_USING_DESCRIPTION 105 | // 106 | #define FINSH_THREAD_STACK_SIZE 4096 107 | //
108 | 109 | //
110 | // 111 | #define RT_USING_LIBC 112 | // 113 | // #define RT_USING_PTHREADS 114 | //
115 | 116 | //
117 | // #define RT_USING_DFS 118 | // 119 | // #define DFS_USING_WORKDIR 120 | // 121 | #define DFS_FILESYSTEMS_MAX 2 122 | // 123 | #define DFS_FD_MAX 4 124 | // 125 | #define RT_USING_DFS_ELMFAT 126 | // 127 | // 1 128 | // 2 129 | // 130 | #define RT_DFS_ELM_USE_LFN 1 131 | // 132 | #define RT_DFS_ELM_MAX_LFN 64 133 | // 134 | // #define RT_USING_DFS_YAFFS2 135 | // 136 | // #define RT_USING_DFS_UFFS 137 | // 138 | // #define RT_USING_DFS_DEVFS 139 | // 140 | // #define RT_USING_DFS_NFS 141 | // 142 | #define RT_NFS_HOST_EXPORT "192.168.1.5:/" 143 | //
144 | 145 | //
146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /boot/rtconfig.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # toolchains options 4 | ARCH='arm' 5 | CPU='vexpress-a9' 6 | CROSS_TOOL='gcc' 7 | 8 | if os.getenv('RTT_CC'): 9 | CROSS_TOOL = os.getenv('RTT_CC') 10 | 11 | if CROSS_TOOL == 'gcc': 12 | PLATFORM = 'gcc' 13 | # EXEC_PATH = r'/opt/arm-2012.09/bin' 14 | EXEC_PATH = r'C:\Program Files (x86)\CodeSourcery\Sourcery_CodeBench_Lite_for_ARM_EABI\bin' 15 | EXEC_PATH = '/opt/gcc-arm-none-eabi-4_8-2014q1_gri/bin' 16 | elif CROSS_TOOL == 'keil': 17 | PLATFORM = 'armcc' 18 | EXEC_PATH = 'C:/Keil' 19 | 20 | if os.getenv('RTT_EXEC_PATH'): 21 | EXEC_PATH = os.getenv('RTT_EXEC_PATH') 22 | 23 | BUILD = 'debug' 24 | 25 | if PLATFORM == 'gcc': 26 | # toolchains 27 | PREFIX = 'arm-none-eabi-' 28 | CC = PREFIX + 'gcc' 29 | CXX = PREFIX + 'g++' 30 | AS = PREFIX + 'gcc' 31 | AR = PREFIX + 'ar' 32 | LINK = PREFIX + 'gcc' 33 | TARGET_EXT = 'elf' 34 | SIZE = PREFIX + 'size' 35 | OBJDUMP = PREFIX + 'objdump' 36 | OBJCPY = PREFIX + 'objcopy' 37 | 38 | DEVICE = ' -march=armv7-a -mtune=cortex-a9 -mfpu=vfpv3-d16 -ftree-vectorize -ffast-math -mfloat-abi=softfp' 39 | CFLAGS = DEVICE + ' -Wall' 40 | AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__' 41 | LINK_SCRIPT = 'vexpress.lds' 42 | LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=vexpress.map,-cref,-u,system_vectors'+\ 43 | ' -T %s' % LINK_SCRIPT 44 | 45 | CPATH = '' 46 | LPATH = '' 47 | 48 | # generate debug info in all cases 49 | AFLAGS += ' -gdwarf-2' 50 | CFLAGS += ' -g -gdwarf-2' 51 | 52 | if BUILD == 'debug': 53 | CFLAGS += ' -O0' 54 | else: 55 | CFLAGS += ' -O2' 56 | 57 | POST_ACTION = OBJCPY + ' -O binary $TARGET boot.bin\n' +\ 58 | SIZE + ' $TARGET \n' 59 | 60 | elif PLATFORM == 'armcc': 61 | # toolchains 62 | CC = 'armcc' 63 | CXX = 'armcc' 64 | AS = 'armasm' 65 | AR = 'armar' 66 | LINK = 'armlink' 67 | TARGET_EXT = 'axf' 68 | 69 | DEVICE = ' --device DARMP' 70 | CFLAGS = DEVICE + ' --apcs=interwork' 71 | AFLAGS = DEVICE 72 | LFLAGS = DEVICE + ' --info sizes --info totals --info unused --info veneers --list rtthread-vexpress.map --scatter vexpress.sct' 73 | 74 | CFLAGS += ' -I' + EXEC_PATH + '/ARM/RV31/INC' 75 | LFLAGS += ' --libpath ' + EXEC_PATH + '/ARM/RV31/LIB' 76 | 77 | EXEC_PATH += '/arm/bin40/' 78 | 79 | if BUILD == 'debug': 80 | CFLAGS += ' -g -O0' 81 | AFLAGS += ' -g' 82 | else: 83 | CFLAGS += ' -O2' 84 | 85 | POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' 86 | 87 | elif PLATFORM == 'iar': 88 | # toolchains 89 | CC = 'iccarm' 90 | AS = 'iasmarm' 91 | AR = 'iarchive' 92 | LINK = 'ilinkarm' 93 | TARGET_EXT = 'out' 94 | 95 | DEVICE = ' --cpu DARMP' 96 | 97 | CFLAGS = '' 98 | AFLAGS = '' 99 | LFLAGS = ' --config vexpress.icf' 100 | 101 | EXEC_PATH += '/arm/bin/' 102 | RT_USING_MINILIBC = False 103 | POST_ACTION = '' 104 | -------------------------------------------------------------------------------- /boot/vexpress.lds: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 2 | OUTPUT_ARCH(arm) 3 | SECTIONS 4 | { 5 | . = 0x8FB00000; 6 | 7 | __text_start = .; 8 | .text : 9 | { 10 | *(.vectors) 11 | *(.text) 12 | *(.text.*) 13 | 14 | /* section information for finsh shell */ 15 | . = ALIGN(4); 16 | __fsymtab_start = .; 17 | KEEP(*(FSymTab)) 18 | __fsymtab_end = .; 19 | . = ALIGN(4); 20 | __vsymtab_start = .; 21 | KEEP(*(VSymTab)) 22 | __vsymtab_end = .; 23 | . = ALIGN(4); 24 | 25 | /* section information for modules */ 26 | . = ALIGN(4); 27 | __rtmsymtab_start = .; 28 | KEEP(*(RTMSymTab)) 29 | __rtmsymtab_end = .; 30 | 31 | /* section information for initialization */ 32 | . = ALIGN(4); 33 | __rt_init_start = .; 34 | KEEP(*(SORT(.rti_fn*))) 35 | __rt_init_end = .; 36 | } =0 37 | __text_end = .; 38 | 39 | __rodata_start = .; 40 | .rodata : { *(.rodata) *(.rodata.*) } 41 | __rodata_end = .; 42 | 43 | . = ALIGN(4); 44 | .ctors : 45 | { 46 | PROVIDE(__ctors_start__ = .); 47 | KEEP(*(SORT(.ctors.*))) 48 | KEEP(*(.ctors)) 49 | PROVIDE(__ctors_end__ = .); 50 | } 51 | 52 | .dtors : 53 | { 54 | PROVIDE(__dtors_start__ = .); 55 | KEEP(*(SORT(.dtors.*))) 56 | KEEP(*(.dtors)) 57 | PROVIDE(__dtors_end__ = .); 58 | } 59 | 60 | __data_start = .; 61 | . = ALIGN(4); 62 | .data : 63 | { 64 | *(.data) 65 | *(.data.*) 66 | } 67 | __data_end = .; 68 | 69 | . = ALIGN(4); 70 | __bss_start = __data_end; 71 | .bss : 72 | { 73 | *(.bss) 74 | *(.bss.*) 75 | *(COMMON) 76 | . = ALIGN(4); 77 | } 78 | . = ALIGN(4); 79 | __bss_end = .; 80 | 81 | /* Stabs debugging sections. */ 82 | .stab 0 : { *(.stab) } 83 | .stabstr 0 : { *(.stabstr) } 84 | .stab.excl 0 : { *(.stab.excl) } 85 | .stab.exclstr 0 : { *(.stab.exclstr) } 86 | .stab.index 0 : { *(.stab.index) } 87 | .stab.indexstr 0 : { *(.stab.indexstr) } 88 | .comment 0 : { *(.comment) } 89 | 90 | _end = .; 91 | } 92 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | cd buildroot-2015.05 2 | make 3 | cd .. 4 | 5 | cd boot 6 | ./build.sh 7 | cd .. 8 | 9 | cd vexpress 10 | ./build.sh 11 | cd .. 12 | 13 | cd rtloader 14 | ./build.sh 15 | cd .. 16 | 17 | cd linux-apps 18 | make 19 | cp vecho $MO_DIR 20 | cd .. 21 | 22 | cd buildroot-2015.05 23 | make 24 | cd .. 25 | 26 | -------------------------------------------------------------------------------- /dn_prepare.sh: -------------------------------------------------------------------------------- 1 | # download RT-Thread git code 2 | git clone https://github.com/RT-Thread/rt-thread.git 3 | # install 32bit environment 4 | sudo apt-get update 5 | sudo apt-get update 6 | sudo apt-get -y install lib32z1 astyle 7 | # prepare toolchains and scons 8 | sudo apt-get -y install scons qemu-system-arm libncurses5-dev zip bc texinfo 9 | 10 | # clone package files repo 11 | git clone https://git.coding.net/RT-Thread/packages-files.git 12 | 13 | # download toolchain 14 | if [ ! -f "arm-2012.09-63-arm-none-eabi-i686-pc-linux-gnu.tar.bz2" ];then 15 | wget -c https://sourcery.mentor.com/public/gnu_toolchain/arm-none-eabi/arm-2012.09-63-arm-none-eabi-i686-pc-linux-gnu.tar.bz2 16 | tar jxvf arm-2012.09-63-arm-none-eabi-i686-pc-linux-gnu.tar.bz2 17 | fi 18 | 19 | # download Linux 3.18.x 20 | if [ ! -f "linux-3.18.16.tar.xz" ]; then 21 | wget -c https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.18.16.tar.xz 22 | tar Jxvf linux-3.18.16.tar.xz 23 | cd linux-3.18.16 24 | patch -p1 < ../rtthread_vbus.patch 25 | cd .. 26 | fi 27 | 28 | # download buildroot 29 | if [ ! -f "buildroot-2015.05.tar.bz2" ]; then 30 | wget -c http://www.buildroot.org/downloads/buildroot-2015.05.tar.bz2 31 | tar jxvf buildroot-2015.05.tar.bz2 32 | fi 33 | 34 | if [ ! -f "gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabi.tar.xz" ]; then 35 | wget -c http://releases.linaro.org/14.11/components/toolchain/binaries/arm-linux-gnueabi/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabi.tar.xz 36 | tar Jxvf gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabi.tar.xz 37 | fi 38 | -------------------------------------------------------------------------------- /env.sh: -------------------------------------------------------------------------------- 1 | # toolchains script 2 | export PATH=/home/coding/workspace/arm-2012.09/bin:$PATH 3 | export RTT_ROOT=/home/coding/workspace/rt-thread 4 | export RTT_CC=gcc 5 | export RTT_EXEC_PATH=/home/coding/workspace/arm-2012.09/bin 6 | 7 | # export KDIR=/home/coding/workspace/linux-3.18.16 8 | export KDIR=/home/coding/workspace/buildroot-2015.05/output/build/linux-custom 9 | export PATH=/home/coding/workspace/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabi/bin:$PATH 10 | export CROSS_COMPILE=arm-linux-gnueabi- 11 | export ARCH=arm 12 | export MO_DIR=/home/coding/workspace/buildroot-2015.05/output/target/root 13 | -------------------------------------------------------------------------------- /gemini.sh: -------------------------------------------------------------------------------- 1 | qemu-system-arm -M vexpress-a9 -cpu cortex-a9 -smp cpus=2 -m 256M -kernel zImage -drive file=rootfs.ext2,if=sd -append "mem=248M console=ttyAMA0 root=/dev/mmcblk0" -dtb vexpress-v2p-ca9.dtb -serial vc -serial vc 2 | -------------------------------------------------------------------------------- /linux-apps/Makefile: -------------------------------------------------------------------------------- 1 | CC=arm-linux-gnueabi-gcc 2 | VBUS_USER=../rtloader/vbus 3 | 4 | all: 5 | $(CC) -std=c99 -I $(VBUS_USER) -I . -o vecho vecho.c 6 | 7 | -------------------------------------------------------------------------------- /linux-apps/vecho.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 1 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | #include "rt_vbus_user.h" 18 | 19 | #define handle_error(msg, err) \ 20 | do { perror(msg); exit(err); } while (0) 21 | 22 | #define BUFLEN 1024 23 | char buf[BUFLEN]; 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | int ctlfd = open("/dev/rtvbus", O_RDWR); 28 | if (ctlfd < 0) 29 | handle_error("open error", ctlfd); 30 | 31 | struct rt_vbus_request req; 32 | 33 | req.name = "vecho"; 34 | req.prio = 20; 35 | req.is_server = 0; 36 | req.oflag = O_RDWR; 37 | req.recv_wm.low = 500; 38 | req.recv_wm.high = 1000; 39 | req.post_wm.low = 500; 40 | req.post_wm.high = 1000; 41 | 42 | int rwfd = ioctl(ctlfd, VBUS_IOCREQ, &req); 43 | if (rwfd < 0) 44 | handle_error("ioctl error", rwfd); 45 | 46 | close(ctlfd); 47 | 48 | printf("send: "); 49 | for (int i = 1; i < argc; i++) { 50 | write(rwfd, argv[i], strlen(argv[i])); 51 | write(rwfd, " ", 1); 52 | printf("%s ", argv[i]); 53 | } 54 | write(rwfd, "\n", 1); 55 | printf("\n"); 56 | int len = read(rwfd, buf, sizeof(buf)-1); 57 | buf[len] = '\0'; 58 | printf("recv: %s\n", buf); 59 | 60 | close(rwfd); 61 | exit(0); 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /prepare.sh: -------------------------------------------------------------------------------- 1 | # download RT-Thread git code 2 | # https://github.com/RT-Thread/rt-thread.git 3 | 4 | git clone https://git.coding.net/RT-Thread/rt-thread.git 5 | 6 | # install 32bit environment 7 | sudo apt-get update 8 | sudo apt-get -y install lib32z1 astyle 9 | # prepare toolchains and scons 10 | sudo apt-get -y install scons qemu-system-arm libncurses5-dev zip bc texinfo 11 | 12 | # clone package files repo 13 | if [ ! -d "packages-files" ]; then 14 | git clone https://git.coding.net/RT-Thread/packages-files.git 15 | else 16 | cd packages-files 17 | git pull origin 18 | cd .. 19 | fi 20 | 21 | if [ ! -d "arm-2012.09" ]; then 22 | tar jxvf packages-files/arm-2012.09-63-arm-none-eabi-i686-pc-linux-gnu.tar.bz2 23 | fi 24 | 25 | if [ ! -d "linux-3.18.16" ]; then 26 | tar Jxvf packages-files/linux-3.18.16.tar.xz 27 | cd linux-3.18.16 28 | patch -p1 < ../rtthread_vbus.patch 29 | cd .. 30 | fi 31 | 32 | if [ ! -d "buildroot-2015.05" ]; then 33 | tar jxvf packages-files/buildroot-2015.05.tar.bz2 34 | mkdir -p buildroot-2015.05/dl 35 | cp packages-files/dl/* buildroot-2015.05/dl 36 | fi 37 | 38 | if [ ! -d "gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabi" ]; then 39 | tar Jxvf packages-files/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabi.tar.xz 40 | fi 41 | 42 | -------------------------------------------------------------------------------- /rtloader/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.o.cmd 3 | *.ko 4 | *.ko.cmd 5 | *.mod.c 6 | 7 | Module.symvers 8 | modules.order 9 | 10 | .tmp_versions/ 11 | -------------------------------------------------------------------------------- /rtloader/Makefile: -------------------------------------------------------------------------------- 1 | COMPONENT_VBUS_HDR := $(RTT_ROOT)/components/vbus/share_hdr/ 2 | COMPONENT_VBUS_CONF_HDR := $(RTT_ROOT)/components/vbus/ 3 | 4 | ccflags-y := -I$(COMPONENT_VBUS_HDR) -I$(COMPONENT_VBUS_CONF_HDR) -I$(src) -I$(src)/vbus 5 | 6 | obj-m += rtloader.o 7 | 8 | VBUS_DIR := vbus 9 | include $(src)/$(VBUS_DIR)/Makefile.in 10 | 11 | rtloader-objs := loader.o $(VBUS_OBJS) 12 | -------------------------------------------------------------------------------- /rtloader/build.sh: -------------------------------------------------------------------------------- 1 | make -C $KDIR M=$PWD ARCH=arm 2 | cp rtloader.ko $MO_DIR 3 | -------------------------------------------------------------------------------- /rtloader/loader.c: -------------------------------------------------------------------------------- 1 | /* 2 | * RT-Thread loader 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2013-09-11 Grissiom the first verion 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include 39 | 40 | #include 41 | #include 42 | 43 | #include "linux_driver.h" 44 | 45 | #define BUFF_SZ (4 * 1024) 46 | 47 | static int _do_startup(unsigned long start_addr) 48 | { 49 | extern int vexpress_cpun_start(u32 address, int cpu); 50 | vexpress_cpun_start(start_addr, 1); 51 | 52 | return 0; 53 | } 54 | 55 | int _do_load_fw(const char* filename, 56 | unsigned long base_addr, 57 | size_t mem_size) 58 | { 59 | mm_segment_t oldfs = {0}; 60 | ssize_t len; 61 | unsigned long file_sz; 62 | loff_t pos = 0; 63 | struct file *flp = NULL; 64 | unsigned long buf_ptr = base_addr; 65 | 66 | printk("loading binary file:%s to %08lx....\n", 67 | filename, buf_ptr); 68 | 69 | flp = filp_open(filename, O_RDONLY, S_IRWXU); 70 | if (IS_ERR(flp)) { 71 | printk("rtloader: open file failed. " 72 | "Return 0x%p\n", flp); 73 | return -1; 74 | } 75 | 76 | /* get file size */ 77 | file_sz = vfs_llseek(flp, 0, SEEK_END); 78 | if (file_sz > mem_size) { 79 | printk("rtloader: bin file too big. " 80 | "mem size: 0x%08x, bin file size: %ld (0x%08lx)\n", 81 | mem_size, file_sz, file_sz); 82 | filp_close(flp, NULL); 83 | return -1; 84 | } 85 | printk("rtloader: bin file size: %ld\n", file_sz); 86 | vfs_llseek(flp, 0, SEEK_SET); 87 | 88 | oldfs = get_fs(); 89 | set_fs(get_ds()); 90 | while (file_sz > 0) { 91 | len = vfs_read(flp, (void __user __force*)buf_ptr, BUFF_SZ, &pos); 92 | if (len < 0) { 93 | pr_err("read %08lx error: %d\n", buf_ptr, len); 94 | set_fs(oldfs); 95 | filp_close(flp, NULL); 96 | return -1; 97 | } 98 | file_sz -= len; 99 | buf_ptr += len; 100 | } 101 | set_fs(oldfs); 102 | 103 | printk("done!\n"); 104 | 105 | /* flush RT-Thread memory */ 106 | flush_cache_vmap(base_addr, mem_size); 107 | 108 | return 0; 109 | } 110 | 111 | static void __iomem *out_ring; 112 | 113 | static int __init rtloader_init(void) 114 | { 115 | int ret; 116 | unsigned long va; 117 | 118 | /* No need to cache the code as we don't run it on this CPU. Also, 119 | * nocache means we don't need to flush it as well. */ 120 | // va = ioremap_nocache(RT_BASE_ADDR, RT_MEM_SIZE); 121 | va = __phys_to_virt(0x6FB00000); 122 | _do_load_fw("/root/boot.bin", (unsigned long)va, 128 * 1024); 123 | 124 | va = __phys_to_virt(0x6FC00000); 125 | pr_info("get mapping :%08lx -> %08x, size: %08x\n", 126 | va, RT_BASE_ADDR, RT_MEM_SIZE); 127 | 128 | if (_do_load_fw("/root/rtthread.bin", 129 | (unsigned long)va, 130 | RT_MEM_SIZE) == 0) { 131 | int res; 132 | 133 | /* We have to down the CPU before loading the code because cpu_down 134 | * will flush the cache. It will corrupt the code we just loaded some 135 | * times. */ 136 | ret = cpu_down(1); 137 | /* EBUSY means CPU is already released */ 138 | if (ret && (ret != -EBUSY)) { 139 | pr_err("Can't release cpu1: %d\n", ret); 140 | return -ENOMEM; 141 | } 142 | 143 | res = _do_startup(0x6FB00000); 144 | pr_info("startup return %d\n", res); 145 | 146 | out_ring = (void*)__phys_to_virt(_RT_VBUS_RING_BASE); 147 | res = driver_load(out_ring, out_ring + _RT_VBUS_RING_SZ); 148 | pr_info("driver_load return %d\n", res); 149 | } 150 | 151 | return 0; 152 | } 153 | 154 | static void __exit rtloader_exit(void) 155 | { 156 | driver_unload(); 157 | } 158 | 159 | module_init(rtloader_init); 160 | module_exit(rtloader_exit); 161 | 162 | MODULE_AUTHOR("Grissiom "); 163 | MODULE_DESCRIPTION("RTLOADER"); 164 | MODULE_LICENSE("GPL"); 165 | -------------------------------------------------------------------------------- /rtloader/vbus/Makefile.in: -------------------------------------------------------------------------------- 1 | # User should define VBUS_DIR and setup the ccflags-y before including this file. 2 | # Append $(VBUS_OBJS) to the object lists of your module 3 | 4 | VBUS_OBJS := $(VBUS_DIR)/linux_driver.o $(VBUS_DIR)/vbus_chn0.o $(VBUS_DIR)/vbus_chnx.o $(VBUS_DIR)/prio_queue.o $(VBUS_DIR)/watermark_queue.o 5 | 6 | ifeq ($(CONFIG_ARM_GIC), y) 7 | VBUS_OBJS += $(VBUS_DIR)/gic_emuint.o 8 | else 9 | VBUS_OBJS += $(VBUS_DIR)/aintc_emuint.o 10 | endif 11 | -------------------------------------------------------------------------------- /rtloader/vbus/gic_emuint.c: -------------------------------------------------------------------------------- 1 | /* 2 | * GIC interrupt 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2013-09-11 Grissiom the first verion 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "linux_driver.h" 34 | 35 | void __iomem *_aintc_base; 36 | 37 | void rt_vmm_clear_emuint(unsigned int irqnr) 38 | { 39 | /* Do nothing, SGI is cleared by EOI. */ 40 | } 41 | 42 | void rt_vmm_trigger_emuint(unsigned int irqnr) 43 | { 44 | extern void arch_send_ipi(int cpu, int ipi); 45 | arch_send_ipi(1, irqnr); 46 | } 47 | 48 | int rt_vmm_get_int_offset(void) 49 | { 50 | return 0; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /rtloader/vbus/linux_driver.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RT-Thread/Linux driver 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2013-09-11 Grissiom the first verion 27 | */ 28 | 29 | #ifndef __LINUX_DRIVER_H__ 30 | #define __LINUX_DRIVER_H__ 31 | 32 | #include "rt_vbus_user.h" 33 | 34 | int driver_load(void __iomem *outr, void __iomem *inr); 35 | void driver_unload(void); 36 | 37 | int rt_vbus_connection_ok(unsigned char chnr); 38 | 39 | typedef void (*rt_vbus_callback)(unsigned char chn); 40 | 41 | int rt_vbus_request_chn(struct rt_vbus_request *req, 42 | int is_server, 43 | rt_vbus_callback cb); 44 | void rt_vbus_close_chn(unsigned char); 45 | 46 | int rt_vbus_post(unsigned char id, unsigned char prio, 47 | const void *data, size_t len); 48 | 49 | void rt_vbus_set_post_wm(unsigned char chnr, 50 | unsigned int low, unsigned int high); 51 | void rt_vbus_set_recv_wm(unsigned char chnr, 52 | unsigned int low, unsigned int high); 53 | 54 | struct rt_vbus_data { 55 | size_t size; 56 | struct rt_vbus_data *next; 57 | /* data follows */ 58 | }; 59 | 60 | struct rt_vbus_data* rt_vbus_data_pop(unsigned char chnr); 61 | int rt_vbus_data_empty(unsigned char id); 62 | 63 | void rt_vmm_clear_emuint(unsigned int nr); 64 | void rt_vmm_trigger_emuint(unsigned int irqnr); 65 | int rt_vmm_get_int_offset(void); 66 | 67 | int chn0_load(void); 68 | void chn0_unload(void); 69 | 70 | #define RT_VBUS_USING_FLOW_CONTROL 71 | 72 | #endif /* end of include guard: __LINUX_DRIVER_H__ */ 73 | -------------------------------------------------------------------------------- /rtloader/vbus/prio_queue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * RT-Thread Priority Queue 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2013-09-11 Grissiom the first verion 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "prio_queue.h" 34 | 35 | #define QUE_ITEM_SZ 64 36 | 37 | struct rt_prio_queue_item { 38 | struct rt_prio_queue_item *next; 39 | /* data follows */ 40 | }; 41 | 42 | static void _do_push(struct rt_prio_queue *que, 43 | unsigned char prio, 44 | struct rt_prio_queue_item *item) 45 | { 46 | spin_lock(&que->lock); 47 | if (que->head[prio] == NULL) 48 | { 49 | que->head[prio] = item; 50 | que->bitmap |= 1 << prio; 51 | } 52 | else 53 | { 54 | BUG_ON(!(que->tail[prio])); 55 | que->tail[prio]->next = item; 56 | } 57 | que->tail[prio] = item; 58 | spin_unlock(&que->lock); 59 | } 60 | 61 | static struct rt_prio_queue_item* _do_pop(struct rt_prio_queue *que) 62 | { 63 | int ffs; 64 | struct rt_prio_queue_item *item; 65 | 66 | ffs = __builtin_ffs(que->bitmap); 67 | if (ffs == 0) 68 | return NULL; 69 | ffs--; 70 | 71 | spin_lock(&que->lock); 72 | item = que->head[ffs]; 73 | BUG_ON(!(item)); 74 | 75 | que->head[ffs] = item->next; 76 | if (que->head[ffs] == NULL) 77 | { 78 | que->bitmap &= ~(1 << ffs); 79 | } 80 | spin_unlock(&que->lock); 81 | 82 | return item; 83 | } 84 | 85 | struct rt_prio_queue* rt_prio_queue_create(const char *name, 86 | size_t item_nr, 87 | size_t item_sz) 88 | { 89 | struct rt_prio_queue *que; 90 | 91 | que = kzalloc(sizeof(*que), GFP_KERNEL); 92 | if (!que) 93 | return NULL; 94 | que->pool = kmem_cache_create(name, item_sz, 0, 95 | SLAB_HWCACHE_ALIGN, NULL); 96 | if (!que->pool) { 97 | kfree(que); 98 | return NULL; 99 | } 100 | 101 | que->item_sz = item_sz; 102 | init_waitqueue_head(&que->pop_wait); 103 | init_waitqueue_head(&que->push_wait); 104 | atomic_set(&que->item_avaialble, item_nr); 105 | spin_lock_init(&que->lock); 106 | 107 | return que; 108 | } 109 | 110 | /** Delete the queue. 111 | * 112 | * It could be dangrous and error prone because other process may waiting for 113 | * push/pop on it. If we delete it, they may crash. If you are confident about 114 | * the situation, you can delete the queue any way. 115 | */ 116 | void rt_prio_queue_delete(struct rt_prio_queue *que) 117 | { 118 | struct rt_prio_queue_item *item; 119 | 120 | BUG_ON(waitqueue_active(&que->pop_wait) || 121 | waitqueue_active(&que->push_wait)); 122 | 123 | /* clean up mem cache */ 124 | for (item = _do_pop(que); item; item = _do_pop(que)) { 125 | kmem_cache_free(que->pool, item); 126 | } 127 | kmem_cache_destroy(que->pool); 128 | 129 | /* God bless the processes want to hold the que again. */ 130 | kfree(que); 131 | } 132 | 133 | /** 134 | * return 0 on OK. 135 | */ 136 | int rt_prio_queue_push(struct rt_prio_queue *que, 137 | unsigned char prio, 138 | char *data) 139 | { 140 | int res = 0; 141 | struct rt_prio_queue_item *item; 142 | 143 | if (atomic_dec_return(&que->item_avaialble) < 0) { 144 | DEFINE_WAIT(__wait); 145 | 146 | atomic_inc(&que->item_avaialble); 147 | 148 | for (;;) { 149 | prepare_to_wait(&que->push_wait, &__wait, TASK_INTERRUPTIBLE); 150 | 151 | if (atomic_dec_return(&que->item_avaialble) >= 0) 152 | break; 153 | atomic_inc(&que->item_avaialble); 154 | 155 | if (signal_pending(current)) { 156 | finish_wait(&que->push_wait, &__wait); 157 | res = -ERESTARTSYS; 158 | goto Out; 159 | } 160 | 161 | schedule(); 162 | } 163 | finish_wait(&que->push_wait, &__wait); 164 | } 165 | 166 | item = kmem_cache_alloc(que->pool, GFP_KERNEL); 167 | if (!item) { 168 | res = -ENOMEM; 169 | goto Out; 170 | } 171 | 172 | item->next = NULL; 173 | memcpy(item+1, data, que->item_sz); 174 | 175 | _do_push(que, prio, item); 176 | 177 | wake_up_interruptible(&que->pop_wait); 178 | 179 | Out: 180 | return res; 181 | } 182 | 183 | int rt_prio_queue_pop(struct rt_prio_queue *que, 184 | char *data) 185 | { 186 | int res; 187 | struct rt_prio_queue_item *item; 188 | 189 | res = wait_event_interruptible(que->pop_wait, 190 | (item = _do_pop(que))); 191 | if (res) 192 | goto Out; 193 | 194 | memcpy(data, item+1, que->item_sz); 195 | kmem_cache_free(que->pool, item); 196 | 197 | atomic_inc(&que->item_avaialble); 198 | wake_up_interruptible(&que->push_wait); 199 | 200 | Out: 201 | return res; 202 | } 203 | 204 | int rt_prio_queue_trypop(struct rt_prio_queue *que, 205 | char *data) 206 | { 207 | struct rt_prio_queue_item *item; 208 | 209 | item = _do_pop(que); 210 | if (!item) 211 | return -1; 212 | 213 | memcpy(data, item+1, que->item_sz); 214 | kmem_cache_free(que->pool, item); 215 | 216 | atomic_inc(&que->item_avaialble); 217 | wake_up_interruptible(&que->push_wait); 218 | 219 | return 0; 220 | } 221 | -------------------------------------------------------------------------------- /rtloader/vbus/prio_queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RT-Thread Priority Queue 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2013-09-11 Grissiom the first verion 27 | */ 28 | 29 | #ifndef __PRIO_QUEUE_H__ 30 | #define __PRIO_QUEUE_H__ 31 | 32 | #define RT_PRIO_QUEUE_PRIO_MAX 32 33 | 34 | struct rt_prio_queue_item; 35 | 36 | struct rt_prio_queue { 37 | u32 bitmap; 38 | struct rt_prio_queue_item *head[RT_PRIO_QUEUE_PRIO_MAX]; 39 | struct rt_prio_queue_item *tail[RT_PRIO_QUEUE_PRIO_MAX]; 40 | 41 | size_t item_sz; 42 | 43 | wait_queue_head_t pop_wait, push_wait; 44 | struct kmem_cache *pool; 45 | 46 | atomic_t item_avaialble; 47 | spinlock_t lock; 48 | }; 49 | 50 | struct rt_prio_queue* rt_prio_queue_create(const char *name, 51 | size_t item_nr, 52 | size_t item_sz); 53 | void rt_prio_queue_delete(struct rt_prio_queue *que); 54 | int rt_prio_queue_push(struct rt_prio_queue *que, 55 | unsigned char prio, 56 | char *data); 57 | int rt_prio_queue_pop(struct rt_prio_queue *que, 58 | char *data); 59 | int rt_prio_queue_trypop(struct rt_prio_queue *que, 60 | char *data); 61 | 62 | #endif /* end of include guard: __PRIO_QUEUE_H__ */ 63 | -------------------------------------------------------------------------------- /rtloader/vbus/rt_vbus_user.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RT-Thread/Linux VBUS user header 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2013-09-11 Grissiom the first verion 27 | */ 28 | 29 | #ifndef __RT_VBUS_USER_H__ 30 | #define __RT_VBUS_USER_H__ 31 | 32 | struct rt_vbus_wm_cfg { 33 | unsigned int low, high; 34 | }; 35 | 36 | struct rt_vbus_request { 37 | const char *name; 38 | int is_server; 39 | unsigned char prio; 40 | /* flags of the opened fd */ 41 | int oflag; 42 | struct rt_vbus_wm_cfg recv_wm, post_wm; 43 | }; 44 | 45 | /* find a spare magic in Documentation/ioctl/ioctl-number.txt */ 46 | #define VBUS_IOC_MAGIC 0xE1 47 | #define VBUS_IOCREQ _IOWR(VBUS_IOC_MAGIC, 0xE2, struct rt_vbus_request) 48 | /* Water marks can be controled on the fly. */ 49 | #define VBUS_IOCRECV_WM _IOWR(VBUS_IOC_MAGIC, 0xE3, struct rt_vbus_request) 50 | #define VBUS_IOCPOST_WM _IOWR(VBUS_IOC_MAGIC, 0xE4, struct rt_vbus_request) 51 | 52 | /* keep consistent with beaglebone/components/vmm/share_hdr/rtt_api.h */ 53 | #define RT_VBUS_SHELL_DEV_NAME "vbser0" 54 | #define RT_VBUS_RFS_DEV_NAME "rfs" 55 | 56 | #endif /* end of include guard: __RT_VBUS_USER_H__ */ 57 | -------------------------------------------------------------------------------- /rtloader/vbus/vbus_chn0.c: -------------------------------------------------------------------------------- 1 | /* 2 | * RT-Thread/Linux VBUS channel 0 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2013-09-11 Grissiom the first verion 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include 39 | 40 | #include "linux_driver.h" 41 | #include "vbus_chnx.h" 42 | 43 | static struct cdev _chn0_dev; 44 | static atomic_t _device_count = ATOMIC_INIT(1); 45 | 46 | static int _open(struct inode *inode, struct file *filp) 47 | { 48 | if (atomic_dec_return(&_device_count) < 0) { 49 | atomic_inc(&_device_count); 50 | return -EBUSY; 51 | } 52 | 53 | filp->private_data = &_chn0_dev; 54 | return 0; 55 | } 56 | 57 | static int _release(struct inode *inode, struct file *filp) 58 | { 59 | BUG_ON(atomic_read(&_device_count) != 0); 60 | 61 | atomic_inc(&_device_count); 62 | 63 | return 0; 64 | } 65 | 66 | static long _ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 67 | { 68 | int chnr, nlen; 69 | char chname[RT_VBUS_CHN_NAME_MAX]; 70 | int res = -ENOTTY; 71 | struct rt_vbus_request req; 72 | 73 | switch (cmd) { 74 | case VBUS_IOCREQ: 75 | if (copy_from_user(&req, (struct rt_vbus_request*)arg, 76 | sizeof(req))) 77 | return -EFAULT; 78 | 79 | nlen = strnlen_user(req.name, sizeof(chname)); 80 | res = copy_from_user(chname, req.name, nlen); 81 | if (res < 0) { 82 | return -EFAULT; 83 | } 84 | /* Let the name point to kernel space. */ 85 | req.name = chname; 86 | 87 | if (req.recv_wm.low > req.recv_wm.high) 88 | return -EINVAL; 89 | if (req.post_wm.low > req.post_wm.high) 90 | return -EINVAL; 91 | chnr = rt_vbus_request_chn(&req, 92 | !!req.is_server, 93 | vbus_chnx_callback); 94 | if (chnr < 0) 95 | return chnr; 96 | res = vbus_chnx_get_fd(chnr, req.prio, req.oflag); 97 | if (res < 0) { 98 | rt_vbus_close_chn(chnr); 99 | return res; 100 | } 101 | default: 102 | break; 103 | }; 104 | return res; 105 | } 106 | 107 | static struct file_operations _chn0_ops = { 108 | .owner = THIS_MODULE, 109 | .open = _open, 110 | .release = _release, 111 | .unlocked_ioctl = _ioctl, 112 | }; 113 | 114 | static struct class *_chn0_cls; 115 | 116 | int chn0_load(void) 117 | { 118 | int res; 119 | 120 | cdev_init(&_chn0_dev, &_chn0_ops); 121 | _chn0_dev.owner = THIS_MODULE; 122 | alloc_chrdev_region(&_chn0_dev.dev, 0, 1, "vbus_ctl"); 123 | 124 | res = cdev_add(&_chn0_dev, _chn0_dev.dev, 1); 125 | if (res) { 126 | pr_err("err adding chn0 device: %d\n", res); 127 | unregister_chrdev_region(_chn0_dev.dev, 1); 128 | return res; 129 | } 130 | 131 | pr_info("chn0 dev nr: %d\n", MAJOR(_chn0_dev.dev)); 132 | 133 | _chn0_cls = class_create(THIS_MODULE, "rtvbus"); 134 | if (IS_ERR(_chn0_cls)) { 135 | pr_err("err creating chn0 device class: %p\n", _chn0_cls); 136 | _chn0_cls = NULL; 137 | } else { 138 | struct device *p = device_create(_chn0_cls, NULL, 139 | MKDEV(MAJOR(_chn0_dev.dev), 0), 140 | NULL, "rtvbus"); 141 | if (IS_ERR(p)) { 142 | pr_err("err creating chn0 device node: %p\n", p); 143 | pr_err("You have create it with " 144 | "`mknod /dev/rtvbus c %d 0`\n", 145 | MAJOR(_chn0_dev.dev)); 146 | class_destroy(_chn0_cls); 147 | _chn0_cls = NULL; 148 | } 149 | } 150 | 151 | return vbus_chnx_init(); 152 | } 153 | 154 | void chn0_unload(void) 155 | { 156 | unregister_chrdev_region(_chn0_dev.dev, 1); 157 | cdev_del(&_chn0_dev); 158 | if (_chn0_cls) { 159 | device_destroy(_chn0_cls, MKDEV(MAJOR(_chn0_dev.dev), 0)); 160 | class_destroy(_chn0_cls); 161 | } 162 | pr_info("unload chn0\n"); 163 | } 164 | -------------------------------------------------------------------------------- /rtloader/vbus/vbus_chnx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * VMM Bus channel files 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2013-09-11 Grissiom the first verion 27 | */ 28 | 29 | /* Inspired by the fs/timerfd.c in the Linux kernel 30 | * 31 | * All we need is a file associated with ops. That's all. 32 | */ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include 47 | 48 | #include "linux_driver.h" 49 | 50 | struct vbus_chnx_ctx { 51 | unsigned char prio; 52 | struct rt_vbus_data *datap; 53 | size_t pos; 54 | int fd; 55 | wait_queue_head_t wait; 56 | }; 57 | 58 | static struct vbus_chnx_ctx _ctxs[RT_VBUS_CHANNEL_NR]; 59 | 60 | static int vbus_chnx_open(struct inode *inode, struct file *filp) 61 | { 62 | printk("chx: try to open inode %p, filp %p\n", inode, filp); 63 | return 0; 64 | } 65 | 66 | static int vbus_chnx_release(struct inode *inode, struct file *filp) 67 | { 68 | unsigned char chnr = (unsigned int)filp->private_data; 69 | 70 | /*pr_info("chx: release chnr %d, fd %d\n", chnr, _ctxs[chnr].fd);*/ 71 | 72 | rt_vbus_close_chn(chnr); 73 | 74 | return 0; 75 | } 76 | 77 | static ssize_t vbus_chnx_write(struct file *filp, 78 | const char __user *buf, size_t size, 79 | loff_t *offp) 80 | { 81 | int res; 82 | unsigned long chnr = (unsigned long)(filp->private_data); 83 | char *kbuf = kmalloc(size, GFP_KERNEL); 84 | 85 | if (!kbuf) 86 | return -ENOMEM; 87 | 88 | res = copy_from_user(kbuf, buf, size); 89 | if (res < 0) 90 | return -EFAULT; 91 | 92 | res = rt_vbus_post(chnr, _ctxs[chnr].prio, kbuf, size); 93 | 94 | kfree(kbuf); 95 | 96 | /* We simplified the things by treating the signal as error. */ 97 | if (unlikely(res)) { 98 | /* Make sure the error is returned as negative values. */ 99 | if (res < 0) 100 | return res; 101 | else 102 | return -res; 103 | } else 104 | return size; 105 | } 106 | 107 | static ssize_t vbus_chnx_read(struct file *filp, 108 | char __user *buf, size_t size, 109 | loff_t *offp) 110 | { 111 | unsigned long chnr = (unsigned long)filp->private_data; 112 | struct vbus_chnx_ctx *ctx = &_ctxs[chnr]; 113 | size_t outsz = 0; 114 | 115 | if (ctx->datap == NULL) { 116 | ctx->datap = rt_vbus_data_pop(chnr); 117 | ctx->pos = 0; 118 | } 119 | else if (ctx->pos == ctx->datap->size) { 120 | kfree(ctx->datap); 121 | ctx->datap = rt_vbus_data_pop(chnr); 122 | ctx->pos = 0; 123 | } 124 | 125 | if (ctx->datap == NULL) { 126 | int err; 127 | 128 | if (!rt_vbus_connection_ok(chnr)) 129 | return 0; 130 | 131 | if (filp->f_flags & O_NONBLOCK) 132 | return -EAGAIN; 133 | 134 | err = wait_event_interruptible(_ctxs[chnr].wait, 135 | !rt_vbus_data_empty(chnr) || 136 | !rt_vbus_connection_ok(chnr)); 137 | if (err) 138 | return err; 139 | 140 | ctx->datap = rt_vbus_data_pop(chnr); 141 | if (ctx->datap == NULL) { 142 | return 0; 143 | } 144 | ctx->pos = 0; 145 | } 146 | 147 | if (IS_ERR(ctx->datap)) { 148 | ssize_t err = PTR_ERR(ctx->datap); 149 | /* Cleanup datap so we don't crash if we access it again. */ 150 | ctx->datap = NULL; 151 | return err; 152 | } 153 | 154 | while (ctx->datap) { 155 | size_t cpysz; 156 | 157 | if (size - outsz > ctx->datap->size - ctx->pos) 158 | cpysz = ctx->datap->size - ctx->pos; 159 | else 160 | cpysz = size - outsz; 161 | 162 | if (copy_to_user(buf + outsz, 163 | ((char*)(ctx->datap+1)) + ctx->pos, 164 | cpysz)) 165 | return -EFAULT; 166 | ctx->pos += cpysz; 167 | 168 | outsz += cpysz; 169 | if (outsz == size) { 170 | return outsz; 171 | } 172 | BUG_ON(outsz > size); 173 | 174 | /* Free the old, get the new. */ 175 | kfree(ctx->datap); 176 | ctx->datap = rt_vbus_data_pop(chnr); 177 | if (IS_ERR(ctx->datap)) { 178 | ctx->datap = NULL; 179 | } 180 | ctx->pos = 0; 181 | /*pr_info("get other data %p, %d copied\n", ctx->datap, outsz);*/ 182 | } 183 | return outsz; 184 | } 185 | 186 | static unsigned int vbus_chnx_poll(struct file *filp, poll_table *wait) 187 | { 188 | unsigned int mask = 0; 189 | unsigned long chnr = (unsigned long)filp->private_data; 190 | 191 | poll_wait(filp, &_ctxs[chnr].wait, wait); 192 | 193 | if (_ctxs[chnr].datap != NULL || !rt_vbus_data_empty(chnr)) 194 | mask |= POLLIN | POLLRDNORM; 195 | if (!rt_vbus_connection_ok(chnr)) 196 | mask |= POLLHUP; 197 | 198 | return mask; 199 | } 200 | 201 | static long vbus_chnx_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 202 | { 203 | int res = -ENOTTY; 204 | 205 | switch (cmd) { 206 | #ifdef RT_VBUS_USING_FLOW_CONTROL 207 | case VBUS_IOCRECV_WM: { 208 | struct rt_vbus_wm_cfg cfg; 209 | unsigned long chnr = (unsigned long)filp->private_data; 210 | 211 | if (copy_from_user(&cfg, (struct rt_vbus_wm_cfg*)arg, 212 | sizeof(cfg))) 213 | return -EFAULT; 214 | rt_vbus_set_recv_wm(chnr, cfg.low, cfg.high); 215 | return 0; 216 | 217 | } 218 | break; 219 | case VBUS_IOCPOST_WM: { 220 | struct rt_vbus_wm_cfg cfg; 221 | unsigned long chnr = (unsigned long)filp->private_data; 222 | 223 | if (copy_from_user(&cfg, (struct rt_vbus_wm_cfg*)arg, 224 | sizeof(cfg))) 225 | return -EFAULT; 226 | rt_vbus_set_post_wm(chnr, cfg.low, cfg.high); 227 | return 0; 228 | 229 | } 230 | break; 231 | #endif 232 | default: 233 | break; 234 | }; 235 | return res; 236 | } 237 | 238 | static const struct file_operations vbus_chnx_fops = { 239 | .owner = THIS_MODULE, 240 | .open = vbus_chnx_open, 241 | .release = vbus_chnx_release, 242 | .read = vbus_chnx_read, 243 | .write = vbus_chnx_write, 244 | .llseek = noop_llseek, 245 | .poll = vbus_chnx_poll, 246 | .unlocked_ioctl = vbus_chnx_ioctl, 247 | }; 248 | 249 | int vbus_chnx_init(void) 250 | { 251 | int i; 252 | 253 | for (i = 0; i < ARRAY_SIZE(_ctxs); i++) { 254 | init_waitqueue_head(&_ctxs[i].wait); 255 | } 256 | return 0; 257 | } 258 | 259 | /* get a file descriptor corresponding to the channel 260 | */ 261 | int vbus_chnx_get_fd(unsigned char chnr, 262 | unsigned char prio, 263 | int oflag) 264 | { 265 | /* supress compiler waring: cast to pointer from integer of different 266 | * size */ 267 | unsigned long lchnr = chnr; 268 | int fd = anon_inode_getfd("[vbus_chnx]", &vbus_chnx_fops, 269 | (void*)lchnr, oflag); 270 | if (fd > 0) { 271 | if (prio == 0) 272 | prio = 1; 273 | else if (prio > 255) 274 | prio = 255; 275 | _ctxs[chnr].prio = prio; 276 | _ctxs[chnr].datap = NULL; 277 | _ctxs[chnr].pos = 0; 278 | } 279 | _ctxs[chnr].fd = fd; 280 | 281 | pr_info("get fd: %d, prio: %d\n", fd, prio); 282 | 283 | return fd; 284 | } 285 | 286 | void vbus_chnx_callback(unsigned char chnr) 287 | { 288 | BUG_ON(chnr == 0 || chnr >= RT_VBUS_CHANNEL_NR); 289 | 290 | wake_up_interruptible(&_ctxs[chnr].wait); 291 | } 292 | 293 | -------------------------------------------------------------------------------- /rtloader/vbus/vbus_chnx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * VMM Bus channel files 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2013-09-11 Grissiom the first verion 27 | */ 28 | 29 | #ifndef __VBUS_CHNX_H__ 30 | #define __VBUS_CHNX_H__ 31 | 32 | int vbus_chnx_init(void); 33 | int vbus_chnx_get_fd(unsigned char chnr, 34 | unsigned char prio, 35 | int oflag); 36 | 37 | void vbus_chnx_callback(unsigned char); 38 | 39 | #endif /* end of include guard: __VBUS_CHNX_H__ */ 40 | -------------------------------------------------------------------------------- /rtloader/vbus/watermark_queue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Thread queue with water mark 3 | * 4 | * COPYRIGHT (C) 2014, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2014-05-19 Grissiom first version 27 | */ 28 | 29 | #include 30 | #include 31 | 32 | #include "watermark_queue.h" 33 | 34 | void rt_wm_que_set_mark(struct rt_watermark_queue *wg, 35 | unsigned int low, unsigned int high) 36 | { 37 | BUG_ON(low > high); 38 | 39 | wg->high_mark = high; 40 | wg->low_mark = low; 41 | } 42 | 43 | void rt_wm_que_init(struct rt_watermark_queue *wg, 44 | unsigned int low, unsigned int high) 45 | { 46 | rt_wm_que_set_mark(wg, low, high); 47 | init_waitqueue_head(&wg->waitq); 48 | wg->level = 0; 49 | spin_lock_init(&wg->lock); 50 | } 51 | 52 | void rt_wm_que_dump(struct rt_watermark_queue *wg) 53 | { 54 | pr_info("wg %p: low: %d, high: %d, cur: %d\n", 55 | wg, wg->low_mark, wg->high_mark, wg->level); 56 | } 57 | -------------------------------------------------------------------------------- /rtloader/vbus/watermark_queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Thread queue with water mark 3 | * 4 | * COPYRIGHT (C) 2014, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2014-04-16 Grissiom first version 27 | */ 28 | 29 | struct rt_watermark_queue 30 | { 31 | /* Current water level. */ 32 | unsigned int level; 33 | unsigned int high_mark; 34 | unsigned int low_mark; 35 | wait_queue_head_t waitq; 36 | spinlock_t lock; 37 | }; 38 | 39 | /** Init the struct rt_watermark_queue. 40 | */ 41 | void rt_wm_que_init(struct rt_watermark_queue *wg, 42 | unsigned int low, unsigned int high); 43 | void rt_wm_que_set_mark(struct rt_watermark_queue *wg, 44 | unsigned int low, unsigned int high); 45 | void rt_wm_que_dump(struct rt_watermark_queue *wg); 46 | 47 | /* Water marks are often used in performance critical places. Benchmark shows 48 | * inlining functions will have 10% performance gain in some situation(for 49 | * example, VBus). So keep the inc/dec compact and inline. */ 50 | 51 | /** Increase the water level. 52 | * 53 | * It should be called in the thread that want to raise the water level. If the 54 | * current level is above the high mark, the thread will be suspended up to 55 | */ 56 | static inline int rt_wm_que_inc(struct rt_watermark_queue *wg) 57 | { 58 | spin_lock(&wg->lock); 59 | 60 | if (wg->level > wg->high_mark) { 61 | DEFINE_WAIT(__wait); 62 | 63 | for (;;) { 64 | prepare_to_wait(&wg->waitq, 65 | &__wait, 66 | TASK_INTERRUPTIBLE); 67 | 68 | if (wg->level <= wg->high_mark) 69 | break; 70 | 71 | if (signal_pending(current)) { 72 | finish_wait(&wg->waitq, &__wait); 73 | spin_unlock(&wg->lock); 74 | return -ERESTARTSYS; 75 | } 76 | 77 | /* Give other thread the chance to change th water 78 | * level. */ 79 | spin_unlock(&wg->lock); 80 | schedule(); 81 | spin_lock(&wg->lock); 82 | } 83 | finish_wait(&wg->waitq, &__wait); 84 | } 85 | 86 | wg->level++; 87 | if (wg->level == 0) 88 | wg->level = -1; 89 | spin_unlock(&wg->lock); 90 | 91 | return 0; 92 | } 93 | 94 | /** Decrease the water level. 95 | * 96 | * It should be called by the consumer that drain the water out. If the water 97 | * level reached low mark, all the thread suspended in this queue will be waken 98 | * up. It's safe to call this function in interrupt context. 99 | */ 100 | static inline void rt_wm_que_dec(struct rt_watermark_queue *wg) 101 | { 102 | spin_lock(&wg->lock); 103 | 104 | if (wg->level == 0) { 105 | spin_unlock(&wg->lock); 106 | return; 107 | } 108 | 109 | wg->level--; 110 | if (wg->level == wg->low_mark) { 111 | /* There should be spaces between the low mark and high mark, so it's 112 | * safe to resume all the threads. */ 113 | spin_unlock(&wg->lock); 114 | wake_up_interruptible_all(&wg->waitq); 115 | return; 116 | } 117 | spin_unlock(&wg->lock); 118 | } 119 | -------------------------------------------------------------------------------- /rtloader/vbus_conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RT-Thread VBUS configuration 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2013-09-11 Grissiom the first verion 27 | */ 28 | 29 | #ifndef VBUS_CONFIG_H__ 30 | #define VBUS_CONFIG_H__ 31 | 32 | /* This is configures where the rings are located. */ 33 | 34 | #define _RT_VBUS_RING_BASE (0x70000000 - 8 * 1024 * 1024) 35 | #define _RT_VBUS_RING_SZ (2 * 1024 * 1024) 36 | 37 | #define RT_VBUS_OUT_RING ((struct rt_vbus_ring*)(_RT_VBUS_RING_BASE)) 38 | #define RT_VBUS_IN_RING ((struct rt_vbus_ring*)(_RT_VBUS_RING_BASE + _RT_VBUS_RING_SZ)) 39 | 40 | #define RT_VBUS_GUEST_VIRQ 14 41 | #define RT_VBUS_HOST_VIRQ 15 42 | 43 | #define RT_VBUS_SHELL_DEV_NAME "vbser0" 44 | #define RT_VBUS_RFS_DEV_NAME "rfs" 45 | 46 | #define RT_BASE_ADDR 0x6FC00000 47 | #define RT_MEM_SIZE 0x400000 48 | 49 | /* Number of blocks in VBus. The total size of VBus is 50 | * RT_VMM_RB_BLK_NR * 64byte * 2. */ 51 | #define RT_VMM_RB_BLK_NR (_RT_VBUS_RING_SZ / 64 - 1) 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /rtloader/vbus_layout.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RT-Thread VBUS layout configuration 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2013-09-11 Grissiom the first verion 27 | */ 28 | 29 | #ifndef VBUS_LAYOUT_H__ 30 | #define VBUS_LAYOUT_H__ 31 | 32 | #include "vbus_conf.h" 33 | 34 | #endif /* end of include guard: __VBUS_LAYOUT_H__ */ 35 | -------------------------------------------------------------------------------- /rtthread_vbus.patch: -------------------------------------------------------------------------------- 1 | Only in linux/arch/arm/include: generated 2 | diff -ur linux-3.18.16/arch/arm/kernel/smp.c linux/arch/arm/kernel/smp.c 3 | --- linux-3.18.16/arch/arm/kernel/smp.c 2015-06-15 00:19:31.000000000 +0800 4 | +++ linux/arch/arm/kernel/smp.c 2015-06-25 14:51:08.940994975 +0800 5 | @@ -62,6 +62,8 @@ 6 | * boot "holding pen" 7 | */ 8 | volatile int pen_release = -1; 9 | +typedef int (*smp_ipi_handler_t)(int irq, void *devid); 10 | +static smp_ipi_handler_t _smp_ipi_handler = NULL; 11 | 12 | enum ipi_msg_type { 13 | IPI_WAKEUP, 14 | @@ -464,6 +466,12 @@ 15 | __smp_cross_call(target, ipinr); 16 | } 17 | 18 | +void smp_set_ipi_handler(smp_ipi_handler_t handler) 19 | +{ 20 | + _smp_ipi_handler = handler; 21 | +} 22 | +EXPORT_SYMBOL(smp_set_ipi_handler); 23 | + 24 | void show_ipi_list(struct seq_file *p, int prec) 25 | { 26 | unsigned int cpu, i; 27 | @@ -505,6 +513,12 @@ 28 | smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); 29 | } 30 | 31 | +void arch_send_ipi(int cpu, int ipi) 32 | +{ 33 | + smp_cross_call(cpumask_of(cpu), ipi); 34 | +} 35 | +EXPORT_SYMBOL(arch_send_ipi); 36 | + 37 | #ifdef CONFIG_IRQ_WORK 38 | void arch_irq_work_raise(void) 39 | { 40 | @@ -624,8 +638,15 @@ 41 | break; 42 | 43 | default: 44 | - printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", 45 | - cpu, ipinr); 46 | + if (_smp_ipi_handler != NULL) 47 | + { 48 | + irq_enter(); 49 | + _smp_ipi_handler(ipinr, NULL); 50 | + irq_exit(); 51 | + } 52 | + 53 | + // printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", 54 | + // cpu, ipinr); 55 | break; 56 | } 57 | 58 | diff -ur linux-3.18.16/arch/arm/mach-vexpress/hotplug.c linux/arch/arm/mach-vexpress/hotplug.c 59 | --- linux-3.18.16/arch/arm/mach-vexpress/hotplug.c 2015-06-15 00:19:31.000000000 +0800 60 | +++ linux/arch/arm/mach-vexpress/hotplug.c 2015-06-25 14:25:50.624938623 +0800 61 | @@ -14,6 +14,7 @@ 62 | 63 | #include 64 | #include 65 | +#include 66 | 67 | static inline void cpu_enter_lowpower(void) 68 | { 69 | @@ -87,8 +88,15 @@ 70 | */ 71 | void __ref vexpress_cpu_die(unsigned int cpu) 72 | { 73 | + extern u32 vexpress_flags_get(void); 74 | + typedef void (*func_t)(void); 75 | + 76 | + u32 boot_addr; 77 | int spurious = 0; 78 | 79 | + boot_addr = vexpress_flags_get(); 80 | + pen_release = cpu_logical_map(cpu); 81 | + 82 | /* 83 | * we're ready for shutdown now, so do it 84 | */ 85 | @@ -100,6 +108,18 @@ 86 | * coherency, and then restore interrupts 87 | */ 88 | cpu_leave_lowpower(); 89 | + pr_info("0x%08x - 0x%08x\n", boot_addr, vexpress_flags_get()); 90 | + 91 | + //if (boot_addr != vexpress_flags_get()) 92 | + { 93 | + func_t func; 94 | + 95 | + pr_info("come back from die!\n"); 96 | + func = (func_t)__phys_to_virt(0x6FB00000); 97 | + 98 | + asm volatile(" cpsid i\n" :::); 99 | + func(); 100 | + } 101 | 102 | if (spurious) 103 | pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); 104 | diff -ur linux-3.18.16/arch/arm/mach-vexpress/platsmp.c linux/arch/arm/mach-vexpress/platsmp.c 105 | --- linux-3.18.16/arch/arm/mach-vexpress/platsmp.c 2015-06-15 00:19:31.000000000 +0800 106 | +++ linux/arch/arm/mach-vexpress/platsmp.c 2015-06-25 14:26:12.880939449 +0800 107 | @@ -25,6 +25,20 @@ 108 | 109 | #include "core.h" 110 | 111 | +int vexpress_cpun_start(u32 address, int cpu) 112 | +{ 113 | + extern u32 vexpress_flags_get(void); 114 | + 115 | + vexpress_flags_set((address)); 116 | + flush_cache_all(); 117 | + smp_wmb(); 118 | + 119 | + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 120 | + 121 | + return 0; 122 | +} 123 | +EXPORT_SYMBOL(vexpress_cpun_start); 124 | + 125 | /* 126 | * Initialise the CPU possible map early - this describes the CPUs 127 | * which may be present or become present in the system. 128 | diff -ur linux-3.18.16/arch/arm/mm/init.c linux/arch/arm/mm/init.c 129 | --- linux-3.18.16/arch/arm/mm/init.c 2015-06-15 00:19:31.000000000 +0800 130 | +++ linux/arch/arm/mm/init.c 2015-06-25 14:30:29.412948970 +0800 131 | @@ -310,6 +310,10 @@ 132 | } 133 | #endif 134 | 135 | + /* reserve RT-Thread space */ 136 | + { 137 | + memblock_reserve(0x6F800000, 8 * 1024 * 1024); 138 | + } 139 | arm_mm_memblock_reserve(); 140 | 141 | /* reserve any platform specific memblock areas */ 142 | diff -ur linux-3.18.16/arch/arm/mm/mmu.c linux/arch/arm/mm/mmu.c 143 | --- linux-3.18.16/arch/arm/mm/mmu.c 2015-06-15 00:19:31.000000000 +0800 144 | +++ linux/arch/arm/mm/mmu.c 2015-06-25 14:30:02.556947973 +0800 145 | @@ -1299,6 +1299,19 @@ 146 | map.type = MT_LOW_VECTORS; 147 | create_mapping(&map); 148 | 149 | + /* create a executable mapping */ 150 | + { 151 | + #define RTT_BASE 0x6F800000 152 | + #define RTT_SIZE (8 * 1024 * 1024) 153 | + 154 | + map.pfn = __phys_to_pfn(RTT_BASE); 155 | + map.virtual = __phys_to_virt(RTT_BASE); 156 | + map.length = RTT_SIZE; 157 | + map.type = MT_MEMORY_RWX; 158 | + 159 | + create_mapping(&map); 160 | + } 161 | + 162 | /* 163 | * Ask the machine support to map in the statically mapped devices. 164 | */ 165 | diff -ur linux-3.18.16/drivers/mfd/vexpress-sysreg.c linux/drivers/mfd/vexpress-sysreg.c 166 | --- linux-3.18.16/drivers/mfd/vexpress-sysreg.c 2015-06-15 00:19:31.000000000 +0800 167 | +++ linux/drivers/mfd/vexpress-sysreg.c 2015-06-23 17:36:43.558950261 +0800 168 | @@ -84,6 +84,15 @@ 169 | writel(data, vexpress_sysreg_base() + SYS_FLAGSSET); 170 | } 171 | 172 | +u32 vexpress_flags_get(void) 173 | +{ 174 | + u32 value; 175 | + 176 | + value = readl(vexpress_sysreg_base() + SYS_FLAGSSET); 177 | + 178 | + return value; 179 | +} 180 | + 181 | unsigned int vexpress_get_mci_cardin(struct device *dev) 182 | { 183 | return readl(vexpress_sysreg_base() + SYS_MCI) & SYS_MCI_CARDIN; 184 | -------------------------------------------------------------------------------- /vexpress/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | rt-thread 3 | *.pyc 4 | *.o 5 | *~ 6 | *.map 7 | *.bin 8 | .sconsign.dblite 9 | 10 | -------------------------------------------------------------------------------- /vexpress/SConscript: -------------------------------------------------------------------------------- 1 | # for module compiling 2 | import os 3 | Import('RTT_ROOT') 4 | 5 | cwd = str(Dir('#')) 6 | objs = [] 7 | list = os.listdir(cwd) 8 | 9 | for d in list: 10 | path = os.path.join(cwd, d) 11 | if os.path.isfile(os.path.join(path, 'SConscript')): 12 | objs = objs + SConscript(os.path.join(d, 'SConscript')) 13 | 14 | Return('objs') 15 | -------------------------------------------------------------------------------- /vexpress/SConstruct: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import rtconfig 4 | 5 | if os.getenv('RTT_ROOT'): 6 | RTT_ROOT = os.getenv('RTT_ROOT') 7 | else: 8 | RTT_ROOT = os.path.normpath(os.getcwd() + '/rt-thread') 9 | 10 | sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] 11 | from building import * 12 | 13 | TARGET = 'rtthread-vexpress.' + rtconfig.TARGET_EXT 14 | 15 | env = Environment(tools = ['mingw'], 16 | AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, 17 | CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, 18 | AR = rtconfig.AR, ARFLAGS = '-rc', 19 | LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) 20 | env.PrependENVPath('PATH', rtconfig.EXEC_PATH) 21 | 22 | Export('RTT_ROOT') 23 | Export('rtconfig') 24 | 25 | # prepare building environment 26 | objs = PrepareBuilding(env, RTT_ROOT,has_libcpu=True) 27 | 28 | # make a building 29 | DoBuilding(TARGET, objs) 30 | -------------------------------------------------------------------------------- /vexpress/applications/SConscript: -------------------------------------------------------------------------------- 1 | Import('RTT_ROOT') 2 | Import('rtconfig') 3 | from building import * 4 | 5 | cwd = os.path.join(str(Dir('#')), 'applications') 6 | src = Glob('*.c') 7 | CPPPATH = [cwd, str(Dir('#'))] 8 | 9 | group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) 10 | 11 | Return('group') 12 | -------------------------------------------------------------------------------- /vexpress/applications/application.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : application.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2012, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2012-11-20 Bernard the first version 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | void init_thread(void* parameter) 19 | { 20 | rt_components_init(); 21 | } 22 | 23 | int rt_application_init() 24 | { 25 | rt_thread_t tid; 26 | 27 | tid = rt_thread_create("init", init_thread, RT_NULL, 28 | 1024, RT_THREAD_PRIORITY_MAX/3, 10); 29 | if (tid != RT_NULL) rt_thread_startup(tid); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /vexpress/applications/startup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : startup.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2006, RT-Thread Develop Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2012-12-05 Bernard the first version 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | extern int rt_application_init(void); 21 | extern void rt_hw_board_init(void); 22 | 23 | /** 24 | * This function will startup RT-Thread RTOS. 25 | */ 26 | void rtthread_startup(void) 27 | { 28 | /* initialzie hardware interrupt */ 29 | rt_hw_interrupt_init(); 30 | 31 | /* initialize board */ 32 | rt_hw_board_init(); 33 | 34 | /* show RT-Thread version */ 35 | rt_show_version(); 36 | 37 | /* initialize memory system */ 38 | #ifdef RT_USING_HEAP 39 | rt_system_heap_init(HEAP_BEGIN, HEAP_END); 40 | #endif 41 | 42 | /* initialize scheduler system */ 43 | rt_system_scheduler_init(); 44 | 45 | /* initialize timer and soft timer thread */ 46 | rt_system_timer_init(); 47 | rt_system_timer_thread_init(); 48 | 49 | /* initialize application */ 50 | rt_application_init(); 51 | 52 | /* initialize idle thread */ 53 | rt_thread_idle_init(); 54 | 55 | /* start scheduler */ 56 | rt_system_scheduler_start(); 57 | 58 | /* never reach here */ 59 | return ; 60 | } 61 | 62 | int main(void) 63 | { 64 | /* disable interrupt first */ 65 | rt_hw_interrupt_disable(); 66 | 67 | /* invoke rtthread_startup */ 68 | rtthread_startup(); 69 | 70 | return 0; 71 | } 72 | 73 | -------------------------------------------------------------------------------- /vexpress/applications/vbus_echo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #define BUFLEN 1024 8 | static char buf[BUFLEN]; 9 | 10 | static void _vbus_on_tx_cmp(void *p) 11 | { 12 | struct rt_completion *cmp = p; 13 | 14 | rt_completion_done(cmp); 15 | } 16 | 17 | static rt_size_t _vbus_write_sync(rt_device_t dev, void *buf, rt_size_t len) 18 | { 19 | rt_size_t sd; 20 | struct rt_completion cmp; 21 | struct rt_vbus_dev_liscfg liscfg; 22 | 23 | rt_completion_init(&cmp); 24 | liscfg.event = RT_VBUS_EVENT_ID_TX; 25 | liscfg.listener = _vbus_on_tx_cmp; 26 | liscfg.ctx = &cmp; 27 | 28 | rt_device_control(dev, VBUS_IOC_LISCFG, &liscfg); 29 | sd = rt_device_write(dev, 0, buf, len); 30 | 31 | rt_completion_wait(&cmp, RT_WAITING_FOREVER); 32 | 33 | return sd; 34 | } 35 | 36 | static void _rev_str(char *buf, rt_size_t len) 37 | { 38 | char tmp; 39 | rt_size_t i, mid; 40 | 41 | RT_ASSERT(buf); 42 | 43 | if (!len) 44 | return; 45 | 46 | mid = len / 2; 47 | for (i = 0; i < mid; i++) 48 | { 49 | tmp = buf[i]; 50 | buf[i] = buf[len - 1 - i]; 51 | buf[len - 1 - i] = tmp; 52 | } 53 | } 54 | 55 | static void _test_write(void *devname) 56 | { 57 | int i; 58 | rt_device_t dev; 59 | 60 | dev = rt_device_find(devname); 61 | 62 | if (!dev) 63 | { 64 | rt_kprintf("could not find %s\n", devname); 65 | return; 66 | } 67 | 68 | again: 69 | i = rt_device_open(dev, RT_DEVICE_OFLAG_RDWR); 70 | if (i) 71 | { 72 | rt_kprintf("open dev err:%d\n", i); 73 | return; 74 | } 75 | 76 | for (i = 0; i < sizeof(buf) - 1;i++) 77 | { 78 | int len; 79 | 80 | len = rt_device_read(dev, 0, buf + i, 1); 81 | if (len != 1 || buf[i] == '\n') 82 | break; 83 | } 84 | buf[i] = '\0'; 85 | rt_kprintf("recv: %s\n", buf); 86 | /* Don't swap the \n. */ 87 | _rev_str(buf, i - 1); 88 | /* Don't write the \0. */ 89 | rt_kprintf("write: %s\n", buf); 90 | _vbus_write_sync(dev, buf, i - 1); 91 | 92 | rt_device_close(dev); 93 | goto again; 94 | } 95 | 96 | int vser_echo_init(void) 97 | { 98 | rt_thread_t tid; 99 | 100 | tid = rt_thread_create("vecho", _test_write, "vecho", 101 | 1024, 0, 20); 102 | RT_ASSERT(tid); 103 | return rt_thread_startup(tid); 104 | } 105 | #ifdef RT_USING_COMPONENTS_INIT 106 | #include 107 | INIT_APP_EXPORT(vser_echo_init); 108 | #endif 109 | -------------------------------------------------------------------------------- /vexpress/build.sh: -------------------------------------------------------------------------------- 1 | scons 2 | cp rtthread.bin $MO_DIR 3 | -------------------------------------------------------------------------------- /vexpress/cpu/SConscript: -------------------------------------------------------------------------------- 1 | Import('rtconfig') 2 | from building import * 3 | 4 | cwd = GetCurrentDir() 5 | src = Glob('*.c') 6 | CPPPATH = [cwd] 7 | 8 | if rtconfig.PLATFORM == 'iar': 9 | src += Glob('*_iar.S') 10 | elif rtconfig.PLATFORM == 'gcc': 11 | src += Glob('*_gcc.S') 12 | elif rtconfig.PLATFORM == 'armcc': 13 | src += Glob('*_rvds.S') 14 | 15 | group = DefineGroup('AM335x', src, depend = [''], CPPPATH = CPPPATH) 16 | 17 | Return('group') 18 | -------------------------------------------------------------------------------- /vexpress/cpu/armv7.h: -------------------------------------------------------------------------------- 1 | #ifndef __ARMV7_H__ 2 | #define __ARMV7_H__ 3 | 4 | /* the exception stack without VFP registers */ 5 | struct rt_hw_exp_stack 6 | { 7 | unsigned long r0; 8 | unsigned long r1; 9 | unsigned long r2; 10 | unsigned long r3; 11 | unsigned long r4; 12 | unsigned long r5; 13 | unsigned long r6; 14 | unsigned long r7; 15 | unsigned long r8; 16 | unsigned long r9; 17 | unsigned long r10; 18 | unsigned long fp; 19 | unsigned long ip; 20 | unsigned long sp; 21 | unsigned long lr; 22 | unsigned long pc; 23 | unsigned long cpsr; 24 | }; 25 | 26 | struct rt_hw_stack 27 | { 28 | unsigned long cpsr; 29 | unsigned long r0; 30 | unsigned long r1; 31 | unsigned long r2; 32 | unsigned long r3; 33 | unsigned long r4; 34 | unsigned long r5; 35 | unsigned long r6; 36 | unsigned long r7; 37 | unsigned long r8; 38 | unsigned long r9; 39 | unsigned long r10; 40 | unsigned long fp; 41 | unsigned long ip; 42 | unsigned long lr; 43 | unsigned long pc; 44 | }; 45 | 46 | #define USERMODE 0x10 47 | #define FIQMODE 0x11 48 | #define IRQMODE 0x12 49 | #define SVCMODE 0x13 50 | #define MONITORMODE 0x16 51 | #define ABORTMODE 0x17 52 | #define HYPMODE 0x1b 53 | #define UNDEFMODE 0x1b 54 | #define MODEMASK 0x1f 55 | #define NOINT 0xc0 56 | 57 | #define T_Bit (1<<5) 58 | #define F_Bit (1<<6) 59 | #define I_Bit (1<<7) 60 | #define A_Bit (1<<8) 61 | #define E_Bit (1<<9) 62 | #define J_Bit (1<<24) 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /vexpress/cpu/context_gcc.S: -------------------------------------------------------------------------------- 1 | /* 2 | * File : context.S 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Development Team 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Change Logs: 21 | * Date Author Notes 22 | * 2013-07-05 Bernard the first version 23 | */ 24 | 25 | .section .text, "ax" 26 | /* 27 | * rt_base_t rt_hw_interrupt_disable(); 28 | */ 29 | .globl rt_hw_interrupt_disable 30 | rt_hw_interrupt_disable: 31 | mrs r0, cpsr 32 | cpsid i 33 | bx lr 34 | 35 | /* 36 | * void rt_hw_interrupt_enable(rt_base_t level); 37 | */ 38 | .globl rt_hw_interrupt_enable 39 | rt_hw_interrupt_enable: 40 | msr cpsr, r0 41 | bx lr 42 | 43 | /* 44 | * void rt_hw_context_switch_to(rt_uint32 to); 45 | * r0 --> to 46 | */ 47 | .globl rt_hw_context_switch_to 48 | rt_hw_context_switch_to: 49 | ldr sp, [r0] @ get new task stack pointer 50 | 51 | ldmfd sp!, {r4} @ pop new task spsr 52 | msr spsr_cxsf, r4 53 | 54 | ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc 55 | 56 | .section .bss.share.isr 57 | _guest_switch_lvl: 58 | .word 0 59 | 60 | .globl vmm_virq_update 61 | 62 | .section .text.isr, "ax" 63 | /* 64 | * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); 65 | * r0 --> from 66 | * r1 --> to 67 | */ 68 | .globl rt_hw_context_switch 69 | rt_hw_context_switch: 70 | stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) 71 | stmfd sp!, {r0-r12, lr} @ push lr & register file 72 | 73 | mrs r4, cpsr 74 | tst lr, #0x01 75 | orrne r4, r4, #0x20 @ it's thumb code 76 | 77 | stmfd sp!, {r4} @ push cpsr 78 | 79 | str sp, [r0] @ store sp in preempted tasks TCB 80 | ldr sp, [r1] @ get new task stack pointer 81 | 82 | ldmfd sp!, {r4} @ pop new task cpsr to spsr 83 | msr spsr_cxsf, r4 84 | ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr 85 | 86 | /* 87 | * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); 88 | */ 89 | .globl rt_thread_switch_interrupt_flag 90 | .globl rt_interrupt_from_thread 91 | .globl rt_interrupt_to_thread 92 | .globl rt_hw_context_switch_interrupt 93 | rt_hw_context_switch_interrupt: 94 | ldr r2, =rt_thread_switch_interrupt_flag 95 | ldr r3, [r2] 96 | cmp r3, #1 97 | beq _reswitch 98 | ldr ip, =rt_interrupt_from_thread @ set rt_interrupt_from_thread 99 | mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 100 | str r0, [ip] 101 | str r3, [r2] 102 | _reswitch: 103 | ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread 104 | str r1, [r2] 105 | bx lr 106 | -------------------------------------------------------------------------------- /vexpress/cpu/cp15.h: -------------------------------------------------------------------------------- 1 | #ifndef __CP15_H__ 2 | #define __CP15_H__ 3 | 4 | unsigned long rt_cpu_get_smp_id(void); 5 | 6 | void rt_cpu_mmu_disable(void); 7 | void rt_cpu_mmu_enable(void); 8 | void rt_cpu_tlb_set(volatile unsigned long*); 9 | 10 | void rt_cpu_vector_set_base(unsigned int addr); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /vexpress/cpu/cp15_gcc.S: -------------------------------------------------------------------------------- 1 | /* 2 | * File : cp15_gcc.S 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Development Team 5 | * http://www.rt-thread.org 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Change Logs: 22 | * Date Author Notes 23 | * 2013-07-05 Bernard the first version 24 | */ 25 | 26 | .globl rt_cpu_get_smp_id 27 | rt_cpu_get_smp_id: 28 | mrc p15, #0, r0, c0, c0, #5 29 | bx lr 30 | 31 | .globl rt_cpu_vector_set_base 32 | rt_cpu_vector_set_base: 33 | mcr p15, #0, r0, c12, c0, #0 34 | dsb 35 | bx lr 36 | 37 | .globl rt_hw_cpu_dcache_enable 38 | rt_hw_cpu_dcache_enable: 39 | mrc p15, #0, r0, c1, c0, #0 40 | orr r0, r0, #0x00000004 41 | mcr p15, #0, r0, c1, c0, #0 42 | bx lr 43 | 44 | .globl rt_hw_cpu_icache_enable 45 | rt_hw_cpu_icache_enable: 46 | mrc p15, #0, r0, c1, c0, #0 47 | orr r0, r0, #0x00001000 48 | mcr p15, #0, r0, c1, c0, #0 49 | bx lr 50 | 51 | _FLD_MAX_WAY: 52 | .word 0x3ff 53 | _FLD_MAX_IDX: 54 | .word 0x7ff 55 | 56 | .globl rt_cpu_dcache_clean_flush 57 | rt_cpu_dcache_clean_flush: 58 | push {r4-r11} 59 | dmb 60 | mrc p15, #1, r0, c0, c0, #1 @ read clid register 61 | ands r3, r0, #0x7000000 @ get level of coherency 62 | mov r3, r3, lsr #23 63 | beq finished 64 | mov r10, #0 65 | loop1: 66 | add r2, r10, r10, lsr #1 67 | mov r1, r0, lsr r2 68 | and r1, r1, #7 69 | cmp r1, #2 70 | blt skip 71 | mcr p15, #2, r10, c0, c0, #0 72 | isb 73 | mrc p15, #1, r1, c0, c0, #0 74 | and r2, r1, #7 75 | add r2, r2, #4 76 | ldr r4, _FLD_MAX_WAY 77 | ands r4, r4, r1, lsr #3 78 | clz r5, r4 79 | ldr r7, _FLD_MAX_IDX 80 | ands r7, r7, r1, lsr #13 81 | loop2: 82 | mov r9, r4 83 | loop3: 84 | orr r11, r10, r9, lsl r5 85 | orr r11, r11, r7, lsl r2 86 | mcr p15, #0, r11, c7, c14, #2 87 | subs r9, r9, #1 88 | bge loop3 89 | subs r7, r7, #1 90 | bge loop2 91 | skip: 92 | add r10, r10, #2 93 | cmp r3, r10 94 | bgt loop1 95 | 96 | finished: 97 | dsb 98 | isb 99 | pop {r4-r11} 100 | bx lr 101 | 102 | .globl rt_hw_cpu_dcache_disable 103 | rt_hw_cpu_dcache_disable: 104 | push {r4-r11, lr} 105 | bl rt_cpu_dcache_clean_flush 106 | mrc p15, #0, r0, c1, c0, #0 107 | bic r0, r0, #0x00000004 108 | mcr p15, #0, r0, c1, c0, #0 109 | pop {r4-r11, lr} 110 | bx lr 111 | 112 | .globl rt_hw_cpu_icache_disable 113 | rt_hw_cpu_icache_disable: 114 | mrc p15, #0, r0, c1, c0, #0 115 | bic r0, r0, #0x00001000 116 | mcr p15, #0, r0, c1, c0, #0 117 | bx lr 118 | 119 | .globl rt_cpu_mmu_disable 120 | rt_cpu_mmu_disable: 121 | mcr p15, #0, r0, c8, c7, #0 @ invalidate tlb 122 | mrc p15, #0, r0, c1, c0, #0 123 | bic r0, r0, #1 124 | mcr p15, #0, r0, c1, c0, #0 @ clear mmu bit 125 | dsb 126 | bx lr 127 | 128 | .globl rt_cpu_mmu_enable 129 | rt_cpu_mmu_enable: 130 | mrc p15, #0, r0, c1, c0, #0 131 | orr r0, r0, #0x001 132 | mcr p15, #0, r0, c1, c0, #0 @ set mmu enable bit 133 | dsb 134 | bx lr 135 | 136 | .globl rt_cpu_tlb_set 137 | rt_cpu_tlb_set: 138 | mcr p15, #0, r0, c2, c0, #0 139 | dmb 140 | bx lr 141 | -------------------------------------------------------------------------------- /vexpress/cpu/cpu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : cpu.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2006, RT-Thread Develop Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2011-09-15 Bernard first version 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | /** 20 | * @addtogroup AM33xx 21 | */ 22 | /*@{*/ 23 | 24 | /** shutdown CPU */ 25 | void rt_hw_cpu_shutdown() 26 | { 27 | rt_uint32_t level; 28 | rt_kprintf("shutdown...\n"); 29 | 30 | level = rt_hw_interrupt_disable(); 31 | while (level) 32 | { 33 | RT_ASSERT(0); 34 | } 35 | } 36 | 37 | /*@}*/ 38 | -------------------------------------------------------------------------------- /vexpress/cpu/gic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File : gic.h, ARM Generic Interrupt Controller 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Develop Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2013-07-20 Bernard first version 13 | */ 14 | 15 | #ifndef __GIC_H__ 16 | #define __GIC_H__ 17 | 18 | int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start); 19 | int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base); 20 | 21 | void arm_gic_mask(rt_uint32_t index, int irq); 22 | void arm_gic_umask(rt_uint32_t index, int irq); 23 | void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask); 24 | void arm_gic_set_group(rt_uint32_t index, int vector, int group); 25 | 26 | int arm_gic_get_active_irq(rt_uint32_t index); 27 | void arm_gic_ack(rt_uint32_t index, int irq); 28 | 29 | void arm_gic_trigger(rt_uint32_t index, int target_cpu, int irq); 30 | void arm_gic_clear_sgi(rt_uint32_t index, int target_cpu, int irq); 31 | 32 | void arm_gic_dump_type(rt_uint32_t index); 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /vexpress/cpu/interrupt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : interrupt.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013-2014, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2013-07-06 Bernard first version 13 | * 2014-04-03 Grissiom port to VMM 14 | */ 15 | 16 | #include 17 | #include 18 | #include "realview.h" 19 | #include "gic.h" 20 | #include "cp15.h" 21 | 22 | #ifdef RT_USING_VMM 23 | #include 24 | #endif 25 | 26 | #define MAX_HANDLERS NR_IRQS_PBA8 27 | 28 | extern volatile rt_uint8_t rt_interrupt_nest; 29 | 30 | /* exception and interrupt handler table */ 31 | struct rt_irq_desc isr_table[MAX_HANDLERS]; 32 | 33 | rt_uint32_t rt_interrupt_from_thread; 34 | rt_uint32_t rt_interrupt_to_thread; 35 | rt_uint32_t rt_thread_switch_interrupt_flag; 36 | 37 | extern void rt_cpu_vector_set_base(unsigned int addr); 38 | extern int system_vectors; 39 | 40 | static void rt_hw_vector_init(void) 41 | { 42 | int sctrl; 43 | unsigned int *src = (unsigned int *)&system_vectors; 44 | 45 | /* C12-C0 is only active when SCTLR.V = 0 */ 46 | asm volatile ("mrc p15, #0, %0, c1, c0, #0" 47 | :"=r" (sctrl)); 48 | sctrl &= ~(1 << 13); 49 | asm volatile ("mcr p15, #0, %0, c1, c0, #0" 50 | : 51 | :"r" (sctrl)); 52 | 53 | asm volatile ("mcr p15, #0, %0, c12, c0, #0" 54 | : 55 | :"r" (src)); 56 | } 57 | 58 | /** 59 | * This function will initialize hardware interrupt 60 | */ 61 | void rt_hw_interrupt_init(void) 62 | { 63 | rt_uint32_t gic_cpu_base; 64 | rt_uint32_t gic_dist_base; 65 | 66 | /* initialize vector table */ 67 | rt_hw_vector_init(); 68 | 69 | /* initialize exceptions table */ 70 | rt_memset(isr_table, 0x00, sizeof(isr_table)); 71 | 72 | /* initialize ARM GIC */ 73 | gic_dist_base = REALVIEW_GIC_DIST_BASE; 74 | gic_cpu_base = REALVIEW_GIC_CPU_BASE; 75 | arm_gic_dist_init(0, gic_dist_base, 0); 76 | arm_gic_cpu_init(0, gic_cpu_base); 77 | /*arm_gic_dump_type(0);*/ 78 | 79 | /* init interrupt nest, and context in thread sp */ 80 | rt_interrupt_nest = 0; 81 | rt_interrupt_from_thread = 0; 82 | rt_interrupt_to_thread = 0; 83 | rt_thread_switch_interrupt_flag = 0; 84 | } 85 | 86 | /** 87 | * This function will mask a interrupt. 88 | * @param vector the interrupt number 89 | */ 90 | void rt_hw_interrupt_mask(int vector) 91 | { 92 | arm_gic_mask(0, vector); 93 | } 94 | 95 | /** 96 | * This function will un-mask a interrupt. 97 | * @param vector the interrupt number 98 | */ 99 | void rt_hw_interrupt_umask(int vector) 100 | { 101 | arm_gic_umask(0, vector); 102 | } 103 | 104 | /** 105 | * This function will install a interrupt service routine to a interrupt. 106 | * @param vector the interrupt number 107 | * @param new_handler the interrupt service routine to be installed 108 | * @param old_handler the old interrupt service routine 109 | */ 110 | rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, 111 | void *param, char *name) 112 | { 113 | rt_isr_handler_t old_handler = RT_NULL; 114 | 115 | if (vector < MAX_HANDLERS) 116 | { 117 | old_handler = isr_table[vector].handler; 118 | 119 | if (handler != RT_NULL) 120 | { 121 | #ifdef RT_USING_INTERRUPT_INFO 122 | rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX); 123 | #endif /* RT_USING_INTERRUPT_INFO */ 124 | isr_table[vector].handler = handler; 125 | isr_table[vector].param = param; 126 | } 127 | arm_gic_set_cpu(0, vector, 1 << rt_cpu_get_smp_id()); 128 | } 129 | 130 | return old_handler; 131 | } 132 | 133 | /** 134 | * Trigger a software IRQ 135 | * 136 | * Since we are running in single core, the target CPU are always CPU0. 137 | */ 138 | void rt_hw_interrupt_trigger(int vector) 139 | { 140 | arm_gic_trigger(0, 1, vector); 141 | } 142 | 143 | void rt_hw_interrupt_clear(int vector) 144 | { 145 | arm_gic_clear_sgi(0, 1, vector); 146 | } 147 | -------------------------------------------------------------------------------- /vexpress/cpu/interrupt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File : interrupt.h 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2011, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2013-07-06 Bernard first version 13 | */ 14 | 15 | #ifndef __INTERRUPT_H__ 16 | #define __INTERRUPT_H__ 17 | 18 | #define INT_IRQ 0x00 19 | #define INT_FIQ 0x01 20 | 21 | #define INTC_REVISION(hw_base) REG32((hw_base) + 0x0) 22 | #define INTC_SYSCONFIG(hw_base) REG32((hw_base) + 0x10) 23 | #define INTC_SYSSTATUS(hw_base) REG32((hw_base) + 0x14) 24 | #define INTC_SIR_IRQ(hw_base) REG32((hw_base) + 0x40) 25 | #define INTC_SIR_FIQ(hw_base) REG32((hw_base) + 0x44) 26 | #define INTC_CONTROL(hw_base) REG32((hw_base) + 0x48) 27 | #define INTC_PROTECTION(hw_base) REG32((hw_base) + 0x4c) 28 | #define INTC_IDLE(hw_base) REG32((hw_base) + 0x50) 29 | #define INTC_IRQ_PRIORITY(hw_base) REG32((hw_base) + 0x60) 30 | #define INTC_FIQ_PRIORITY(hw_base) REG32((hw_base) + 0x64) 31 | #define INTC_THRESHOLD(hw_base) REG32((hw_base) + 0x68) 32 | #define INTC_SICR(hw_base) REG32((hw_base) + 0x6c) 33 | #define INTC_SCR(hw_base, n) REG32((hw_base) + 0x70 + ((n) * 0x04)) 34 | #define INTC_ITR(hw_base, n) REG32((hw_base) + 0x80 + ((n) * 0x20)) 35 | #define INTC_MIR(hw_base, n) REG32((hw_base) + 0x84 + ((n) * 0x20)) 36 | #define INTC_MIR_CLEAR(hw_base, n) REG32((hw_base) + 0x88 + ((n) * 0x20)) 37 | #define INTC_MIR_SET(hw_base, n) REG32((hw_base) + 0x8c + ((n) * 0x20)) 38 | #define INTC_ISR_SET(hw_base, n) REG32((hw_base) + 0x90 + ((n) * 0x20)) 39 | #define INTC_ISR_CLEAR(hw_base, n) REG32((hw_base) + 0x94 + ((n) * 0x20)) 40 | #define INTC_PENDING_IRQ(hw_base, n) REG32((hw_base) + 0x98 + ((n) * 0x20)) 41 | #define INTC_PENDING_FIQ(hw_base, n) REG32((hw_base) + 0x9c + ((n) * 0x20)) 42 | #define INTC_ILR(hw_base, n) REG32((hw_base) + 0x100 + ((n) * 0x04)) 43 | 44 | void rt_hw_interrupt_control(int vector, int priority, int route); 45 | int rt_hw_interrupt_get_active(int fiq_irq); 46 | void rt_hw_interrupt_ack(int fiq_irq); 47 | void rt_hw_interrupt_trigger(int vector); 48 | void rt_hw_interrupt_clear(int vector); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /vexpress/cpu/mmu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : mmu.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2006, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2012-01-10 bernard porting to AM1808 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "cp15.h" 20 | 21 | #define DESC_SEC (0x2) 22 | #define CB (3<<2) //cache_on, write_back 23 | #define CNB (2<<2) //cache_on, write_through 24 | #define NCB (1<<2) //cache_off,WR_BUF on 25 | #define NCNB (0<<2) //cache_off,WR_BUF off 26 | #define AP_RW (3<<10) //supervisor=RW, user=RW 27 | #define AP_RO (2<<10) //supervisor=RW, user=RO 28 | #define XN (1<<4) // eXecute Never 29 | 30 | #define DOMAIN_FAULT (0x0) 31 | #define DOMAIN_CHK (0x1) 32 | #define DOMAIN_NOTCHK (0x3) 33 | #define DOMAIN0 (0x0<<5) 34 | #define DOMAIN1 (0x1<<5) 35 | 36 | #define DOMAIN0_ATTR (DOMAIN_CHK<<0) 37 | #define DOMAIN1_ATTR (DOMAIN_FAULT<<2) 38 | 39 | /* Read/Write, cache, write back */ 40 | #define RW_CB (AP_RW|DOMAIN0|CB|DESC_SEC) 41 | /* Read/Write, cache, write through */ 42 | #define RW_CNB (AP_RW|DOMAIN0|CNB|DESC_SEC) 43 | /* Read/Write without cache and write buffer */ 44 | #define RW_NCNB (AP_RW|DOMAIN0|NCNB|DESC_SEC) 45 | /* Read/Write without cache and write buffer, no execute */ 46 | #define RW_NCNBXN (AP_RW|DOMAIN0|NCNB|DESC_SEC|XN) 47 | /* Read/Write without cache and write buffer */ 48 | #define RW_FAULT (AP_RW|DOMAIN1|NCNB|DESC_SEC) 49 | 50 | /* dump 2nd level page table */ 51 | void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb) 52 | { 53 | int i; 54 | int fcnt = 0; 55 | 56 | for (i = 0; i < 256; i++) 57 | { 58 | rt_uint32_t pte2 = ptb[i]; 59 | if ((pte2 & 0x3) == 0) 60 | { 61 | if (fcnt == 0) 62 | rt_kprintf(" "); 63 | rt_kprintf("%04x: ", i); 64 | fcnt++; 65 | if (fcnt == 16) 66 | { 67 | rt_kprintf("fault\n"); 68 | fcnt = 0; 69 | } 70 | continue; 71 | } 72 | if (fcnt != 0) 73 | { 74 | rt_kprintf("fault\n"); 75 | fcnt = 0; 76 | } 77 | 78 | rt_kprintf(" %04x: %x: ", i, pte2); 79 | if ((pte2 & 0x3) == 0x1) 80 | { 81 | rt_kprintf("L,ap:%x,xn:%d,texcb:%02x\n", 82 | ((pte2 >> 7) | (pte2 >> 4))& 0xf, 83 | (pte2 >> 15) & 0x1, 84 | ((pte2 >> 10) | (pte2 >> 2)) & 0x1f); 85 | } 86 | else 87 | { 88 | rt_kprintf("S,ap:%x,xn:%d,texcb:%02x\n", 89 | ((pte2 >> 7) | (pte2 >> 4))& 0xf, pte2 & 0x1, 90 | ((pte2 >> 4) | (pte2 >> 2)) & 0x1f); 91 | } 92 | } 93 | } 94 | 95 | void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb) 96 | { 97 | int i; 98 | int fcnt = 0; 99 | 100 | rt_kprintf("page table@%p\n", ptb); 101 | for (i = 0; i < 1024*4; i++) 102 | { 103 | rt_uint32_t pte1 = ptb[i]; 104 | if ((pte1 & 0x3) == 0) 105 | { 106 | rt_kprintf("%03x: ", i); 107 | fcnt++; 108 | if (fcnt == 16) 109 | { 110 | rt_kprintf("fault\n"); 111 | fcnt = 0; 112 | } 113 | continue; 114 | } 115 | if (fcnt != 0) 116 | { 117 | rt_kprintf("fault\n"); 118 | fcnt = 0; 119 | } 120 | 121 | rt_kprintf("%03x: %08x: ", i, pte1); 122 | if ((pte1 & 0x3) == 0x3) 123 | { 124 | rt_kprintf("LPAE\n"); 125 | } 126 | else if ((pte1 & 0x3) == 0x1) 127 | { 128 | rt_kprintf("pte,ns:%d,domain:%d\n", 129 | (pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf); 130 | /* 131 | *rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000) 132 | * - 0x80000000 + 0xC0000000)); 133 | */ 134 | } 135 | else if (pte1 & (1 << 18)) 136 | { 137 | rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n", 138 | (pte1 >> 19) & 0x1, 139 | ((pte1 >> 13) | (pte1 >> 10))& 0xf, 140 | (pte1 >> 4) & 0x1, 141 | ((pte1 >> 10) | (pte1 >> 2)) & 0x1f); 142 | } 143 | else 144 | { 145 | rt_kprintf("section,ns:%d,ap:%x," 146 | "xn:%d,texcb:%02x,domain:%d\n", 147 | (pte1 >> 19) & 0x1, 148 | ((pte1 >> 13) | (pte1 >> 10))& 0xf, 149 | (pte1 >> 4) & 0x1, 150 | (((pte1 & (0x7 << 12)) >> 10) | 151 | ((pte1 & 0x0c) >> 2)) & 0x1f, 152 | (pte1 >> 5) & 0xf); 153 | } 154 | } 155 | } 156 | 157 | /* level1 page table, each entry for 1MB memory. */ 158 | volatile static unsigned long MMUTable[4*1024] __attribute__((aligned(16*1024))); 159 | void rt_hw_mmu_setmtt(rt_uint32_t vaddrStart, 160 | rt_uint32_t vaddrEnd, 161 | rt_uint32_t paddrStart, 162 | rt_uint32_t attr) 163 | { 164 | volatile rt_uint32_t *pTT; 165 | volatile int i, nSec; 166 | pTT = (rt_uint32_t *)MMUTable + (vaddrStart >> 20); 167 | nSec = (vaddrEnd >> 20) - (vaddrStart >> 20); 168 | for(i = 0; i <= nSec; i++) 169 | { 170 | *pTT = attr | (((paddrStart >> 20) + i) << 20); 171 | pTT++; 172 | } 173 | } 174 | 175 | unsigned long rt_hw_set_domain_register(unsigned long domain_val) 176 | { 177 | unsigned long old_domain; 178 | 179 | asm volatile ("mrc p15, 0, %0, c3, c0\n" : "=r" (old_domain)); 180 | asm volatile ("mcr p15, 0, %0, c3, c0\n" : :"r" (domain_val) : "memory"); 181 | 182 | return old_domain; 183 | } 184 | 185 | void rt_hw_mmu_init(void) 186 | { 187 | rt_hw_cpu_dcache_disable(); 188 | rt_hw_cpu_icache_disable(); 189 | rt_cpu_mmu_disable(); 190 | 191 | /* set page table */ 192 | /* 4G 1:1 memory */ 193 | rt_hw_mmu_setmtt(0, 0xffffffff-1, 0, RW_CB); 194 | /* IO memory region */ 195 | rt_hw_mmu_setmtt(0x44000000, 0x80000000-1, 0x44000000, RW_NCNBXN); 196 | 197 | /*rt_hw_cpu_dump_page_table(MMUTable);*/ 198 | rt_hw_set_domain_register(0x55555555); 199 | 200 | rt_cpu_tlb_set(MMUTable); 201 | 202 | rt_cpu_mmu_enable(); 203 | 204 | rt_hw_cpu_icache_enable(); 205 | rt_hw_cpu_dcache_enable(); 206 | } 207 | 208 | -------------------------------------------------------------------------------- /vexpress/cpu/pmu.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pmu.h" 3 | 4 | void rt_hw_pmu_dump_feature(void) 5 | { 6 | unsigned long reg; 7 | 8 | reg = rt_hw_pmu_get_control(); 9 | rt_kprintf("ARM PMU Implementor: %c, ID code: %02x, %d counters\n", 10 | reg >> 24, (reg >> 16) & 0xff, (reg >> 11) & 0x1f); 11 | RT_ASSERT(ARM_PMU_CNTER_NR == ((reg >> 11) & 0x1f)); 12 | } 13 | -------------------------------------------------------------------------------- /vexpress/cpu/pmu.h: -------------------------------------------------------------------------------- 1 | #ifndef __PMU_H__ 2 | #define __PMU_H__ 3 | 4 | #include "board.h" 5 | 6 | /* Number of counters */ 7 | #define ARM_PMU_CNTER_NR 4 8 | 9 | enum rt_hw_pmu_event_type { 10 | ARM_PMU_EVENT_PMNC_SW_INCR = 0x00, 11 | ARM_PMU_EVENT_L1_ICACHE_REFILL = 0x01, 12 | ARM_PMU_EVENT_ITLB_REFILL = 0x02, 13 | ARM_PMU_EVENT_L1_DCACHE_REFILL = 0x03, 14 | ARM_PMU_EVENT_L1_DCACHE_ACCESS = 0x04, 15 | ARM_PMU_EVENT_DTLB_REFILL = 0x05, 16 | ARM_PMU_EVENT_MEM_READ = 0x06, 17 | ARM_PMU_EVENT_MEM_WRITE = 0x07, 18 | ARM_PMU_EVENT_INSTR_EXECUTED = 0x08, 19 | ARM_PMU_EVENT_EXC_TAKEN = 0x09, 20 | ARM_PMU_EVENT_EXC_EXECUTED = 0x0A, 21 | ARM_PMU_EVENT_CID_WRITE = 0x0B, 22 | }; 23 | 24 | /* Enable bit */ 25 | #define ARM_PMU_PMCR_E (0x01 << 0) 26 | /* Event counter reset */ 27 | #define ARM_PMU_PMCR_P (0x01 << 1) 28 | /* Cycle counter reset */ 29 | #define ARM_PMU_PMCR_C (0x01 << 2) 30 | /* Cycle counter divider */ 31 | #define ARM_PMU_PMCR_D (0x01 << 3) 32 | 33 | #ifdef __GNUC__ 34 | rt_inline void rt_hw_pmu_enable_cnt(int divide64) 35 | { 36 | unsigned long pmcr; 37 | unsigned long pmcntenset; 38 | 39 | asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr)); 40 | pmcr |= ARM_PMU_PMCR_E | ARM_PMU_PMCR_P | ARM_PMU_PMCR_C; 41 | if (divide64) 42 | pmcr |= ARM_PMU_PMCR_D; 43 | else 44 | pmcr &= ~ARM_PMU_PMCR_D; 45 | asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr)); 46 | 47 | /* enable all the counters */ 48 | pmcntenset = ~0; 49 | asm volatile ("mcr p15, 0, %0, c9, c12, 1" :: "r"(pmcntenset)); 50 | /* clear overflows(just in case) */ 51 | asm volatile ("mcr p15, 0, %0, c9, c12, 3" :: "r"(pmcntenset)); 52 | } 53 | 54 | rt_inline unsigned long rt_hw_pmu_get_control(void) 55 | { 56 | unsigned long pmcr; 57 | asm ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr)); 58 | return pmcr; 59 | } 60 | 61 | rt_inline unsigned long rt_hw_pmu_get_ceid(void) 62 | { 63 | unsigned long reg; 64 | /* only PMCEID0 is supported, PMCEID1 is RAZ. */ 65 | asm ("mrc p15, 0, %0, c9, c12, 6" : "=r"(reg)); 66 | return reg; 67 | } 68 | 69 | rt_inline unsigned long rt_hw_pmu_get_cnten(void) 70 | { 71 | unsigned long pmcnt; 72 | asm ("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcnt)); 73 | return pmcnt; 74 | } 75 | 76 | rt_inline void rt_hw_pmu_reset_cycle(void) 77 | { 78 | unsigned long pmcr; 79 | 80 | asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr)); 81 | pmcr |= ARM_PMU_PMCR_C; 82 | asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr)); 83 | asm volatile ("isb"); 84 | } 85 | 86 | rt_inline void rt_hw_pmu_reset_event(void) 87 | { 88 | unsigned long pmcr; 89 | 90 | asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr)); 91 | pmcr |= ARM_PMU_PMCR_P; 92 | asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr)); 93 | asm volatile ("isb"); 94 | } 95 | 96 | rt_inline unsigned long rt_hw_pmu_get_cycle(void) 97 | { 98 | unsigned long cyc; 99 | asm volatile ("isb"); 100 | asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r"(cyc)); 101 | return cyc; 102 | } 103 | 104 | rt_inline void rt_hw_pmu_select_counter(int idx) 105 | { 106 | RT_ASSERT(idx < ARM_PMU_CNTER_NR); 107 | 108 | asm volatile ("mcr p15, 0, %0, c9, c12, 5" : : "r"(idx)); 109 | /* Linux add an isb here, don't know why here. */ 110 | asm volatile ("isb"); 111 | } 112 | 113 | rt_inline void rt_hw_pmu_select_event(int idx, 114 | enum rt_hw_pmu_event_type eve) 115 | { 116 | RT_ASSERT(idx < ARM_PMU_CNTER_NR); 117 | 118 | rt_hw_pmu_select_counter(idx); 119 | asm volatile ("mcr p15, 0, %0, c9, c13, 1" : : "r"(eve)); 120 | } 121 | 122 | rt_inline unsigned long rt_hw_pmu_read_counter(int idx) 123 | { 124 | unsigned long reg; 125 | 126 | rt_hw_pmu_select_counter(idx); 127 | asm volatile ("isb"); 128 | asm volatile ("mrc p15, 0, %0, c9, c13, 2" : "=r"(reg)); 129 | return reg; 130 | } 131 | 132 | rt_inline unsigned long rt_hw_pmu_get_ovsr(void) 133 | { 134 | unsigned long reg; 135 | asm volatile ("isb"); 136 | asm ("mrc p15, 0, %0, c9, c12, 3" : "=r"(reg)); 137 | return reg; 138 | } 139 | 140 | rt_inline void rt_hw_pmu_clear_ovsr(unsigned long reg) 141 | { 142 | asm ("mcr p15, 0, %0, c9, c12, 3" : : "r"(reg)); 143 | asm volatile ("isb"); 144 | } 145 | 146 | #endif 147 | 148 | void rt_hw_pmu_dump_feature(void); 149 | 150 | #endif /* end of include guard: __PMU_H__ */ 151 | 152 | -------------------------------------------------------------------------------- /vexpress/cpu/stack.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : stack.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2011, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2011-09-23 Bernard the first version 13 | * 2011-10-05 Bernard add thumb mode 14 | */ 15 | #include 16 | #include 17 | 18 | /** 19 | * @addtogroup AM33xx 20 | */ 21 | /*@{*/ 22 | 23 | /** 24 | * This function will initialize thread stack 25 | * 26 | * @param tentry the entry of thread 27 | * @param parameter the parameter of entry 28 | * @param stack_addr the beginning stack address 29 | * @param texit the function will be called when thread exit 30 | * 31 | * @return stack address 32 | */ 33 | rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, 34 | rt_uint8_t *stack_addr, void *texit) 35 | { 36 | rt_uint32_t *stk; 37 | 38 | stk = (rt_uint32_t*)stack_addr; 39 | *(stk) = (rt_uint32_t)tentry; /* entry point */ 40 | *(--stk) = (rt_uint32_t)texit; /* lr */ 41 | *(--stk) = 0; /* r12 */ 42 | *(--stk) = 0; /* r11 */ 43 | *(--stk) = 0; /* r10 */ 44 | *(--stk) = 0; /* r9 */ 45 | *(--stk) = 0; /* r8 */ 46 | *(--stk) = 0; /* r7 */ 47 | *(--stk) = 0; /* r6 */ 48 | *(--stk) = 0; /* r5 */ 49 | *(--stk) = 0; /* r4 */ 50 | *(--stk) = 0; /* r3 */ 51 | *(--stk) = 0; /* r2 */ 52 | *(--stk) = 0; /* r1 */ 53 | *(--stk) = (rt_uint32_t)parameter; /* r0 : argument */ 54 | 55 | /* cpsr */ 56 | if ((rt_uint32_t)tentry & 0x01) 57 | *(--stk) = SVCMODE | 0x20; /* thumb mode */ 58 | else 59 | *(--stk) = SVCMODE; /* arm mode */ 60 | 61 | /* return task's current stack address */ 62 | return (rt_uint8_t *)stk; 63 | } 64 | 65 | /*@}*/ 66 | -------------------------------------------------------------------------------- /vexpress/cpu/start_gcc.S: -------------------------------------------------------------------------------- 1 | /* 2 | * File : start_gcc.S 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013-2014, RT-Thread Development Team 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Change Logs: 21 | * Date Author Notes 22 | * 2013-07-05 Bernard the first version 23 | */ 24 | 25 | .equ Mode_USR, 0x10 26 | .equ Mode_FIQ, 0x11 27 | .equ Mode_IRQ, 0x12 28 | .equ Mode_SVC, 0x13 29 | .equ Mode_ABT, 0x17 30 | .equ Mode_UND, 0x1B 31 | .equ Mode_SYS, 0x1F 32 | 33 | .equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled 34 | .equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled 35 | 36 | .equ UND_Stack_Size, 0x00000000 37 | .equ SVC_Stack_Size, 0x00000100 38 | .equ ABT_Stack_Size, 0x00000000 39 | .equ RT_FIQ_STACK_PGSZ, 0x00000000 40 | .equ RT_IRQ_STACK_PGSZ, 0x00000100 41 | .equ USR_Stack_Size, 0x00000100 42 | 43 | #define ISR_Stack_Size (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \ 44 | RT_FIQ_STACK_PGSZ + RT_IRQ_STACK_PGSZ) 45 | 46 | .section .data.share.isr 47 | /* stack */ 48 | .globl stack_start 49 | .globl stack_top 50 | 51 | stack_start: 52 | .rept ISR_Stack_Size 53 | .byte 0 54 | .endr 55 | stack_top: 56 | 57 | .text 58 | /* reset entry */ 59 | .globl _reset 60 | _reset: 61 | bl rt_cpu_mmu_disable 62 | /* set the cpu to SVC32 mode and disable interrupt */ 63 | mrs r0, cpsr 64 | bic r0, r0, #0x1f 65 | orr r0, r0, #0x13 66 | msr cpsr_c, r0 67 | 68 | /* setup stack */ 69 | bl stack_setup 70 | 71 | /* clear .bss */ 72 | mov r0,#0 /* get a zero */ 73 | ldr r1,=__bss_start /* bss start */ 74 | ldr r2,=__bss_end /* bss end */ 75 | 76 | bss_loop: 77 | cmp r1,r2 /* check if data to clear */ 78 | strlo r0,[r1],#4 /* clear 4 bytes */ 79 | blo bss_loop /* loop until done */ 80 | 81 | /* call C++ constructors of global objects */ 82 | ldr r0, =__ctors_start__ 83 | ldr r1, =__ctors_end__ 84 | 85 | ctor_loop: 86 | cmp r0, r1 87 | beq ctor_end 88 | ldr r2, [r0], #4 89 | stmfd sp!, {r0-r1} 90 | mov lr, pc 91 | bx r2 92 | ldmfd sp!, {r0-r1} 93 | b ctor_loop 94 | ctor_end: 95 | 96 | /* start RT-Thread Kernel */ 97 | ldr pc, _rtthread_startup 98 | _rtthread_startup: 99 | .word rtthread_startup 100 | 101 | stack_setup: 102 | ldr r0, =stack_top 103 | 104 | @ Set the startup stack for svc 105 | mov sp, r0 106 | 107 | @ Enter Undefined Instruction Mode and set its Stack Pointer 108 | msr cpsr_c, #Mode_UND|I_Bit|F_Bit 109 | mov sp, r0 110 | sub r0, r0, #UND_Stack_Size 111 | 112 | @ Enter Abort Mode and set its Stack Pointer 113 | msr cpsr_c, #Mode_ABT|I_Bit|F_Bit 114 | mov sp, r0 115 | sub r0, r0, #ABT_Stack_Size 116 | 117 | @ Enter FIQ Mode and set its Stack Pointer 118 | msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit 119 | mov sp, r0 120 | sub r0, r0, #RT_FIQ_STACK_PGSZ 121 | 122 | @ Enter IRQ Mode and set its Stack Pointer 123 | msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit 124 | mov sp, r0 125 | sub r0, r0, #RT_IRQ_STACK_PGSZ 126 | 127 | /* come back to SVC mode */ 128 | msr cpsr_c, #Mode_SVC|I_Bit|F_Bit 129 | bx lr 130 | 131 | /* exception handlers: undef, swi, padt, dabt, resv, irq, fiq */ 132 | .section .text.isr, "ax" 133 | .align 5 134 | .globl vector_fiq 135 | vector_fiq: 136 | stmfd sp!,{r0-r7,lr} 137 | bl rt_hw_trap_fiq 138 | ldmfd sp!,{r0-r7,lr} 139 | subs pc, lr, #4 140 | 141 | .globl rt_interrupt_enter 142 | .globl rt_interrupt_leave 143 | .globl rt_thread_switch_interrupt_flag 144 | .globl rt_interrupt_from_thread 145 | .globl rt_interrupt_to_thread 146 | 147 | .globl rt_current_thread 148 | .globl vmm_thread 149 | .globl vmm_virq_check 150 | 151 | .align 5 152 | .globl vector_irq 153 | vector_irq: 154 | stmfd sp!, {r0-r12,lr} 155 | 156 | bl rt_interrupt_enter 157 | bl rt_hw_trap_irq 158 | bl rt_interrupt_leave 159 | 160 | @ if rt_thread_switch_interrupt_flag set, jump to 161 | @ rt_hw_context_switch_interrupt_do and don't return 162 | ldr r0, =rt_thread_switch_interrupt_flag 163 | ldr r1, [r0] 164 | cmp r1, #1 165 | beq rt_hw_context_switch_interrupt_do 166 | 167 | ldmfd sp!, {r0-r12,lr} 168 | subs pc, lr, #4 169 | 170 | rt_hw_context_switch_interrupt_do: 171 | mov r1, #0 @ clear flag 172 | str r1, [r0] 173 | 174 | mov r1, sp @ r1 point to {r0-r3} in stack 175 | add sp, sp, #4*4 176 | ldmfd sp!, {r4-r12,lr}@ reload saved registers 177 | mrs r0, spsr @ get cpsr of interrupt thread 178 | sub r2, lr, #4 @ save old task's pc to r2 179 | 180 | @ Switch to SVC mode with no interrupt. If the usr mode guest is 181 | @ interrupted, this will just switch to the stack of kernel space. 182 | @ save the registers in kernel space won't trigger data abort. 183 | msr cpsr_c, #I_Bit|F_Bit|Mode_SVC 184 | 185 | stmfd sp!, {r2} @ push old task's pc 186 | stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4 187 | ldmfd r1, {r1-r4} @ restore r0-r3 of the interrupt thread 188 | stmfd sp!, {r1-r4} @ push old task's r0-r3 189 | stmfd sp!, {r0} @ push old task's cpsr 190 | 191 | ldr r4, =rt_interrupt_from_thread 192 | ldr r5, [r4] 193 | str sp, [r5] @ store sp in preempted tasks's TCB 194 | 195 | ldr r6, =rt_interrupt_to_thread 196 | ldr r6, [r6] 197 | ldr sp, [r6] @ get new task's stack pointer 198 | 199 | ldmfd sp!, {r4} @ pop new task's cpsr to spsr 200 | msr spsr_cxsf, r4 201 | 202 | ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr 203 | 204 | .macro push_svc_reg 205 | sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */ 206 | stmia sp, {r0 - r12} @/* Calling r0-r12 */ 207 | mov r0, sp 208 | mrs r6, spsr @/* Save CPSR */ 209 | str lr, [r0, #15*4] @/* Push PC */ 210 | str r6, [r0, #16*4] @/* Push CPSR */ 211 | cps #Mode_SVC 212 | str sp, [r0, #13*4] @/* Save calling SP */ 213 | str lr, [r0, #14*4] @/* Save calling PC */ 214 | .endm 215 | 216 | .align 5 217 | .globl vector_swi 218 | vector_swi: 219 | push_svc_reg 220 | bl rt_hw_trap_swi 221 | b . 222 | 223 | .align 5 224 | .globl vector_undef 225 | vector_undef: 226 | push_svc_reg 227 | bl rt_hw_trap_undef 228 | b . 229 | 230 | .align 5 231 | .globl vector_pabt 232 | vector_pabt: 233 | push_svc_reg 234 | bl rt_hw_trap_pabt 235 | b . 236 | 237 | .align 5 238 | .globl vector_dabt 239 | vector_dabt: 240 | push_svc_reg 241 | bl rt_hw_trap_dabt 242 | b . 243 | 244 | .align 5 245 | .globl vector_resv 246 | vector_resv: 247 | push_svc_reg 248 | bl rt_hw_trap_resv 249 | b . 250 | -------------------------------------------------------------------------------- /vexpress/cpu/trap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : trap.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Develop Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2013-07-20 Bernard first version 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "armv7.h" 20 | 21 | #ifdef RT_USING_VMM 22 | #include 23 | #endif 24 | 25 | #include "gic.h" 26 | 27 | extern struct rt_thread *rt_current_thread; 28 | #ifdef RT_USING_FINSH 29 | extern long list_thread(void); 30 | #endif 31 | 32 | /** 33 | * this function will show registers of CPU 34 | * 35 | * @param regs the registers point 36 | */ 37 | void rt_hw_show_register(struct rt_hw_exp_stack *regs) 38 | { 39 | rt_kprintf("Execption:\n"); 40 | rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3); 41 | rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7); 42 | rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10); 43 | rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip); 44 | rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc); 45 | rt_kprintf("cpsr:0x%08x\n", regs->cpsr); 46 | } 47 | 48 | /** 49 | * When comes across an instruction which it cannot handle, 50 | * it takes the undefined instruction trap. 51 | * 52 | * @param regs system registers 53 | * 54 | * @note never invoke this function in application 55 | */ 56 | void rt_hw_trap_undef(struct rt_hw_exp_stack *regs) 57 | { 58 | rt_kprintf("undefined instruction:\n"); 59 | rt_hw_show_register(regs); 60 | #ifdef RT_USING_FINSH 61 | list_thread(); 62 | #endif 63 | rt_hw_cpu_shutdown(); 64 | } 65 | 66 | /** 67 | * The software interrupt instruction (SWI) is used for entering 68 | * Supervisor mode, usually to request a particular supervisor 69 | * function. 70 | * 71 | * @param regs system registers 72 | * 73 | * @note never invoke this function in application 74 | */ 75 | void rt_hw_trap_swi(struct rt_hw_exp_stack *regs) 76 | { 77 | rt_kprintf("software interrupt:\n"); 78 | rt_hw_show_register(regs); 79 | #ifdef RT_USING_FINSH 80 | list_thread(); 81 | #endif 82 | rt_hw_cpu_shutdown(); 83 | } 84 | 85 | /** 86 | * An abort indicates that the current memory access cannot be completed, 87 | * which occurs during an instruction prefetch. 88 | * 89 | * @param regs system registers 90 | * 91 | * @note never invoke this function in application 92 | */ 93 | void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs) 94 | { 95 | rt_kprintf("prefetch abort:\n"); 96 | rt_hw_show_register(regs); 97 | #ifdef RT_USING_FINSH 98 | list_thread(); 99 | #endif 100 | rt_hw_cpu_shutdown(); 101 | } 102 | 103 | /** 104 | * An abort indicates that the current memory access cannot be completed, 105 | * which occurs during a data access. 106 | * 107 | * @param regs system registers 108 | * 109 | * @note never invoke this function in application 110 | */ 111 | void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs) 112 | { 113 | rt_kprintf("data abort:"); 114 | rt_hw_show_register(regs); 115 | #ifdef RT_USING_FINSH 116 | list_thread(); 117 | #endif 118 | rt_hw_cpu_shutdown(); 119 | } 120 | 121 | /** 122 | * Normally, system will never reach here 123 | * 124 | * @param regs system registers 125 | * 126 | * @note never invoke this function in application 127 | */ 128 | void rt_hw_trap_resv(struct rt_hw_exp_stack *regs) 129 | { 130 | rt_kprintf("reserved trap:\n"); 131 | rt_hw_show_register(regs); 132 | #ifdef RT_USING_FINSH 133 | list_thread(); 134 | #endif 135 | rt_hw_cpu_shutdown(); 136 | } 137 | 138 | #define GIC_ACK_INTID_MASK 0x000003ff 139 | 140 | void rt_hw_trap_irq(void) 141 | { 142 | void *param; 143 | unsigned long ir; 144 | unsigned long fullir; 145 | rt_isr_handler_t isr_func; 146 | extern struct rt_irq_desc isr_table[]; 147 | 148 | fullir = arm_gic_get_active_irq(0); 149 | ir = fullir & GIC_ACK_INTID_MASK; 150 | 151 | if (ir == 1023) 152 | { 153 | /* Spurious interrupt */ 154 | return; 155 | } 156 | 157 | /* get interrupt service routine */ 158 | isr_func = isr_table[ir].handler; 159 | #ifdef RT_USING_INTERRUPT_INFO 160 | isr_table[ir].counter++; 161 | #endif 162 | if (isr_func) 163 | { 164 | /* Interrupt for myself. */ 165 | param = isr_table[ir].param; 166 | /* turn to interrupt service routine */ 167 | isr_func(ir, param); 168 | } 169 | #ifdef RT_USING_VMM 170 | else 171 | { 172 | /* We have to EOI before masking the interrupts */ 173 | arm_gic_ack(0, fullir); 174 | vmm_virq_pending(ir); 175 | return; 176 | } 177 | #endif 178 | 179 | /* end of interrupt */ 180 | arm_gic_ack(0, fullir); 181 | } 182 | 183 | void rt_hw_trap_fiq(void) 184 | { 185 | void *param; 186 | unsigned long ir; 187 | unsigned long fullir; 188 | rt_isr_handler_t isr_func; 189 | extern struct rt_irq_desc isr_table[]; 190 | 191 | fullir = arm_gic_get_active_irq(0); 192 | ir = fullir & GIC_ACK_INTID_MASK; 193 | 194 | /* get interrupt service routine */ 195 | isr_func = isr_table[ir].handler; 196 | param = isr_table[ir].param; 197 | 198 | /* turn to interrupt service routine */ 199 | isr_func(ir, param); 200 | 201 | /* end of interrupt */ 202 | arm_gic_ack(0, fullir); 203 | } 204 | 205 | -------------------------------------------------------------------------------- /vexpress/cpu/vector_gcc.S: -------------------------------------------------------------------------------- 1 | /* 2 | * File : vector_gcc.S 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Development Team 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | * 20 | * Change Logs: 21 | * Date Author Notes 22 | * 2013-07-05 Bernard the first version 23 | */ 24 | 25 | .section .vectors, "ax" 26 | .code 32 27 | 28 | .globl system_vectors 29 | system_vectors: 30 | ldr pc, _vector_reset 31 | ldr pc, _vector_undef 32 | ldr pc, _vector_swi 33 | ldr pc, _vector_pabt 34 | ldr pc, _vector_dabt 35 | ldr pc, _vector_resv 36 | ldr pc, _vector_irq 37 | ldr pc, _vector_fiq 38 | 39 | .globl _reset 40 | .globl vector_undef 41 | .globl vector_swi 42 | .globl vector_pabt 43 | .globl vector_dabt 44 | .globl vector_resv 45 | .globl vector_irq 46 | .globl vector_fiq 47 | 48 | _vector_reset: 49 | .word _reset 50 | _vector_undef: 51 | .word vector_undef 52 | _vector_swi: 53 | .word vector_swi 54 | _vector_pabt: 55 | .word vector_pabt 56 | _vector_dabt: 57 | .word vector_dabt 58 | _vector_resv: 59 | .word vector_resv 60 | _vector_irq: 61 | .word vector_irq 62 | _vector_fiq: 63 | .word vector_fiq 64 | 65 | .balignl 16,0xdeadbeef 66 | -------------------------------------------------------------------------------- /vexpress/drivers/SConscript: -------------------------------------------------------------------------------- 1 | import copy 2 | Import('RTT_ROOT') 3 | Import('rtconfig') 4 | from building import * 5 | 6 | cwd = GetCurrentDir() 7 | src = Glob('*.c') 8 | 9 | CPPPATH = [cwd] 10 | 11 | group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) 12 | 13 | Return('group') 14 | -------------------------------------------------------------------------------- /vexpress/drivers/board.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File : board.c 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2012, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2012-11-20 Bernard the first version 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "board.h" 20 | 21 | #define TIMER_LOAD(hw_base) __REG32(hw_base + 0x00) 22 | #define TIMER_VALUE(hw_base) __REG32(hw_base + 0x04) 23 | #define TIMER_CTRL(hw_base) __REG32(hw_base + 0x08) 24 | #define TIMER_CTRL_ONESHOT (1 << 0) 25 | #define TIMER_CTRL_32BIT (1 << 1) 26 | #define TIMER_CTRL_DIV1 (0 << 2) 27 | #define TIMER_CTRL_DIV16 (1 << 2) 28 | #define TIMER_CTRL_DIV256 (2 << 2) 29 | #define TIMER_CTRL_IE (1 << 5) /* Interrupt Enable (versatile only) */ 30 | #define TIMER_CTRL_PERIODIC (1 << 6) 31 | #define TIMER_CTRL_ENABLE (1 << 7) 32 | 33 | #define TIMER_INTCLR(hw_base) __REG32(hw_base + 0x0c) 34 | #define TIMER_RIS(hw_base) __REG32(hw_base + 0x10) 35 | #define TIMER_MIS(hw_base) __REG32(hw_base + 0x14) 36 | #define TIMER_BGLOAD(hw_base) __REG32(hw_base + 0x18) 37 | 38 | #define SYS_CTRL __REG32(REALVIEW_SCTL_BASE) 39 | 40 | #define TIMER_HW_BASE REALVIEW_TIMER2_3_BASE 41 | 42 | void rt_hw_timer_ack(void) 43 | { 44 | /* clear interrupt */ 45 | TIMER_INTCLR(TIMER_HW_BASE) = 0x01; 46 | } 47 | 48 | static void rt_hw_timer_isr(int vector, void *param) 49 | { 50 | rt_tick_increase(); 51 | 52 | rt_hw_timer_ack(); 53 | } 54 | 55 | int rt_hw_timer_init(void) 56 | { 57 | rt_uint32_t val; 58 | 59 | SYS_CTRL |= REALVIEW_REFCLK; 60 | 61 | /* Setup Timer0 for generating irq */ 62 | val = TIMER_CTRL(TIMER_HW_BASE); 63 | val &= ~TIMER_CTRL_ENABLE; 64 | val |= (TIMER_CTRL_32BIT | TIMER_CTRL_PERIODIC | TIMER_CTRL_IE); 65 | TIMER_CTRL(TIMER_HW_BASE) = val; 66 | 67 | TIMER_LOAD(TIMER_HW_BASE) = 1000; 68 | 69 | /* enable timer */ 70 | TIMER_CTRL(TIMER_HW_BASE) |= TIMER_CTRL_ENABLE; 71 | 72 | rt_hw_interrupt_install(IRQ_PBA8_TIMER2_3, rt_hw_timer_isr, RT_NULL, "tick"); 73 | rt_hw_interrupt_umask(IRQ_PBA8_TIMER2_3); 74 | 75 | return 0; 76 | } 77 | INIT_BOARD_EXPORT(rt_hw_timer_init); 78 | 79 | /** 80 | * This function will initialize beaglebone board 81 | */ 82 | void rt_hw_board_init(void) 83 | { 84 | rt_components_board_init(); 85 | rt_console_set_device(RT_CONSOLE_DEVICE_NAME); 86 | } 87 | 88 | /*@}*/ 89 | -------------------------------------------------------------------------------- /vexpress/drivers/board.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File : board.h 3 | * This file is part of RT-Thread RTOS 4 | * COPYRIGHT (C) 2013, RT-Thread Development Team 5 | * 6 | * The license and distribution terms for this file may be 7 | * found in the file LICENSE in this distribution or at 8 | * http://www.rt-thread.org/license/LICENSE 9 | * 10 | * Change Logs: 11 | * Date Author Notes 12 | * 2013-07-06 Bernard the first version 13 | */ 14 | 15 | #ifndef __BOARD_H__ 16 | #define __BOARD_H__ 17 | 18 | #include 19 | 20 | #if defined(__CC_ARM) 21 | extern int Image$$RW_IRAM1$$ZI$$Limit; 22 | #define HEAP_BEGIN ((void*)&Image$$RW_IRAM1$$ZI$$Limit) 23 | #elif defined(__GNUC__) 24 | extern int __bss_end; 25 | #define HEAP_BEGIN ((void*)&__bss_end) 26 | #endif 27 | 28 | #define HEAP_END (void*)(0x70000000) 29 | 30 | void rt_hw_board_init(void); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /vexpress/drivers/serial.c: -------------------------------------------------------------------------------- 1 | /* 2 | * serial.c UART driver 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * Maintainer: bernard.xiong 8 | * 9 | * All rights reserved. 10 | * 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation; either version 2 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License along 22 | * with this program; if not, write to the Free Software Foundation, Inc., 23 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 24 | * 25 | * Change Logs: 26 | * Date Author Notes 27 | * 2013-03-30 Bernard the first verion 28 | */ 29 | 30 | #include 31 | #include 32 | 33 | #include "serial.h" 34 | 35 | struct hw_uart_device 36 | { 37 | rt_uint32_t hw_base; 38 | rt_uint32_t irqno; 39 | }; 40 | 41 | #define UART_DR(base) __REG32(base + 0x00) 42 | #define UART_FR(base) __REG32(base + 0x18) 43 | #define UART_CR(base) __REG32(base + 0x30) 44 | #define UART_IMSC(base) __REG32(base + 0x38) 45 | #define UART_ICR(base) __REG32(base + 0x44) 46 | 47 | #define UARTFR_RXFE 0x10 48 | #define UARTFR_TXFF 0x20 49 | #define UARTIMSC_RXIM 0x10 50 | #define UARTIMSC_TXIM 0x20 51 | #define UARTICR_RXIC 0x10 52 | #define UARTICR_TXIC 0x20 53 | 54 | static void rt_hw_uart_isr(int irqno, void *param) 55 | { 56 | struct rt_serial_device *serial = (struct rt_serial_device *)param; 57 | 58 | rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); 59 | } 60 | 61 | static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) 62 | { 63 | return RT_EOK; 64 | } 65 | 66 | static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg) 67 | { 68 | struct hw_uart_device *uart; 69 | 70 | RT_ASSERT(serial != RT_NULL); 71 | uart = (struct hw_uart_device *)serial->parent.user_data; 72 | 73 | switch (cmd) 74 | { 75 | case RT_DEVICE_CTRL_CLR_INT: 76 | /* disable rx irq */ 77 | UART_IMSC(uart->hw_base) &= ~UARTIMSC_RXIM; 78 | break; 79 | 80 | case RT_DEVICE_CTRL_SET_INT: 81 | /* enable rx irq */ 82 | UART_IMSC(uart->hw_base) |= UARTIMSC_RXIM; 83 | rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, serial, "uart"); 84 | rt_hw_interrupt_umask(uart->irqno); 85 | break; 86 | } 87 | 88 | return RT_EOK; 89 | } 90 | 91 | static int uart_putc(struct rt_serial_device *serial, char c) 92 | { 93 | struct hw_uart_device *uart; 94 | 95 | RT_ASSERT(serial != RT_NULL); 96 | uart = (struct hw_uart_device *)serial->parent.user_data; 97 | 98 | while (UART_FR(uart->hw_base) & UARTFR_TXFF); 99 | UART_DR(uart->hw_base) = c; 100 | 101 | return 1; 102 | } 103 | 104 | static int uart_getc(struct rt_serial_device *serial) 105 | { 106 | int ch; 107 | struct hw_uart_device *uart; 108 | 109 | RT_ASSERT(serial != RT_NULL); 110 | uart = (struct hw_uart_device *)serial->parent.user_data; 111 | 112 | ch = -1; 113 | if (!(UART_FR(uart->hw_base) & UARTFR_RXFE)) 114 | { 115 | ch = UART_DR(uart->hw_base) & 0xff; 116 | } 117 | 118 | return ch; 119 | } 120 | 121 | static const struct rt_uart_ops _uart_ops = 122 | { 123 | uart_configure, 124 | uart_control, 125 | uart_putc, 126 | uart_getc, 127 | }; 128 | 129 | #ifdef RT_USING_UART0 130 | /* UART device driver structure */ 131 | static struct hw_uart_device _uart0_device = 132 | { 133 | REALVIEW_UART0_BASE, 134 | IRQ_PBA8_UART0, 135 | }; 136 | static struct rt_serial_device _serial0; 137 | #endif 138 | 139 | #ifdef RT_USING_UART1 140 | /* UART1 device driver structure */ 141 | static struct hw_uart_device _uart1_device = 142 | { 143 | REALVIEW_UART1_BASE, 144 | IRQ_PBA8_UART1, 145 | }; 146 | static struct rt_serial_device _serial1; 147 | #endif 148 | 149 | int uart_isr_test(void) 150 | { 151 | return uart_getc(&_serial1); 152 | } 153 | 154 | int rt_hw_uart_init(void) 155 | { 156 | struct hw_uart_device *uart; 157 | struct serial_configure config; 158 | 159 | config.baud_rate = BAUD_RATE_115200; 160 | config.bit_order = BIT_ORDER_LSB; 161 | config.data_bits = DATA_BITS_8; 162 | config.parity = PARITY_NONE; 163 | config.stop_bits = STOP_BITS_1; 164 | config.invert = NRZ_NORMAL; 165 | config.bufsz = RT_SERIAL_RB_BUFSZ; 166 | 167 | #ifdef RT_USING_UART0 168 | uart = &_uart0_device; 169 | 170 | _serial0.ops = &_uart_ops; 171 | _serial0.config = config; 172 | 173 | /* register UART1 device */ 174 | rt_hw_serial_register(&_serial0, "uart0", 175 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, 176 | uart); 177 | /* enable Rx and Tx of UART */ 178 | UART_CR(uart->hw_base) = (1 << 0) | (1 << 8) | (1 << 9); 179 | #endif 180 | 181 | #ifdef RT_USING_UART1 182 | uart = &_uart1_device; 183 | _serial1.ops = &_uart_ops; 184 | _serial1.config = config; 185 | 186 | /* register UART1 device */ 187 | rt_hw_serial_register(&_serial1, "uart1", 188 | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); 189 | /* enable Rx and Tx of UART */ 190 | UART_CR(uart->hw_base) = (1 << 0) | (1 << 8) | (1 << 9); 191 | #endif 192 | 193 | return 0; 194 | } 195 | INIT_BOARD_EXPORT(rt_hw_uart_init); 196 | -------------------------------------------------------------------------------- /vexpress/drivers/serial.h: -------------------------------------------------------------------------------- 1 | /* 2 | * UART driver 3 | * 4 | * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * Maintainer: bernard.xiong 8 | * 9 | * All rights reserved. 10 | * 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation; either version 2 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License along 22 | * with this program; if not, write to the Free Software Foundation, Inc., 23 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 24 | * 25 | * Change Logs: 26 | * Date Author Notes 27 | * 2013-03-30 Bernard the first verion 28 | */ 29 | 30 | #ifndef __UART_H__ 31 | #define __UART_H__ 32 | 33 | #include 34 | 35 | int rt_hw_uart_init(void); 36 | 37 | #endif 38 | 39 | 40 | -------------------------------------------------------------------------------- /vexpress/drivers/vbus_conf.h: -------------------------------------------------------------------------------- 1 | #ifndef __VBUS_CONF_H__ 2 | #define __VBUS_CONF_H__ 3 | 4 | /* This is configures where the rings are located. */ 5 | 6 | #define _RT_VBUS_RING_BASE (0x6f800000) 7 | #define _RT_VBUS_RING_SZ (2 * 1024 * 1024) 8 | 9 | /* Number of blocks in VBus. The total size of VBus is 10 | * RT_VMM_RB_BLK_NR * 64byte * 2. */ 11 | #define RT_VMM_RB_BLK_NR (_RT_VBUS_RING_SZ / 64 - 1) 12 | 13 | /* We don't use the IRQ number to trigger IRQ in this BSP. */ 14 | #define RT_VBUS_GUEST_VIRQ 14 15 | #define RT_VBUS_HOST_VIRQ 15 16 | 17 | #define RT_VBUS_SHELL_DEV_NAME "vbser0" 18 | #define RT_VBUS_RFS_DEV_NAME "rfs" 19 | 20 | #endif /* end of include guard: __VBUS_CONF_H__ */ 21 | 22 | -------------------------------------------------------------------------------- /vexpress/drivers/vbus_drv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * VMM Bus Driver 3 | * 4 | * COPYRIGHT (C) 2015, Shanghai Real-Thread Technology Co., Ltd 5 | * http://www.rt-thread.com 6 | * 7 | * This file is part of RT-Thread (http://www.rt-thread.org) 8 | * 9 | * All rights reserved. 10 | * 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation; either version 2 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License along 22 | * with this program; if not, write to the Free Software Foundation, Inc., 23 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 24 | * 25 | * Change Logs: 26 | * Date Author Notes 27 | * 2015-01-07 Grissiom add comment 28 | */ 29 | 30 | #include 31 | 32 | #ifdef RT_USING_VBUS 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | int rt_vbus_do_init(void) 40 | { 41 | return rt_vbus_init((void*)_RT_VBUS_RING_BASE, 42 | (void*)(_RT_VBUS_RING_BASE + _RT_VBUS_RING_SZ)); 43 | } 44 | INIT_COMPONENT_EXPORT(rt_vbus_do_init); 45 | 46 | static void _bus_resume_in_thread(int irqnr, void *param) 47 | { 48 | rt_vbus_isr(irqnr, RT_NULL); 49 | } 50 | 51 | int rt_vbus_hw_init(void) 52 | { 53 | rt_kprintf("install irq: %d\n", RT_VBUS_HOST_VIRQ); 54 | rt_hw_interrupt_install(RT_VBUS_HOST_VIRQ, 55 | _bus_resume_in_thread, RT_NULL, 56 | "vbusin"); 57 | rt_hw_interrupt_umask(RT_VBUS_HOST_VIRQ); 58 | 59 | return 0; 60 | } 61 | 62 | int rt_vbus_hw_eoi(int irqnr, void *param) 63 | { 64 | rt_hw_interrupt_clear(irqnr); 65 | 66 | return 0; 67 | } 68 | 69 | #define RT_VBUS_SER_PRIO 20 70 | #define RT_VBUS_RFS_PRIO 19 71 | #define RT_VBUS_TASK2_PRIO 6 72 | #define RT_VBUS_INT_PRIO 4 73 | 74 | struct rt_vbus_dev rt_vbus_chn_devx[] = { 75 | { 76 | .req = 77 | { 78 | .prio = RT_VBUS_SER_PRIO, 79 | .name = RT_VBUS_SHELL_DEV_NAME, 80 | .is_server = 1, 81 | .recv_wm.low = RT_VMM_RB_BLK_NR / 3, 82 | .recv_wm.high = RT_VMM_RB_BLK_NR * 2 / 3, 83 | .post_wm.low = RT_VMM_RB_BLK_NR / 3, 84 | .post_wm.high = RT_VMM_RB_BLK_NR * 2 / 3, 85 | } 86 | }, 87 | { 88 | .req = 89 | { 90 | .prio = 23, 91 | .name = RT_VBUS_RFS_DEV_NAME, 92 | .is_server = 0, 93 | .recv_wm.low = RT_VMM_RB_BLK_NR / 3, 94 | .recv_wm.high = RT_VMM_RB_BLK_NR * 2 / 3, 95 | .post_wm.low = RT_VMM_RB_BLK_NR / 3, 96 | .post_wm.high = RT_VMM_RB_BLK_NR * 2 / 3, 97 | } 98 | }, 99 | { 100 | .req = 101 | { 102 | .prio = 30, 103 | .name = "vecho", 104 | .is_server = 1, 105 | .recv_wm.low = RT_VMM_RB_BLK_NR / 3, 106 | .recv_wm.high = RT_VMM_RB_BLK_NR * 2 / 3, 107 | .post_wm.low = RT_VMM_RB_BLK_NR / 3, 108 | .post_wm.high = RT_VMM_RB_BLK_NR * 2 / 3, 109 | } 110 | }, 111 | { 112 | .req = 113 | { 114 | .name = RT_NULL, 115 | } 116 | }, 117 | }; 118 | 119 | #endif /* RT_USING_VBUS */ 120 | 121 | -------------------------------------------------------------------------------- /vexpress/drivers/vbus_hw.h: -------------------------------------------------------------------------------- 1 | /* 2 | * VMM Bus 3 | * 4 | * COPYRIGHT (C) 2015, Shanghai Real-Thread Technology Co., Ltd 5 | * 6 | * This file is part of RT-Thread (http://www.rt-thread.org) 7 | * 8 | * All rights reserved. 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | * 24 | * Change Logs: 25 | * Date Author Notes 26 | * 2015-01-07 Grissiom init commit 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | rt_inline void rt_vbus_tick(unsigned int target_cpu, unsigned int irqnr) 34 | { 35 | arm_gic_trigger(0, 1, irqnr); 36 | } 37 | 38 | /* Read memory barrier. */ 39 | rt_inline void rt_vbus_smp_rmb(void) 40 | { 41 | asm volatile ("dsb" : : : "memory"); 42 | } 43 | 44 | /* Write memory barrier. */ 45 | rt_inline void rt_vbus_smp_wmb(void) 46 | { 47 | asm volatile ("dsb" : : : "memory"); 48 | } 49 | 50 | /* General memory barrier. */ 51 | rt_inline void rt_vbus_smp_mb(void) 52 | { 53 | asm volatile ("dsb" : : : "memory"); 54 | } 55 | -------------------------------------------------------------------------------- /vexpress/drivers/vbus_local_conf.h: -------------------------------------------------------------------------------- 1 | #ifndef __VBUS_LOCAL_CONF_H__ 2 | #define __VBUS_LOCAL_CONF_H__ 3 | 4 | #define RT_VBUS_USING_FLOW_CONTROL 5 | 6 | #define RT_VBUS_USING_TESTS 7 | 8 | #endif /* end of include guard: __VBUS_LOCAL_CONF_H__ */ 9 | -------------------------------------------------------------------------------- /vexpress/qemu.sh: -------------------------------------------------------------------------------- 1 | qemu-system-arm -M vexpress-a9 -cpu cortex-a9 -m 256M -kernel rtthread-vexpress.elf -serial vc -serial vc 2 | -------------------------------------------------------------------------------- /vexpress/rtconfig.h: -------------------------------------------------------------------------------- 1 | /* RT-Thread config file */ 2 | #ifndef __RTTHREAD_CFG_H__ 3 | #define __RTTHREAD_CFG_H__ 4 | 5 | // 6 | 7 | // 8 | #define RT_NAME_MAX 6 9 | // 10 | #define RT_ALIGN_SIZE 4 11 | // 12 | // 8 13 | // 32 14 | // 256 15 | // 16 | #define RT_THREAD_PRIORITY_MAX 32 17 | // 18 | #define RT_TICK_PER_SECOND 1000 19 | // 20 | #define IDLE_THREAD_STACK_SIZE 512 21 | //
22 | #define RT_DEBUG 23 | // 24 | // #define RT_DEBUG_SCHEDULER 1 25 | // 26 | #define RT_USING_OVERFLOW_CHECK 27 | //
28 | 29 | // 30 | #define RT_USING_HOOK 31 | //
32 | // #define RT_USING_TIMER_SOFT 33 | // 34 | #define RT_TIMER_THREAD_PRIO 4 35 | // 36 | #define RT_TIMER_THREAD_STACK_SIZE 512 37 | // 38 | #define RT_TIMER_TICK_PER_SECOND 10 39 | //
40 | 41 | //
42 | // 43 | #define RT_USING_SEMAPHORE 44 | // 45 | #define RT_USING_MUTEX 46 | // 47 | #define RT_USING_EVENT 48 | // 49 | #define RT_USING_MAILBOX 50 | // 51 | #define RT_USING_MESSAGEQUEUE 52 | //
53 | 54 | //
55 | // 56 | #define RT_USING_MEMPOOL 57 | // 58 | // #define RT_USING_MEMHEAP 59 | // 60 | #define RT_USING_HEAP 61 | // 62 | // #define RT_USING_MEMHEAP_AS_HEAP 63 | // 64 | #define RT_USING_SMALL_MEM 65 | // 66 | // #define RT_USING_SLAB 67 | //
68 | 69 | //
70 | #define RT_USING_DEVICE 71 | // 72 | #define RT_USING_DEVICE_IPC 73 | // 74 | #define RT_USING_SERIAL 75 | // 76 | #define RT_UART_RX_BUFFER_SIZE 64 77 | // 78 | #define RT_USING_INTERRUPT_INFO 79 | // 80 | // #define RT_USING_UART0 81 | // 82 | #define RT_USING_UART1 83 | //
84 | 85 | //
86 | #define RT_USING_CONSOLE 87 | // 88 | #define RT_CONSOLEBUF_SIZE 128 89 | // 90 | #define RT_CONSOLE_DEVICE_NAME "uart1" 91 | //
92 | 93 | // 94 | #define RT_USING_COMPONENTS_INIT 95 | //
96 | #define RT_USING_FINSH 97 | // 98 | #define FINSH_USING_MSH 99 | // 100 | #define FINSH_USING_MSH_DEFAULT 101 | // 102 | #define FINSH_USING_SYMTAB 103 | // 104 | #define FINSH_USING_DESCRIPTION 105 | // 106 | #define FINSH_THREAD_STACK_SIZE 4096 107 | //
108 | 109 | //
110 | // 111 | #define RT_USING_LIBC 112 | // 113 | #define RT_USING_PTHREADS 114 | //
115 | 116 | //
117 | // #define RT_USING_DFS 118 | // 119 | #define DFS_USING_WORKDIR 120 | // 121 | #define DFS_FILESYSTEMS_MAX 2 122 | // 123 | #define DFS_FD_MAX 4 124 | // 125 | // #define RT_USING_DFS_ELMFAT 126 | // 127 | // 1 128 | // 2 129 | // 130 | #define RT_DFS_ELM_USE_LFN 1 131 | // 132 | #define RT_DFS_ELM_MAX_LFN 64 133 | // 134 | // #define RT_USING_DFS_YAFFS2 135 | // 136 | // #define RT_USING_DFS_UFFS 137 | // 138 | #define RT_USING_DFS_DEVFS 139 | // 140 | // #define RT_USING_DFS_NFS 141 | // 142 | #define RT_NFS_HOST_EXPORT "192.168.1.5:/" 143 | //
144 | 145 | // 146 | #define RT_USING_VBUS 147 | 148 | #define RT_USING_LOGTRACE 149 | 150 | //
151 | 152 | #endif 153 | -------------------------------------------------------------------------------- /vexpress/rtconfig.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # toolchains options 4 | ARCH='arm' 5 | CPU='vexpress-a9' 6 | CROSS_TOOL='gcc' 7 | 8 | if os.getenv('RTT_CC'): 9 | CROSS_TOOL = os.getenv('RTT_CC') 10 | 11 | if CROSS_TOOL == 'gcc': 12 | PLATFORM = 'gcc' 13 | # EXEC_PATH = r'/opt/arm-2012.09/bin' 14 | EXEC_PATH = r'C:\Program Files (x86)\CodeSourcery\Sourcery_CodeBench_Lite_for_ARM_EABI\bin' 15 | EXEC_PATH = '/opt/gcc-arm-none-eabi-4_8-2014q1_gri/bin' 16 | elif CROSS_TOOL == 'keil': 17 | PLATFORM = 'armcc' 18 | EXEC_PATH = 'C:/Keil' 19 | 20 | if os.getenv('RTT_EXEC_PATH'): 21 | EXEC_PATH = os.getenv('RTT_EXEC_PATH') 22 | 23 | BUILD = 'debug' 24 | 25 | if PLATFORM == 'gcc': 26 | # toolchains 27 | PREFIX = 'arm-none-eabi-' 28 | CC = PREFIX + 'gcc' 29 | CXX = PREFIX + 'g++' 30 | AS = PREFIX + 'gcc' 31 | AR = PREFIX + 'ar' 32 | LINK = PREFIX + 'gcc' 33 | TARGET_EXT = 'elf' 34 | SIZE = PREFIX + 'size' 35 | OBJDUMP = PREFIX + 'objdump' 36 | OBJCPY = PREFIX + 'objcopy' 37 | 38 | DEVICE = ' -march=armv7-a -mtune=cortex-a9 -mfpu=vfpv3-d16 -ftree-vectorize -ffast-math -mfloat-abi=softfp' 39 | CFLAGS = DEVICE + ' -Wall' 40 | AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__' 41 | LINK_SCRIPT = 'vexpress.lds' 42 | LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=vexpress.map,-cref,-u,system_vectors'+\ 43 | ' -T %s' % LINK_SCRIPT 44 | 45 | CPATH = '' 46 | LPATH = '' 47 | 48 | # generate debug info in all cases 49 | AFLAGS += ' -gdwarf-2' 50 | CFLAGS += ' -g -gdwarf-2' 51 | 52 | if BUILD == 'debug': 53 | CFLAGS += ' -O0' 54 | else: 55 | CFLAGS += ' -O2' 56 | 57 | POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' +\ 58 | SIZE + ' $TARGET \n' 59 | 60 | elif PLATFORM == 'armcc': 61 | # toolchains 62 | CC = 'armcc' 63 | CXX = 'armcc' 64 | AS = 'armasm' 65 | AR = 'armar' 66 | LINK = 'armlink' 67 | TARGET_EXT = 'axf' 68 | 69 | DEVICE = ' --device DARMP' 70 | CFLAGS = DEVICE + ' --apcs=interwork' 71 | AFLAGS = DEVICE 72 | LFLAGS = DEVICE + ' --info sizes --info totals --info unused --info veneers --list rtthread-vexpress.map --scatter vexpress.sct' 73 | 74 | CFLAGS += ' -I' + EXEC_PATH + '/ARM/RV31/INC' 75 | LFLAGS += ' --libpath ' + EXEC_PATH + '/ARM/RV31/LIB' 76 | 77 | EXEC_PATH += '/arm/bin40/' 78 | 79 | if BUILD == 'debug': 80 | CFLAGS += ' -g -O0' 81 | AFLAGS += ' -g' 82 | else: 83 | CFLAGS += ' -O2' 84 | 85 | POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' 86 | 87 | elif PLATFORM == 'iar': 88 | # toolchains 89 | CC = 'iccarm' 90 | AS = 'iasmarm' 91 | AR = 'iarchive' 92 | LINK = 'ilinkarm' 93 | TARGET_EXT = 'out' 94 | 95 | DEVICE = ' --cpu DARMP' 96 | 97 | CFLAGS = '' 98 | AFLAGS = '' 99 | LFLAGS = ' --config vexpress.icf' 100 | 101 | EXEC_PATH += '/arm/bin/' 102 | RT_USING_MINILIBC = False 103 | POST_ACTION = '' 104 | -------------------------------------------------------------------------------- /vexpress/vexpress.lds: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 2 | OUTPUT_ARCH(arm) 3 | SECTIONS 4 | { 5 | . = 0x6FC00000; 6 | 7 | __text_start = .; 8 | .text : 9 | { 10 | *(.vectors) 11 | *(.text) 12 | *(.text.*) 13 | 14 | /* section information for finsh shell */ 15 | . = ALIGN(4); 16 | __fsymtab_start = .; 17 | KEEP(*(FSymTab)) 18 | __fsymtab_end = .; 19 | . = ALIGN(4); 20 | __vsymtab_start = .; 21 | KEEP(*(VSymTab)) 22 | __vsymtab_end = .; 23 | . = ALIGN(4); 24 | 25 | /* section information for modules */ 26 | . = ALIGN(4); 27 | __rtmsymtab_start = .; 28 | KEEP(*(RTMSymTab)) 29 | __rtmsymtab_end = .; 30 | 31 | /* section information for initialization */ 32 | . = ALIGN(4); 33 | __rt_init_start = .; 34 | KEEP(*(SORT(.rti_fn*))) 35 | __rt_init_end = .; 36 | } =0 37 | __text_end = .; 38 | 39 | __rodata_start = .; 40 | .rodata : { *(.rodata) *(.rodata.*) } 41 | __rodata_end = .; 42 | 43 | . = ALIGN(4); 44 | .ctors : 45 | { 46 | PROVIDE(__ctors_start__ = .); 47 | KEEP(*(SORT(.ctors.*))) 48 | KEEP(*(.ctors)) 49 | PROVIDE(__ctors_end__ = .); 50 | } 51 | 52 | .dtors : 53 | { 54 | PROVIDE(__dtors_start__ = .); 55 | KEEP(*(SORT(.dtors.*))) 56 | KEEP(*(.dtors)) 57 | PROVIDE(__dtors_end__ = .); 58 | } 59 | 60 | __data_start = .; 61 | . = ALIGN(4); 62 | .data : 63 | { 64 | *(.data) 65 | *(.data.*) 66 | } 67 | __data_end = .; 68 | 69 | . = ALIGN(4); 70 | __bss_start = __data_end; 71 | .bss : 72 | { 73 | *(.bss) 74 | *(.bss.*) 75 | *(COMMON) 76 | . = ALIGN(4); 77 | } 78 | . = ALIGN(4); 79 | __bss_end = .; 80 | 81 | /* Stabs debugging sections. */ 82 | .stab 0 : { *(.stab) } 83 | .stabstr 0 : { *(.stabstr) } 84 | .stab.excl 0 : { *(.stab.excl) } 85 | .stab.exclstr 0 : { *(.stab.exclstr) } 86 | .stab.index 0 : { *(.stab.index) } 87 | .stab.indexstr 0 : { *(.stab.indexstr) } 88 | .comment 0 : { *(.comment) } 89 | 90 | _end = .; 91 | } 92 | --------------------------------------------------------------------------------