1. [cpu] split ARM926 cpu code from AT91SAM9260 BSP

This commit is contained in:
ardafu 2015-04-14 21:56:34 +08:00
parent 2d1edc94a3
commit 39452b67b0
21 changed files with 1856 additions and 1159 deletions

View File

@ -47,17 +47,11 @@ extern void rt_application_init(void);
/*@{*/ /*@{*/
#if defined(__CC_ARM) #if defined(__CC_ARM)
extern int Image$$ER_ZI$$ZI$$Base;
extern int Image$$ER_ZI$$ZI$$Length;
extern int Image$$ER_ZI$$ZI$$Limit; extern int Image$$ER_ZI$$ZI$$Limit;
#elif (defined (__GNUC__)) #elif (defined (__GNUC__))
rt_uint8_t _irq_stack_start[1024]; extern unsigned char __bss_end__;
rt_uint8_t _fiq_stack_start[1024]; #elif (defined (__ICCARM__))
rt_uint8_t _undefined_stack_start[512]; #pragma section="HEAP"
rt_uint8_t _abort_stack_start[512];
rt_uint8_t _svc_stack_start[4096] SECTION(".nobss");
extern unsigned char __bss_start;
extern unsigned char __bss_end;
#endif #endif
#ifdef RT_USING_FINSH #ifdef RT_USING_FINSH
@ -98,8 +92,10 @@ void rtthread_startup(void)
/* initialize heap memory system */ /* initialize heap memory system */
#ifdef __CC_ARM #ifdef __CC_ARM
rt_system_heap_init((void*)&Image$$ER_ZI$$ZI$$Limit, (void*)0x24000000); rt_system_heap_init((void*)&Image$$ER_ZI$$ZI$$Limit, (void*)0x24000000);
#else #elif (defined (__GNUC__))
rt_system_heap_init((void*)&__bss_end, (void*)0x23f00000); rt_system_heap_init((void*)&__bss_end__, (void*)0x23f00000);
#elif (defined (__ICCARM__))
rt_system_heap_init(__section_begin("HEAP"),(void*)0x23f00000);
#endif #endif
#ifdef RT_USING_MODULE #ifdef RT_USING_MODULE

View File

@ -24,7 +24,7 @@
#include <rthw.h> #include <rthw.h>
#include "at91sam926x.h" #include "at91sam926x.h"
#include "interrupt.h"
#define MAX_HANDLERS (AIC_IRQS + PIN_IRQS) #define MAX_HANDLERS (AIC_IRQS + PIN_IRQS)
extern rt_uint32_t rt_interrupt_nest; extern rt_uint32_t rt_interrupt_nest;
@ -374,6 +374,53 @@ static int at91_aic_set_type(unsigned irq, unsigned type)
return 0; return 0;
} }
rt_uint32_t rt_hw_interrupt_get_active(rt_uint32_t fiq_irq, rt_uint32_t* id)
{
rt_uint32_t irqstat;
if (fiq_irq == INT_FIQ)
{
*id = 0;
}
else //IRQ
{
/* get irq number */
*id = (rt_uint32_t)at91_sys_read(AT91_AIC_IVR);
/* clear pending register */
irqstat = (rt_uint32_t)at91_sys_read(AT91_AIC_ISR);
}
return irqstat;
}
void rt_hw_interrupt_ack(rt_uint32_t fiq_irq)
{
if (fiq_irq == INT_FIQ)
{
/* new FIQ generation */
}
else
{
// EIOCR must be write any value after interrupt,
// or else can't response next interrupt
/* new IRQ generation */
at91_sys_write(AT91_AIC_EOICR, 0x55555555);
}
}
#ifdef RT_USING_FINSH #ifdef RT_USING_FINSH
void list_irq(void) void list_irq(void)
{ {

View File

@ -0,0 +1,25 @@
/*
* File : interrupt.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2011, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2013-07-06 Bernard first version
*/
#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__
#define INT_IRQ 0x00
#define INT_FIQ 0x01
rt_uint32_t rt_hw_interrupt_get_active(rt_uint32_t fiq_irq, rt_uint32_t* id);
void rt_hw_interrupt_ack(rt_uint32_t fiq_irq);
#endif

View File

@ -0,0 +1,7 @@
//;--------- Stack size of CPU modes -------------------------------------------
.equ UND_STK_SIZE, 2048
.equ SVC_STK_SIZE, 4096
.equ ABT_STK_SIZE, 2048
.equ IRQ_STK_SIZE, 4096
.equ FIQ_STK_SIZE, 4096
.equ SYS_STK_SIZE, 2048

View File

@ -0,0 +1,7 @@
;--------- Stack size of CPU modes --------------------------------------------
#define UND_STK_SIZE 512
#define SVC_STK_SIZE 4096
#define ABT_STK_SIZE 512
#define IRQ_STK_SIZE 1024
#define FIQ_STK_SIZE 1024
#define SYS_STK_SIZE 512

View File

@ -0,0 +1,27 @@
#define write_reg(a,v) (*(volatile unsigned int *)(a) = (v))
/* Processor Reset */
#define AT91_RSTC_PROCRST (1 << 0)
#define AT91_RSTC_PERRST (1 << 2)
#define AT91_RSTC_KEY (0xa5 << 24)
#define AT91_MATRIX_BASE (0XFFFFEE00)
/* Master Remap Control Register */
#define AT91_MATRIX_MRCR (AT91_MATRIX_BASE + 0x100)
/* Remap Command for AHB Master 0 (ARM926EJ-S InSTRuction Master) */
#define AT91_MATRIX_RCB0 (1 << 0)
/* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
#define AT91_MATRIX_RCB1 (1 << 1)
#define AT91_AIC_BASE (0XFFFFF000)
/* Interrupt DisaBLe Command Register */
#define AT91_AIC_IDCR (0x124)
/* Interrupt Clear Command Register */
#define AT91_AIC_ICCR (0x128)
void rt_low_level_init(void)
{
// Mask all IRQs by clearing all bits in the INTMRS
write_reg(AT91_AIC_BASE + AT91_AIC_IDCR, 0xFFFFFFFF);
write_reg(AT91_AIC_BASE + AT91_AIC_ICCR, 0xFFFFFFFF);
// Remap internal ram to 0x00000000 Address
write_reg(AT91_MATRIX_MRCR, AT91_MATRIX_RCB0 | AT91_MATRIX_RCB1);
}

View File

@ -0,0 +1,8 @@
;--------- Stack size of CPU modes --------------------------------------------
UND_STK_SIZE EQU 512
SVC_STK_SIZE EQU 4096
ABT_STK_SIZE EQU 512
IRQ_STK_SIZE EQU 1024
FIQ_STK_SIZE EQU 1024
SYS_STK_SIZE EQU 512
END

View File

@ -1,392 +0,0 @@
/*
* File : start.S
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2011-01-13 weety first version
*/
#define CONFIG_STACKSIZE 512
#define S_FRAME_SIZE 72
#define S_OLD_R0 68
#define S_PSR 64
#define S_PC 60
#define S_LR 56
#define S_SP 52
#define S_IP 48
#define S_FP 44
#define S_R10 40
#define S_R9 36
#define S_R8 32
#define S_R7 28
#define S_R6 24
#define S_R5 20
#define S_R4 16
#define S_R3 12
#define S_R2 8
#define S_R1 4
#define S_R0 0
.equ USERMODE, 0x10
.equ FIQMODE, 0x11
.equ IRQMODE, 0x12
.equ SVCMODE, 0x13
.equ ABORTMODE, 0x17
.equ UNDEFMODE, 0x1b
.equ MODEMASK, 0x1f
.equ NOINT, 0xc0
.equ RAM_BASE, 0x00000000 /*Start address of RAM */
.equ ROM_BASE, 0x20000000 /*Start address of Flash */
#define AT91_RSTC_PROCRST (1 << 0) /* Processor Reset */
#define AT91_RSTC_PERRST (1 << 2)
#define AT91_RSTC_KEY (0xa5 << 24)
#define AT91_MATRIX_BASE 0xffffee00
#define AT91_MATRIX_MRCR (AT91_MATRIX_BASE + 0x100) /* Master Remap Control Register */
#define AT91_MATRIX_RCB0 (1 << 0) /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
#define AT91_MATRIX_RCB1 (1 << 1) /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
#define AT91_AIC_BASE 0xfffff000
#define AT91_AIC_IDCR 0x124 /* Interrupt Disable Command Register */
#define AT91_AIC_ICCR 0x128 /* Interrupt Clear Command Register */
/*
*************************************************************************
*
* Jump vector table
*
*************************************************************************
*/
.section .init, "ax"
.code 32
.globl _start
_start:
b reset
ldr pc, _vector_undef
ldr pc, _vector_swi
ldr pc, _vector_pabt
ldr pc, _vector_dabt
ldr pc, _vector_resv
ldr pc, _vector_irq
ldr pc, _vector_fiq
_vector_undef: .word vector_undef
_vector_swi: .word vector_swi
_vector_pabt: .word vector_pabt
_vector_dabt: .word vector_dabt
_vector_resv: .word vector_resv
_vector_irq: .word vector_irq
_vector_fiq: .word vector_fiq
.balignl 16,0xdeadbeef
/*
*************************************************************************
*
* Startup Code (reset vector)
* relocate armboot to ram
* setup stack
* jump to second stage
*
*************************************************************************
*/
_TEXT_BASE:
.word TEXT_BASE
/*
* rtthread kernel start and end
* which are defined in linker script
*/
.globl _rtthread_start
_rtthread_start:
.word _start
.globl _rtthread_end
_rtthread_end:
.word _end
/*
* rtthread bss start and end which are defined in linker script
*/
.globl _bss_start
_bss_start:
.word __bss_start
.globl _bss_end
_bss_end:
.word __bss_end
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word _irq_stack_start + 1024
.globl FIQ_STACK_START
FIQ_STACK_START:
.word _fiq_stack_start + 1024
.globl UNDEFINED_STACK_START
UNDEFINED_STACK_START:
.word _undefined_stack_start + CONFIG_STACKSIZE
.globl ABORT_STACK_START
ABORT_STACK_START:
.word _abort_stack_start + CONFIG_STACKSIZE
.globl _STACK_START
_STACK_START:
.word _svc_stack_start + 4096
/* ----------------------------------entry------------------------------*/
reset:
/* set the cpu to SVC32 mode */
mrs r0,cpsr
bic r0,r0,#MODEMASK
orr r0,r0,#SVCMODE
msr cpsr,r0
/* mask all IRQs by clearing all bits in the INTMRs */
ldr r1, =AT91_AIC_BASE
ldr r0, =0xffffffff
str r0, [r1, #AT91_AIC_IDCR]
str r0, [r1, #AT91_AIC_ICCR]
/*remap internal ram to 0x00000000 address*/
ldr r0, =AT91_MATRIX_MRCR
ldr r1, =(AT91_MATRIX_RCB0|AT91_MATRIX_RCB1)
str r1, [r0]
/* set interrupt vector */
ldr r0, _TEXT_BASE
mov r1, #0x00
add r2, r0, #0x40 /* size, 32bytes */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
/* setup stack */
bl stack_setup
/* clear .bss */
mov r0,#0 /* get a zero */
ldr r1,=__bss_start /* bss start */
ldr r2,=__bss_end /* bss end */
bss_loop:
cmp r1,r2 /* check if data to clear */
strlo r0,[r1],#4 /* clear 4 bytes */
blo bss_loop /* loop until done */
/* call C++ constructors of global objects */
ldr r0, =__ctors_start__
ldr r1, =__ctors_end__
ctor_loop:
cmp r0, r1
beq ctor_end
ldr r2, [r0], #4
stmfd sp!, {r0-r1}
mov lr, pc
bx r2
ldmfd sp!, {r0-r1}
b ctor_loop
ctor_end:
/* start RT-Thread Kernel */
ldr pc, _rtthread_startup
_rtthread_startup:
.word rtthread_startup
#if defined (__FLASH_BUILD__)
_load_address:
.word ROM_BASE + _TEXT_BASE
#else
_load_address:
.word RAM_BASE + _TEXT_BASE
#endif
.global cpu_reset
cpu_reset:
ldr r0, =0xfffffd00
ldr r1, =(AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST)
str r1, [r0]
mov pc, lr
/*
*************************************************************************
*
* Interrupt handling
*
*************************************************************************
*/
/* exception handlers */
.align 5
vector_undef:
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} /* Calling r0-r12 */
add r8, sp, #S_PC
stmdb r8, {sp, lr}^ /* Calling SP, LR */
str lr, [r8, #0] /* Save calling PC */
mrs r6, spsr
str r6, [r8, #4] /* Save CPSR */
str r0, [r8, #8] /* Save OLD_R0 */
mov r0, sp
bl rt_hw_trap_udef
.align 5
vector_swi:
bl rt_hw_trap_swi
.align 5
vector_pabt:
bl rt_hw_trap_pabt
.align 5
vector_dabt:
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} /* Calling r0-r12 */
add r8, sp, #S_PC
stmdb r8, {sp, lr}^ /* Calling SP, LR */
str lr, [r8, #0] /* Save calling PC */
mrs r6, spsr
str r6, [r8, #4] /* Save CPSR */
str r0, [r8, #8] /* Save OLD_R0 */
mov r0, sp
bl rt_hw_trap_dabt
.align 5
vector_resv:
bl rt_hw_trap_resv
.globl rt_interrupt_enter
.globl rt_interrupt_leave
.globl rt_thread_switch_interrupt_flag
.globl rt_interrupt_from_thread
.globl rt_interrupt_to_thread
vector_irq:
stmfd sp!, {r0-r12,lr}
bl rt_interrupt_enter
bl rt_hw_trap_irq
bl rt_interrupt_leave
/* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */
ldr r0, =rt_thread_switch_interrupt_flag
ldr r1, [r0]
cmp r1, #1
beq _interrupt_thread_switch
ldmfd sp!, {r0-r12,lr}
subs pc, lr, #4
.align 5
vector_fiq:
stmfd sp!,{r0-r7,lr}
bl rt_hw_trap_fiq
ldmfd sp!,{r0-r7,lr}
subs pc,lr,#4
_interrupt_thread_switch:
mov r1, #0 /* clear rt_thread_switch_interrupt_flag*/
str r1, [r0]
ldmfd sp!, {r0-r12,lr} /* reload saved registers */
stmfd sp!, {r0-r3} /* save r0-r3 */
mov r1, sp
add sp, sp, #16 /* restore sp */
sub r2, lr, #4 /* save old task's pc to r2 */
mrs r3, spsr /* disable interrupt */
orr r0, r3, #NOINT
msr spsr_c, r0
ldr r0, =.+8 /* switch to interrupted task's stack*/
movs pc, r0
stmfd sp!, {r2} /* push old task's pc */
stmfd sp!, {r4-r12,lr} /* push old task's lr,r12-r4 */
mov r4, r1 /* Special optimised code below */
mov r5, r3
ldmfd r4!, {r0-r3}
stmfd sp!, {r0-r3} /* push old task's r3-r0 */
stmfd sp!, {r5} /* push old task's psr */
mrs r4, spsr
stmfd sp!, {r4} /* push old task's spsr */
ldr r4, =rt_interrupt_from_thread
ldr r5, [r4]
str sp, [r5] /* store sp in preempted tasks's TCB*/
ldr r6, =rt_interrupt_to_thread
ldr r6, [r6]
ldr sp, [r6] /* get new task's stack pointer */
ldmfd sp!, {r4} /* pop new task's spsr */
msr SPSR_cxsf, r4
ldmfd sp!, {r4} /* pop new task's psr */
msr CPSR_cxsf, r4
ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */
stack_setup:
mrs r0, cpsr
bic r0, r0, #MODEMASK
orr r1, r0, #UNDEFMODE|NOINT
msr cpsr_cxsf, r1 /* undef mode */
ldr sp, UNDEFINED_STACK_START
orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 /* abort mode */
ldr sp, ABORT_STACK_START
orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1 /* IRQ mode */
ldr sp, IRQ_STACK_START
orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1 /* FIQ mode */
ldr sp, FIQ_STACK_START
bic r0,r0,#MODEMASK
orr r1,r0,#SVCMODE|NOINT
msr cpsr_cxsf,r1 /* SVC mode */
ldr sp, _STACK_START
/* USER mode is not initialized. */
mov pc,lr /* The LR register may be not valid for the mode changes.*/
/*/*}*/

View File

@ -1,325 +0,0 @@
;/*
; * File : start_rvds.S
; * This file is part of RT-Thread RTOS
; * COPYRIGHT (C) 2006, RT-Thread Development Team
; *
; * This program is free software; you can redistribute it and/or modify
; * it under the terms of the GNU General Public License as published by
; * the Free Software Foundation; either version 2 of the License, or
; * (at your option) any later version.
; *
; * This program is distributed in the hope that it will be useful,
; * but WITHOUT ANY WARRANTY; without even the implied warranty of
; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; * GNU General Public License for more details.
; *
; * You should have received a copy of the GNU General Public License along
; * with this program; if not, write to the Free Software Foundation, Inc.,
; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; *
; * Change Logs:
; * Date Author Notes
; * 2011-08-14 weety first version
; */
; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
Mode_USR EQU 0x10
Mode_FIQ EQU 0x11
Mode_IRQ EQU 0x12
Mode_SVC EQU 0x13
Mode_ABT EQU 0x17
Mode_UND EQU 0x1B
Mode_SYS EQU 0x1F
SVCMODE EQU 0x13
MODEMASK EQU 0x1f
I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled
F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled
;----------------------- Stack and Heap Definitions ----------------------------
;// <h> Stack Configuration (Stack Sizes in Bytes)
;// <o0> Undefined Mode <0x0-0xFFFFFFFF:8>
;// <o1> Supervisor Mode <0x0-0xFFFFFFFF:8>
;// <o2> Abort Mode <0x0-0xFFFFFFFF:8>
;// <o3> Fast Interrupt Mode <0x0-0xFFFFFFFF:8>
;// <o4> Interrupt Mode <0x0-0xFFFFFFFF:8>
;// <o5> User/System Mode <0x0-0xFFFFFFFF:8>
;// </h>
UND_Stack_Size EQU 512
SVC_Stack_Size EQU 4096
ABT_Stack_Size EQU 512
FIQ_Stack_Size EQU 1024
IRQ_Stack_Size EQU 1024
USR_Stack_Size EQU 512
ISR_Stack_Size EQU (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
FIQ_Stack_Size + IRQ_Stack_Size)
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE USR_Stack_Size
__initial_sp SPACE ISR_Stack_Size
Stack_Top
;// <h> Heap Configuration
;// <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF>
;// </h>
Heap_Size EQU 0x00000000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
;----------------------- Memory Definitions ------------------------------------
AT91_MATRIX_BASE EQU 0xffffee00
AT91_MATRIX_MRCR EQU (AT91_MATRIX_BASE + 0x100)
AT91_MATRIX_RCB0 EQU 0x00000001
AT91_MATRIX_RCB1 EQU 0x00000002
AT91_AIC_BASE EQU 0xfffff000
AT91_AIC_IDCR EQU 0x124
AT91_AIC_ICCR EQU 0x128
;----------------------- CODE --------------------------------------------------
PRESERVE8
; Area Definition and Entry Point
; Startup Code must be linked first at Address at which it expects to run.
AREA RESET, CODE, READONLY
ARM
; Exception Vectors
; Mapped to Address 0.
; Absolute addressing mode must be used.
; Dummy Handlers are implemented as infinite loops which can be modified.
EXPORT Entry_Point
Entry_Point
Vectors LDR PC, Reset_Addr
LDR PC, Undef_Addr
LDR PC, SWI_Addr
LDR PC, PAbt_Addr
LDR PC, DAbt_Addr
NOP
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
Reset_Addr DCD Reset_Handler
Undef_Addr DCD Undef_Handler
SWI_Addr DCD SWI_Handler
PAbt_Addr DCD PAbt_Handler
DAbt_Addr DCD DAbt_Handler
DCD 0 ; Reserved Address
IRQ_Addr DCD IRQ_Handler
FIQ_Addr DCD FIQ_Handler
Undef_Handler B Undef_Handler
SWI_Handler B SWI_Handler
PAbt_Handler B PAbt_Handler
;DAbt_Handler B DAbt_Handler
FIQ_Handler B FIQ_Handler
;*
;*************************************************************************
;*
;* Interrupt handling
;*
;*************************************************************************
;*
; DAbt Handler
DAbt_Handler
IMPORT rt_hw_trap_dabt
sub sp, sp, #72
stmia sp, {r0 - r12} ;/* Calling r0-r12 */
add r8, sp, #60
stmdb r8, {sp, lr} ;/* Calling SP, LR */
str lr, [r8, #0] ;/* Save calling PC */
mrs r6, spsr
str r6, [r8, #4] ;/* Save CPSR */
str r0, [r8, #8] ;/* Save OLD_R0 */
mov r0, sp
bl rt_hw_trap_dabt
;##########################################
; Reset Handler
EXPORT Reset_Handler
Reset_Handler
; set the cpu to SVC32 mode-----------------------------------------------------
MRS R0,CPSR
BIC R0,R0,#MODEMASK
ORR R0,R0,#SVCMODE
MSR CPSR_cxsf,R0
LDR R1, =AT91_AIC_BASE
LDR R0, =0xffffffff
STR R0, [R1, #AT91_AIC_IDCR]
STR R0, [R1, #AT91_AIC_ICCR]
; remap internal ram to 0x00000000 address
LDR R0, =AT91_MATRIX_MRCR
LDR R1, =(AT91_MATRIX_RCB0|AT91_MATRIX_RCB1)
STR R1, [R0]
; Copy Exception Vectors to Internal RAM ---------------------------------------
ADR R8, Vectors ; Source
LDR R9, =0x00 ; Destination
LDMIA R8!, {R0-R7} ; Load Vectors
STMIA R9!, {R0-R7} ; Store Vectors
LDMIA R8!, {R0-R7} ; Load Handler Addresses
STMIA R9!, {R0-R7} ; Store Handler Addresses
; Setup Stack for each mode ----------------------------------------------------
LDR R0, =Stack_Top
; Enter Undefined Instruction Mode and set its Stack Pointer
MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #UND_Stack_Size
; Enter Abort Mode and set its Stack Pointer
MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #ABT_Stack_Size
; Enter FIQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #FIQ_Stack_Size
; Enter IRQ Mode and set its Stack Pointer
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #IRQ_Stack_Size
; Enter Supervisor Mode and set its Stack Pointer
MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
MOV SP, R0
SUB R0, R0, #SVC_Stack_Size
; Enter User Mode and set its Stack Pointer
; MSR CPSR_c, #Mode_USR
MOV SP, R0
SUB SL, SP, #USR_Stack_Size
; Enter the C code -------------------------------------------------------------
IMPORT __main
LDR R0, =__main
BX R0
IMPORT rt_interrupt_enter
IMPORT rt_interrupt_leave
IMPORT rt_thread_switch_interrupt_flag
IMPORT rt_interrupt_from_thread
IMPORT rt_interrupt_to_thread
IMPORT rt_hw_trap_irq
IRQ_Handler PROC
EXPORT IRQ_Handler
STMFD sp!, {r0-r12,lr}
BL rt_interrupt_enter
BL rt_hw_trap_irq
BL rt_interrupt_leave
; if rt_thread_switch_interrupt_flag set, jump to
; rt_hw_context_switch_interrupt_do and don't return
LDR r0, =rt_thread_switch_interrupt_flag
LDR r1, [r0]
CMP r1, #1
BEQ rt_hw_context_switch_interrupt_do
LDMFD sp!, {r0-r12,lr}
SUBS pc, lr, #4
ENDP
; /*
; * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
; */
rt_hw_context_switch_interrupt_do PROC
EXPORT rt_hw_context_switch_interrupt_do
MOV r1, #0 ; clear flag
STR r1, [r0]
LDMFD sp!, {r0-r12,lr}; reload saved registers
STMFD sp!, {r0-r3} ; save r0-r3
MOV r1, sp
ADD sp, sp, #16 ; restore sp
SUB r2, lr, #4 ; save old task's pc to r2
MRS r3, spsr ; get cpsr of interrupt thread
; switch to SVC mode and no interrupt
MSR cpsr_c, #I_Bit:OR:F_Bit:OR:Mode_SVC
STMFD sp!, {r2} ; push old task's pc
STMFD sp!, {r4-r12,lr}; push old task's lr,r12-r4
MOV r4, r1 ; Special optimised code below
MOV r5, r3
LDMFD r4!, {r0-r3}
STMFD sp!, {r0-r3} ; push old task's r3-r0
STMFD sp!, {r5} ; push old task's cpsr
MRS r4, spsr
STMFD sp!, {r4} ; push old task's spsr
LDR r4, =rt_interrupt_from_thread
LDR r5, [r4]
STR sp, [r5] ; store sp in preempted tasks's TCB
LDR r6, =rt_interrupt_to_thread
LDR r6, [r6]
LDR sp, [r6] ; get new task's stack pointer
LDMFD sp!, {r4} ; pop new task's spsr
MSR spsr_cxsf, r4
LDMFD sp!, {r4} ; pop new task's psr
MSR cpsr_cxsf, r4
LDMFD sp!, {r0-r12,lr,pc} ; pop new task's r0-r12,lr & pc
ENDP
IF :DEF:__MICROLIB
EXPORT __heap_base
EXPORT __heap_limit
ELSE
; User Initial Stack & Heap
AREA |.text|, CODE, READONLY
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + USR_Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR
ENDIF
END

View File

@ -12,10 +12,11 @@ if os.getenv('RTT_CC'):
if CROSS_TOOL == 'gcc': if CROSS_TOOL == 'gcc':
PLATFORM = 'gcc' PLATFORM = 'gcc'
EXEC_PATH = '/opt/arm-2010q1/bin/' #EXEC_PATH = 'D:/ArdaArmTools/Sourcery_Lite/bin'
EXEC_PATH = 'D:/ArdaArmTools/GNUARM_4.9_2015q1/bin'
elif CROSS_TOOL == 'keil': elif CROSS_TOOL == 'keil':
PLATFORM = 'armcc' PLATFORM = 'armcc'
EXEC_PATH = 'C:/Keil' EXEC_PATH = 'C:/Keil_v5'
elif CROSS_TOOL == 'iar': elif CROSS_TOOL == 'iar':
print '================ERROR============================' print '================ERROR============================'
print 'Not support yet!' print 'Not support yet!'
@ -43,7 +44,7 @@ if PLATFORM == 'gcc':
DEVICE = ' -mcpu=arm926ej-s' DEVICE = ' -mcpu=arm926ej-s'
CFLAGS = DEVICE CFLAGS = DEVICE
AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp' + ' -DTEXT_BASE=' + TextBase AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp' + ' -Iplatform'+' -DTEXT_BASE=' + TextBase
LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread_at91sam9260.map,-cref,-u,_start -T at91sam9260_ram.ld' + ' -Ttext ' + TextBase LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread_at91sam9260.map,-cref,-u,_start -T at91sam9260_ram.ld' + ' -Ttext ' + TextBase
CPATH = '' CPATH = ''
@ -65,9 +66,9 @@ elif PLATFORM == 'armcc':
LINK = 'armlink' LINK = 'armlink'
TARGET_EXT = 'axf' TARGET_EXT = 'axf'
DEVICE = ' --device DARMATS9' DEVICE = ' --cpu=ARM926EJ-S'
CFLAGS = DEVICE + ' --apcs=interwork --diag_suppress=870' CFLAGS = DEVICE + ' --apcs=interwork --diag_suppress=870'
AFLAGS = DEVICE AFLAGS = DEVICE + ' -Iplatform'
LFLAGS = DEVICE + ' --strict --info sizes --info totals --info unused --info veneers --list rtthread-at91sam9260.map --ro-base 0x20000000 --entry Entry_Point --first Entry_Point' LFLAGS = DEVICE + ' --strict --info sizes --info totals --info unused --info veneers --list rtthread-at91sam9260.map --ro-base 0x20000000 --entry Entry_Point --first Entry_Point'
CFLAGS += ' -I"' + EXEC_PATH + '/ARM/RV31/INC"' CFLAGS += ' -I"' + EXEC_PATH + '/ARM/RV31/INC"'

View File

@ -1,110 +1,99 @@
/* ;/*
* File : context.S ; * File : context_iar.S
* This file is part of RT-Thread RTOS ; * This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team ; * COPYRIGHT (C) 2006, RT-Thread Development Team
* ; *
* This program is free software; you can redistribute it and/or modify ; * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by ; * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or ; * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. ; * (at your option) any later version.
* ; *
* This program is distributed in the hope that it will be useful, ; * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of ; * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. ; * GNU General Public License for more details.
* ; *
* You should have received a copy of the GNU General Public License along ; * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., ; * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* ; *
* Change Logs: ; * Change Logs:
* Date Author Notes ; * Date Author Notes
* 2011-01-13 weety copy from mini2440 ; * 2011-08-14 weety copy from mini2440
*/ ; */
/*! #define NOINT 0xC0
* \addtogroup AT91SAM926X
*/
/*@{*/
#define NOINT 0xc0 ;/*
; * rt_base_t rt_hw_interrupt_disable();
; */
/* .globl rt_hw_interrupt_disable
* rt_base_t rt_hw_interrupt_disable();
*/
.globl rt_hw_interrupt_disable
rt_hw_interrupt_disable: rt_hw_interrupt_disable:
mrs r0, cpsr MRS R0, CPSR
orr r1, r0, #NOINT ORR R1, R0, #NOINT
msr cpsr_c, r1 MSR CPSR_c, R1
mov pc, lr BX LR
/* /*
* void rt_hw_interrupt_enable(rt_base_t level); * void rt_hw_interrupt_enable(rt_base_t level);
*/ */
.globl rt_hw_interrupt_enable .globl rt_hw_interrupt_enable
rt_hw_interrupt_enable: rt_hw_interrupt_enable:
msr cpsr, r0 MSR CPSR, R0
mov pc, lr BX LR
/* /*
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
* r0 --> from * r0 --> from
* r1 --> to * r1 --> to
*/ */
.globl rt_hw_context_switch .globl rt_hw_context_switch
rt_hw_context_switch: rt_hw_context_switch:
stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) stmfd sp!, {lr} @; push pc (lr should be pushed in place of pc)
stmfd sp!, {r0-r12, lr} @ push lr & register file stmfd sp!, {r0-r12, lr} @; push lr & register file
mrs r4, cpsr
mrs r4, cpsr stmfd sp!, {r4} @; push cpsr
stmfd sp!, {r4} @ push cpsr mrs r4, spsr
mrs r4, spsr stmfd sp!, {r4} @; push spsr
stmfd sp!, {r4} @ push spsr str sp, [r0] @; store sp in preempted tasks tcb
ldr sp, [r1] @; get new task stack pointer
str sp, [r0] @ store sp in preempted tasks TCB ldmfd sp!, {r4} @; pop new task spsr
ldr sp, [r1] @ get new task stack pointer msr spsr_cxsf, r4
ldmfd sp!, {r4} @; pop new task cpsr
ldmfd sp!, {r4} @ pop new task spsr msr spsr_cxsf, r4
msr spsr_cxsf, r4 ldmfd sp!, {r0-r12, lr, pc}^ @; pop new task r0-r12, lr & pc
ldmfd sp!, {r4} @ pop new task cpsr
msr spsr_cxsf, r4
ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc
/* /*
* void rt_hw_context_switch_to(rt_uint32 to); * void rt_hw_context_switch_to(rt_uint32 to);
* r0 --> to * r0 --> to
*/ */
.globl rt_hw_context_switch_to .globl rt_hw_context_switch_to
rt_hw_context_switch_to: rt_hw_context_switch_to:
ldr sp, [r0] @ get new task stack pointer ldr sp, [r0] @; get new task stack pointer
ldmfd sp!, {r4} @ pop new task spsr ldmfd sp!, {r4} @; pop new task spsr
msr spsr_cxsf, r4 msr spsr_cxsf, r4
ldmfd sp!, {r4} @ pop new task cpsr ldmfd sp!, {r4} @; pop new task cpsr
msr cpsr_cxsf, r4 msr spsr_cxsf, r4
ldmfd sp!, {r0-r12, lr, pc}^ @; pop new task r0-r12, lr & pc
ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc
/* /*
* void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
*/ */
.globl rt_thread_switch_interrupt_flag .globl rt_thread_switch_interrupt_flag
.globl rt_interrupt_from_thread .globl rt_interrupt_from_thread
.globl rt_interrupt_to_thread .globl rt_interrupt_to_thread
.globl rt_hw_context_switch_interrupt .globl rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt: rt_hw_context_switch_interrupt:
ldr r2, =rt_thread_switch_interrupt_flag LDR R2, =rt_thread_switch_interrupt_flag
ldr r3, [r2] LDR R3, [R2]
cmp r3, #1 CMP R3, #1
beq _reswitch BEQ _reswitch
mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 MOV R3, #1 @; set flag to 1
str r3, [r2] STR R3, [R2]
ldr r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread LDR R2, =rt_interrupt_from_thread @; set rt_interrupt_from_thread
str r0, [r2] STR R0, [R2]
_reswitch: _reswitch:
ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread LDR R2, =rt_interrupt_to_thread @; set rt_interrupt_to_thread
str r1, [r2] STR R1, [R2]
mov pc, lr BX LR

View File

@ -0,0 +1,103 @@
;/*
; * File : context_iar.S
; * This file is part of RT-Thread RTOS
; * COPYRIGHT (C) 2006, RT-Thread Development Team
; *
; * This program is free software; you can redistribute it and/or modify
; * it under the terms of the GNU General Public License as published by
; * the Free Software Foundation; either version 2 of the License, or
; * (at your option) any later version.
; *
; * This program is distributed in the hope that it will be useful,
; * but WITHOUT ANY WARRANTY; without even the implied warranty of
; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; * GNU General Public License for more details.
; *
; * You should have received a copy of the GNU General Public License along
; * with this program; if not, write to the Free Software Foundation, Inc.,
; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; *
; * Change Logs:
; * Date Author Notes
; * 2011-08-14 weety copy from mini2440
; */
#define NOINT 0xc0
SECTION .text:CODE(6)
/*
* rt_base_t rt_hw_interrupt_disable();
*/
PUBLIC rt_hw_interrupt_disable
rt_hw_interrupt_disable:
MRS R0, CPSR
ORR R1, R0, #NOINT
MSR CPSR_C, R1
MOV PC, LR
/*
* void rt_hw_interrupt_enable(rt_base_t level);
*/
PUBLIC rt_hw_interrupt_enable
rt_hw_interrupt_enable:
MSR CPSR_CXSF, R0
MOV PC, LR
/*
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
* r0 --> from
* r1 --> to
*/
PUBLIC rt_hw_context_switch
rt_hw_context_switch:
STMFD SP!, {LR} ; push pc (lr should be pushed in place of PC)
STMFD SP!, {R0-R12, LR} ; push lr & register file
MRS R4, CPSR
STMFD SP!, {R4} ; push cpsr
MRS R4, SPSR
STMFD SP!, {R4} ; push spsr
STR SP, [R0] ; store sp in preempted tasks TCB
LDR SP, [R1] ; get new task stack pointer
LDMFD SP!, {R4} ; pop new task spsr
MSR SPSR_cxsf, R4
LDMFD SP!, {R4} ; pop new task cpsr
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12, LR, PC}^ ; pop new task r0-r12, lr & pc
/*
* void rt_hw_context_switch_to(rt_uint32 to);
* r0 --> to
*/
PUBLIC rt_hw_context_switch_to
rt_hw_context_switch_to:
LDR SP, [R0] ; get new task stack pointer
LDMFD SP!, {R4} ; pop new task spsr
MSR SPSR_cxsf, R4
LDMFD SP!, {R4} ; pop new task cpsr
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12, LR, PC}^ ; pop new task r0-r12, lr & pc
/*
* void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
*/
IMPORT rt_thread_switch_interrupt_flag
IMPORT rt_interrupt_from_thread
IMPORT rt_interrupt_to_thread
PUBLIC rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt:
LDR R2, =rt_thread_switch_interrupt_flag
LDR R3, [R2]
CMP R3, #1
BEQ _reswitch
MOV R3, #1 ; set flag to 1
STR R3, [R2]
LDR R2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread
STR R0, [R2]
_reswitch:
LDR R2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread
STR R1, [R2]
MOV PC, LR
END

View File

@ -1,117 +1,112 @@
;/* ;/*
; * File : context_rvds.S ; * file : context_rvds.s
; * This file is part of RT-Thread RTOS ; * this file is part of rt-thread rtos
; * COPYRIGHT (C) 2006, RT-Thread Development Team ; * copyright (c) 2006, rt-thread development team
; * ; *
; * This program is free software; you can redistribute it and/or modify ; * this program is free software; you can redistribute it and/or modify
; * it under the terms of the GNU General Public License as published by ; * it under the terms of the gnu general public license as published by
; * the Free Software Foundation; either version 2 of the License, or ; * the free software foundation; either version 2 of the license, or
; * (at your option) any later version. ; * (at your option) any later version.
; * ; *
; * This program is distributed in the hope that it will be useful, ; * this program is distributed in the hope that it will be useful,
; * but WITHOUT ANY WARRANTY; without even the implied warranty of ; * but without any warranty; without even the implied warranty of
; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; * merchantability or fitness for a particular purpose. see the
; * GNU General Public License for more details. ; * gnu general public license for more details.
; * ; *
; * You should have received a copy of the GNU General Public License along ; * you should have received a copy of the gnu general public license along
; * with this program; if not, write to the Free Software Foundation, Inc., ; * with this program; if not, write to the free software foundation, inc.,
; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ; * 51 franklin street, fifth floor, boston, ma 02110-1301 usa.
; * ; *
; * Change Logs: ; * change logs:
; * Date Author Notes ; * date author notes
; * 2011-08-14 weety copy from mini2440 ; * 2011-08-14 weety copy from mini2440
; */ ; */
NOINT EQU 0xc0 ; disable interrupt in psr NOINT EQU 0XC0 ; disable interrupt in psr
AREA |.text|, CODE, READONLY, ALIGN=2 AREA |.TEXT|, CODE, READONLY, ALIGN=2
ARM ARM
REQUIRE8 REQUIRE8
PRESERVE8 PRESERVE8
;/* ;/*
; * rt_base_t rt_hw_interrupt_disable(); ; * rt_base_t rt_hw_interrupt_disable();
; */ ; */
rt_hw_interrupt_disable PROC rt_hw_interrupt_disable PROC
EXPORT rt_hw_interrupt_disable EXPORT rt_hw_interrupt_disable
MRS r0, cpsr MRS R0, CPSR
ORR r1, r0, #NOINT ORR R1, R0, #NOINT
MSR cpsr_c, r1 MSR CPSR_C, R1
BX lr BX LR
ENDP ENDP
;/* ;/*
; * void rt_hw_interrupt_enable(rt_base_t level); ; * void rt_hw_interrupt_enable(rt_base_t level);
; */ ; */
rt_hw_interrupt_enable PROC rt_hw_interrupt_enable proc
EXPORT rt_hw_interrupt_enable export rt_hw_interrupt_enable
MSR cpsr_c, r0 msr cpsr_c, r0
BX lr bx lr
ENDP endp
;/* ;/*
; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); ; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
; * r0 --> from ; * r0 --> from
; * r1 --> to ; * r1 --> to
; */ ; */
rt_hw_context_switch PROC rt_hw_context_switch proc
EXPORT rt_hw_context_switch export rt_hw_context_switch
STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) stmfd sp!, {lr} ; push pc (lr should be pushed in place of pc)
STMFD sp!, {r0-r12, lr} ; push lr & register file stmfd sp!, {r0-r12, lr} ; push lr & register file
mrs r4, cpsr
MRS r4, cpsr stmfd sp!, {r4} ; push cpsr
STMFD sp!, {r4} ; push cpsr mrs r4, spsr
MRS r4, spsr stmfd sp!, {r4} ; push spsr
STMFD sp!, {r4} ; push spsr str sp, [r0] ; store sp in preempted tasks tcb
ldr sp, [r1] ; get new task stack pointer
STR sp, [r0] ; store sp in preempted tasks TCB ldmfd sp!, {r4} ; pop new task spsr
LDR sp, [r1] ; get new task stack pointer msr spsr_cxsf, r4
ldmfd sp!, {r4} ; pop new task cpsr
LDMFD sp!, {r4} ; pop new task spsr msr spsr_cxsf, r4
MSR spsr_cxsf, r4 ldmfd sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc
LDMFD sp!, {r4} ; pop new task cpsr endp
MSR spsr_cxsf, r4
LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc
ENDP
;/* ;/*
; * void rt_hw_context_switch_to(rt_uint32 to); ; * void rt_hw_context_switch_to(rt_uint32 to);
; * r0 --> to ; * r0 --> to
; */ ; */
rt_hw_context_switch_to PROC rt_hw_context_switch_to proc
EXPORT rt_hw_context_switch_to export rt_hw_context_switch_to
LDR sp, [r0] ; get new task stack pointer ldr sp, [r0] ; get new task stack pointer
LDMFD sp!, {r4} ; pop new task spsr ldmfd sp!, {r4} ; pop new task spsr
MSR spsr_cxsf, r4 msr spsr_cxsf, r4
LDMFD sp!, {r4} ; pop new task cpsr ldmfd sp!, {r4} ; pop new task cpsr
MSR cpsr_cxsf, r4 msr spsr_cxsf, r4
ldmfd sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc
LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc endp
ENDP
;/* ;/*
; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); ; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
; */ ; */
IMPORT rt_thread_switch_interrupt_flag import rt_thread_switch_interrupt_flag
IMPORT rt_interrupt_from_thread import rt_interrupt_from_thread
IMPORT rt_interrupt_to_thread import rt_interrupt_to_thread
rt_hw_context_switch_interrupt PROC rt_hw_context_switch_interrupt proc
EXPORT rt_hw_context_switch_interrupt export rt_hw_context_switch_interrupt
LDR r2, =rt_thread_switch_interrupt_flag ldr r2, =rt_thread_switch_interrupt_flag
LDR r3, [r2] ldr r3, [r2]
CMP r3, #1 cmp r3, #1
BEQ _reswitch beq _reswitch
MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 mov r3, #1 ; set flag to 1
STR r3, [r2] str r3, [r2]
LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread ldr r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread
STR r0, [r2] str r0, [r2]
_reswitch _reswitch
LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread ldr r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread
STR r1, [r2] str r1, [r2]
BX lr bx lr
ENDP endp
END end

View File

@ -25,8 +25,8 @@
#include <rthw.h> #include <rthw.h>
#include <rtthread.h> #include <rtthread.h>
#define ICACHE_MASK (rt_uint32_t)(1 << 12) #define ICACHE_MASK (rt_uint32_t)(1 << 12)
#define DCACHE_MASK (rt_uint32_t)(1 << 2) #define DCACHE_MASK (rt_uint32_t)(1 << 2)
extern void machine_reset(void); extern void machine_reset(void);
extern void machine_shutdown(void); extern void machine_shutdown(void);
@ -34,70 +34,102 @@ extern void machine_shutdown(void);
#ifdef __GNUC__ #ifdef __GNUC__
rt_inline rt_uint32_t cp15_rd(void) rt_inline rt_uint32_t cp15_rd(void)
{ {
rt_uint32_t i; rt_uint32_t i;
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
return i; return i;
} }
rt_inline void cache_enable(rt_uint32_t bit) rt_inline void cache_enable(rt_uint32_t bit)
{ {
__asm__ __volatile__( \ __asm__ __volatile__( \
"mrc p15,0,r0,c1,c0,0\n\t" \ "mrc p15,0,r0,c1,c0,0\n\t" \
"orr r0,r0,%0\n\t" \ "orr r0,r0,%0\n\t" \
"mcr p15,0,r0,c1,c0,0" \ "mcr p15,0,r0,c1,c0,0" \
: \ : \
:"r" (bit) \ :"r" (bit) \
:"memory"); :"memory");
} }
rt_inline void cache_disable(rt_uint32_t bit) rt_inline void cache_disable(rt_uint32_t bit)
{ {
__asm__ __volatile__( \ __asm__ __volatile__( \
"mrc p15,0,r0,c1,c0,0\n\t" \ "mrc p15,0,r0,c1,c0,0\n\t" \
"bic r0,r0,%0\n\t" \ "bic r0,r0,%0\n\t" \
"mcr p15,0,r0,c1,c0,0" \ "mcr p15,0,r0,c1,c0,0" \
: \ : \
:"r" (bit) \ :"r" (bit) \
:"memory"); :"memory");
} }
#endif #endif
#ifdef __CC_ARM #ifdef __CC_ARM
rt_inline rt_uint32_t cp15_rd(void) rt_inline rt_uint32_t cp15_rd(void)
{ {
rt_uint32_t i; rt_uint32_t i;
__asm __asm
{ {
mrc p15, 0, i, c1, c0, 0 mrc p15, 0, i, c1, c0, 0
} }
return i; return i;
} }
rt_inline void cache_enable(rt_uint32_t bit) rt_inline void cache_enable(rt_uint32_t bit)
{ {
rt_uint32_t value; rt_uint32_t value;
__asm __asm
{ {
mrc p15, 0, value, c1, c0, 0 mrc p15, 0, value, c1, c0, 0
orr value, value, bit orr value, value, bit
mcr p15, 0, value, c1, c0, 0 mcr p15, 0, value, c1, c0, 0
} }
} }
rt_inline void cache_disable(rt_uint32_t bit) rt_inline void cache_disable(rt_uint32_t bit)
{ {
rt_uint32_t value; rt_uint32_t value;
__asm __asm
{ {
mrc p15, 0, value, c1, c0, 0 mrc p15, 0, value, c1, c0, 0
bic value, value, bit bic value, value, bit
mcr p15, 0, value, c1, c0, 0 mcr p15, 0, value, c1, c0, 0
} }
}
#endif
#ifdef __ICCARM__
rt_inline rt_uint32_t cp15_rd(void)
{
rt_uint32_t i;
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
return i;
}
rt_inline void cache_enable(rt_uint32_t bit)
{
asm volatile( \
"mrc p15,0,r0,c1,c0,0\n\t" \
"orr r0,r0,%0\n\t" \
"mcr p15,0,r0,c1,c0,0" \
: \
:"r" (bit) \
:"memory");
}
rt_inline void cache_disable(rt_uint32_t bit)
{
asm volatile( \
"mrc p15,0,r0,c1,c0,0\n\t" \
"bic r0,r0,%0\n\t" \
"mcr p15,0,r0,c1,c0,0" \
: \
:"r" (bit) \
:"memory");
} }
#endif #endif
@ -107,7 +139,7 @@ rt_inline void cache_disable(rt_uint32_t bit)
*/ */
void rt_hw_cpu_icache_enable() void rt_hw_cpu_icache_enable()
{ {
cache_enable(ICACHE_MASK); cache_enable(ICACHE_MASK);
} }
/** /**
@ -116,7 +148,7 @@ void rt_hw_cpu_icache_enable()
*/ */
void rt_hw_cpu_icache_disable() void rt_hw_cpu_icache_disable()
{ {
cache_disable(ICACHE_MASK); cache_disable(ICACHE_MASK);
} }
/** /**
@ -125,7 +157,7 @@ void rt_hw_cpu_icache_disable()
*/ */
rt_base_t rt_hw_cpu_icache_status() rt_base_t rt_hw_cpu_icache_status()
{ {
return (cp15_rd() & ICACHE_MASK); return (cp15_rd() & ICACHE_MASK);
} }
/** /**
@ -134,7 +166,7 @@ rt_base_t rt_hw_cpu_icache_status()
*/ */
void rt_hw_cpu_dcache_enable() void rt_hw_cpu_dcache_enable()
{ {
cache_enable(DCACHE_MASK); cache_enable(DCACHE_MASK);
} }
/** /**
@ -143,7 +175,7 @@ void rt_hw_cpu_dcache_enable()
*/ */
void rt_hw_cpu_dcache_disable() void rt_hw_cpu_dcache_disable()
{ {
cache_disable(DCACHE_MASK); cache_disable(DCACHE_MASK);
} }
/** /**
@ -152,7 +184,7 @@ void rt_hw_cpu_dcache_disable()
*/ */
rt_base_t rt_hw_cpu_dcache_status() rt_base_t rt_hw_cpu_dcache_status()
{ {
return (cp15_rd() & DCACHE_MASK); return (cp15_rd() & DCACHE_MASK);
} }
/** /**
@ -162,12 +194,12 @@ rt_base_t rt_hw_cpu_dcache_status()
void rt_hw_cpu_reset() void rt_hw_cpu_reset()
{ {
rt_kprintf("Restarting system...\n"); rt_kprintf("Restarting system...\n");
machine_reset(); machine_reset();
while(1); /* loop forever and wait for reset to happen */ while(1); /* loop forever and wait for reset to happen */
/* NEVER REACHED */ /* NEVER REACHED */
} }
/** /**
@ -176,15 +208,15 @@ void rt_hw_cpu_reset()
*/ */
void rt_hw_cpu_shutdown() void rt_hw_cpu_shutdown()
{ {
rt_uint32_t level; rt_uint32_t level;
rt_kprintf("shutdown...\n"); rt_kprintf("shutdown...\n");
level = rt_hw_interrupt_disable(); level = rt_hw_interrupt_disable();
machine_shutdown(); machine_shutdown();
while (level) while (level)
{ {
RT_ASSERT(0); RT_ASSERT(0);
} }
} }
#ifdef RT_USING_CPU_FFS #ifdef RT_USING_CPU_FFS
@ -201,42 +233,42 @@ void rt_hw_cpu_shutdown()
#if defined(__CC_ARM) #if defined(__CC_ARM)
int __rt_ffs(int value) int __rt_ffs(int value)
{ {
register rt_uint32_t x; register rt_uint32_t x;
if (value == 0) if (value == 0)
return value; return value;
__asm __asm
{ {
rsb x, value, #0 rsb x, value, #0
and x, x, value and x, x, value
clz x, x clz x, x
rsb x, x, #32 rsb x, x, #32
} }
return x; return x;
} }
#elif defined(__IAR_SYSTEMS_ICC__) #elif defined(__IAR_SYSTEMS_ICC__)
int __rt_ffs(int value) int __rt_ffs(int value)
{ {
if (value == 0) if (value == 0)
return value; return value;
__ASM("RSB r4, r0, #0"); __ASM("RSB r4, r0, #0");
__ASM("AND r4, r4, r0"); __ASM("AND r4, r4, r0");
__ASM("CLZ r4, r4"); __ASM("CLZ r4, r4");
__ASM("RSB r0, r4, #32"); __ASM("RSB r0, r4, #32");
} }
#elif defined(__GNUC__) #elif defined(__GNUC__)
int __rt_ffs(int value) int __rt_ffs(int value)
{ {
if (value == 0) if (value == 0)
return value; return value;
value &= (-value); value &= (-value);
asm ("clz %0, %1": "=r"(value) :"r"(value)); asm ("clz %0, %1": "=r"(value) :"r"(value));
return (32 - value); return (32 - value);
} }
#endif #endif

View File

@ -26,22 +26,22 @@
#ifdef __CC_ARM #ifdef __CC_ARM
void mmu_setttbase(rt_uint32_t i) void mmu_setttbase(rt_uint32_t i)
{ {
register rt_uint32_t value; register rt_uint32_t value;
/* Invalidates all TLBs.Domain access is selected as /* Invalidates all TLBs.Domain access is selected as
* client by configuring domain access register, * client by configuring domain access register,
* in that case access controlled by permission value * in that case access controlled by permission value
* set by page table entry * set by page table entry
*/ */
value = 0; value = 0;
__asm __asm
{ {
mcr p15, 0, value, c8, c7, 0 mcr p15, 0, value, c8, c7, 0
} }
value = 0x55555555; value = 0x55555555;
__asm __asm
{ {
mcr p15, 0, value, c3, c0, 0 mcr p15, 0, value, c3, c0, 0
mcr p15, 0, i, c2, c0, 0 mcr p15, 0, i, c2, c0, 0
} }
@ -167,44 +167,44 @@ void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
while(ptr < buffer + size) while(ptr < buffer + size)
{ {
__asm __asm
{ {
MCR p15, 0, ptr, c7, c14, 1 MCR p15, 0, ptr, c7, c14, 1
} }
ptr += CACHE_LINE_SIZE; ptr += CACHE_LINE_SIZE;
} }
} }
void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size) void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
{ {
unsigned int ptr; unsigned int ptr;
ptr = buffer & ~(CACHE_LINE_SIZE - 1); ptr = buffer & ~(CACHE_LINE_SIZE - 1);
while (ptr < buffer + size) while (ptr < buffer + size)
{ {
__asm __asm
{ {
MCR p15, 0, ptr, c7, c10, 1 MCR p15, 0, ptr, c7, c10, 1
} }
ptr += CACHE_LINE_SIZE; ptr += CACHE_LINE_SIZE;
} }
} }
void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size) void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
{ {
unsigned int ptr; unsigned int ptr;
ptr = buffer & ~(CACHE_LINE_SIZE - 1); ptr = buffer & ~(CACHE_LINE_SIZE - 1);
while (ptr < buffer + size) while (ptr < buffer + size)
{ {
__asm __asm
{ {
MCR p15, 0, ptr, c7, c6, 1 MCR p15, 0, ptr, c7, c6, 1
} }
ptr += CACHE_LINE_SIZE; ptr += CACHE_LINE_SIZE;
} }
} }
void mmu_invalidate_tlb() void mmu_invalidate_tlb()
@ -245,133 +245,133 @@ void mmu_invalidate_dcache_all()
#elif defined(__GNUC__) #elif defined(__GNUC__)
void mmu_setttbase(register rt_uint32_t i) void mmu_setttbase(register rt_uint32_t i)
{ {
register rt_uint32_t value; register rt_uint32_t value;
/* Invalidates all TLBs.Domain access is selected as /* Invalidates all TLBs.Domain access is selected as
* client by configuring domain access register, * client by configuring domain access register,
* in that case access controlled by permission value * in that case access controlled by permission value
* set by page table entry * set by page table entry
*/ */
value = 0; value = 0;
asm ("mcr p15, 0, %0, c8, c7, 0"::"r"(value)); asm ("mcr p15, 0, %0, c8, c7, 0"::"r"(value));
value = 0x55555555; value = 0x55555555;
asm ("mcr p15, 0, %0, c3, c0, 0"::"r"(value)); asm ("mcr p15, 0, %0, c3, c0, 0"::"r"(value));
asm ("mcr p15, 0, %0, c2, c0, 0"::"r"(i)); asm ("mcr p15, 0, %0, c2, c0, 0"::"r"(i));
} }
void mmu_set_domain(register rt_uint32_t i) void mmu_set_domain(register rt_uint32_t i)
{ {
asm ("mcr p15,0, %0, c3, c0, 0": :"r" (i)); asm ("mcr p15,0, %0, c3, c0, 0": :"r" (i));
} }
void mmu_enable() void mmu_enable()
{ {
register rt_uint32_t i; register rt_uint32_t i;
/* read control register */ /* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i |= 0x1; i |= 0x1;
/* write back to control register */ /* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
} }
void mmu_disable() void mmu_disable()
{ {
register rt_uint32_t i; register rt_uint32_t i;
/* read control register */ /* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i &= ~0x1; i &= ~0x1;
/* write back to control register */ /* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
} }
void mmu_enable_icache() void mmu_enable_icache()
{ {
register rt_uint32_t i; register rt_uint32_t i;
/* read control register */ /* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i |= (1 << 12); i |= (1 << 12);
/* write back to control register */ /* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
} }
void mmu_enable_dcache() void mmu_enable_dcache()
{ {
register rt_uint32_t i; register rt_uint32_t i;
/* read control register */ /* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i |= (1 << 2); i |= (1 << 2);
/* write back to control register */ /* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
} }
void mmu_disable_icache() void mmu_disable_icache()
{ {
register rt_uint32_t i; register rt_uint32_t i;
/* read control register */ /* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i &= ~(1 << 12); i &= ~(1 << 12);
/* write back to control register */ /* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
} }
void mmu_disable_dcache() void mmu_disable_dcache()
{ {
register rt_uint32_t i; register rt_uint32_t i;
/* read control register */ /* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i &= ~(1 << 2); i &= ~(1 << 2);
/* write back to control register */ /* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
} }
void mmu_enable_alignfault() void mmu_enable_alignfault()
{ {
register rt_uint32_t i; register rt_uint32_t i;
/* read control register */ /* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i |= (1 << 1); i |= (1 << 1);
/* write back to control register */ /* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
} }
void mmu_disable_alignfault() void mmu_disable_alignfault()
{ {
register rt_uint32_t i; register rt_uint32_t i;
/* read control register */ /* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i &= ~(1 << 1); i &= ~(1 << 1);
/* write back to control register */ /* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
} }
void mmu_clean_invalidated_cache_index(int index) void mmu_clean_invalidated_cache_index(int index)
{ {
asm ("mcr p15, 0, %0, c7, c14, 2": :"r" (index)); asm ("mcr p15, 0, %0, c7, c14, 2": :"r" (index));
} }
void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size) void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
@ -382,7 +382,7 @@ void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
while(ptr < buffer + size) while(ptr < buffer + size)
{ {
asm ("mcr p15, 0, %0, c7, c14, 1": :"r" (ptr)); asm ("mcr p15, 0, %0, c7, c14, 1": :"r" (ptr));
ptr += CACHE_LINE_SIZE; ptr += CACHE_LINE_SIZE;
} }
} }
@ -390,38 +390,224 @@ void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size) void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
{ {
unsigned int ptr; unsigned int ptr;
ptr = buffer & ~(CACHE_LINE_SIZE - 1); ptr = buffer & ~(CACHE_LINE_SIZE - 1);
while (ptr < buffer + size) while (ptr < buffer + size)
{ {
asm ("mcr p15, 0, %0, c7, c10, 1": :"r" (ptr)); asm ("mcr p15, 0, %0, c7, c10, 1": :"r" (ptr));
ptr += CACHE_LINE_SIZE; ptr += CACHE_LINE_SIZE;
} }
} }
void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size) void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
{ {
unsigned int ptr; unsigned int ptr;
ptr = buffer & ~(CACHE_LINE_SIZE - 1); ptr = buffer & ~(CACHE_LINE_SIZE - 1);
while (ptr < buffer + size) while (ptr < buffer + size)
{ {
asm ("mcr p15, 0, %0, c7, c6, 1": :"r" (ptr)); asm ("mcr p15, 0, %0, c7, c6, 1": :"r" (ptr));
ptr += CACHE_LINE_SIZE; ptr += CACHE_LINE_SIZE;
} }
} }
void mmu_invalidate_tlb() void mmu_invalidate_tlb()
{ {
asm ("mcr p15, 0, %0, c8, c7, 0": :"r" (0)); asm ("mcr p15, 0, %0, c8, c7, 0": :"r" (0));
} }
void mmu_invalidate_icache() void mmu_invalidate_icache()
{ {
asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0)); asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0));
}
void mmu_invalidate_dcache_all()
{
asm ("mcr p15, 0, %0, c7, c6, 0": :"r" (0));
}
#elif defined(__ICCARM__)
void mmu_setttbase(register rt_uint32_t i)
{
register rt_uint32_t value;
/* Invalidates all TLBs.Domain access is selected as
* client by configuring domain access register,
* in that case access controlled by permission value
* set by page table entry
*/
value = 0;
asm ("mcr p15, 0, %0, c8, c7, 0"::"r"(value));
value = 0x55555555;
asm ("mcr p15, 0, %0, c3, c0, 0"::"r"(value));
asm ("mcr p15, 0, %0, c2, c0, 0"::"r"(i));
}
void mmu_set_domain(register rt_uint32_t i)
{
asm ("mcr p15,0, %0, c3, c0, 0": :"r" (i));
}
void mmu_enable()
{
register rt_uint32_t i;
/* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i |= 0x1;
/* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
}
void mmu_disable()
{
register rt_uint32_t i;
/* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i &= ~0x1;
/* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
}
void mmu_enable_icache()
{
register rt_uint32_t i;
/* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i |= (1 << 12);
/* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
}
void mmu_enable_dcache()
{
register rt_uint32_t i;
/* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i |= (1 << 2);
/* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
}
void mmu_disable_icache()
{
register rt_uint32_t i;
/* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i &= ~(1 << 12);
/* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
}
void mmu_disable_dcache()
{
register rt_uint32_t i;
/* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i &= ~(1 << 2);
/* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
}
void mmu_enable_alignfault()
{
register rt_uint32_t i;
/* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i |= (1 << 1);
/* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
}
void mmu_disable_alignfault()
{
register rt_uint32_t i;
/* read control register */
asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
i &= ~(1 << 1);
/* write back to control register */
asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
}
void mmu_clean_invalidated_cache_index(int index)
{
asm ("mcr p15, 0, %0, c7, c14, 2": :"r" (index));
}
void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
{
unsigned int ptr;
ptr = buffer & ~(CACHE_LINE_SIZE - 1);
while(ptr < buffer + size)
{
asm ("mcr p15, 0, %0, c7, c14, 1": :"r" (ptr));
ptr += CACHE_LINE_SIZE;
}
}
void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
{
unsigned int ptr;
ptr = buffer & ~(CACHE_LINE_SIZE - 1);
while (ptr < buffer + size)
{
asm ("mcr p15, 0, %0, c7, c10, 1": :"r" (ptr));
ptr += CACHE_LINE_SIZE;
}
}
void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
{
unsigned int ptr;
ptr = buffer & ~(CACHE_LINE_SIZE - 1);
while (ptr < buffer + size)
{
asm ("mcr p15, 0, %0, c7, c6, 1": :"r" (ptr));
ptr += CACHE_LINE_SIZE;
}
}
void mmu_invalidate_tlb()
{
asm ("mcr p15, 0, %0, c8, c7, 0": :"r" (0));
}
void mmu_invalidate_icache()
{
asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0));
} }
void mmu_invalidate_dcache_all() void mmu_invalidate_dcache_all()
@ -431,38 +617,44 @@ void mmu_invalidate_dcache_all()
#endif #endif
/* level1 page table */ /* level1 page table */
#if defined(__ICCARM__)
#pragma data_alignment=(16*1024)
static volatile unsigned int _page_table[4*1024];;
#else
static volatile unsigned int _page_table[4*1024] __attribute__((aligned(16*1024))); static volatile unsigned int _page_table[4*1024] __attribute__((aligned(16*1024)));
#endif
void mmu_setmtt(rt_uint32_t vaddrStart, rt_uint32_t vaddrEnd, rt_uint32_t paddrStart, rt_uint32_t attr) void mmu_setmtt(rt_uint32_t vaddrStart, rt_uint32_t vaddrEnd, rt_uint32_t paddrStart, rt_uint32_t attr)
{ {
volatile rt_uint32_t *pTT; volatile rt_uint32_t *pTT;
volatile int i,nSec; volatile int nSec;
int i = 0;
pTT=(rt_uint32_t *)_page_table+(vaddrStart>>20); pTT=(rt_uint32_t *)_page_table+(vaddrStart>>20);
nSec=(vaddrEnd>>20)-(vaddrStart>>20); nSec=(vaddrEnd>>20)-(vaddrStart>>20);
for(i=0;i<=nSec;i++) for(i=0;i<=nSec;i++)
{ {
*pTT = attr |(((paddrStart>>20)+i)<<20); *pTT = attr |(((paddrStart>>20)+i)<<20);
pTT++; pTT++;
} }
} }
void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size) void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size)
{ {
/* disable I/D cache */ /* disable I/D cache */
mmu_disable_dcache(); mmu_disable_dcache();
mmu_disable_icache(); mmu_disable_icache();
mmu_disable(); mmu_disable();
mmu_invalidate_tlb(); mmu_invalidate_tlb();
/* set page table */ /* set page table */
for (; size > 0; size--) for (; size > 0; size--)
{ {
mmu_setmtt(mdesc->vaddr_start, mdesc->vaddr_end, mmu_setmtt(mdesc->vaddr_start, mdesc->vaddr_end,
mdesc->paddr_start, mdesc->attr); mdesc->paddr_start, mdesc->attr);
mdesc++; mdesc++;
} }
/* set MMU table address */ /* set MMU table address */
mmu_setttbase((rt_uint32_t)_page_table); mmu_setttbase((rt_uint32_t)_page_table);
/* enables MMU */ /* enables MMU */
mmu_enable(); mmu_enable();

View File

@ -26,35 +26,35 @@
#include <rtthread.h> #include <rtthread.h>
#define CACHE_LINE_SIZE 32 #define CACHE_LINE_SIZE 32
#define DESC_SEC (0x2|(1<<4)) #define DESC_SEC (0x2|(1<<4))
#define CB (3<<2) //cache_on, write_back #define CB (3<<2) //cache_on, write_back
#define CNB (2<<2) //cache_on, write_through #define CNB (2<<2) //cache_on, write_through
#define NCB (1<<2) //cache_off,WR_BUF on #define NCB (1<<2) //cache_off,WR_BUF on
#define NCNB (0<<2) //cache_off,WR_BUF off #define NCNB (0<<2) //cache_off,WR_BUF off
#define AP_RW (3<<10) //supervisor=RW, user=RW #define AP_RW (3<<10) //supervisor=RW, user=RW
#define AP_RO (2<<10) //supervisor=RW, user=RO #define AP_RO (2<<10) //supervisor=RW, user=RO
#define DOMAIN_FAULT (0x0) #define DOMAIN_FAULT (0x0)
#define DOMAIN_CHK (0x1) #define DOMAIN_CHK (0x1)
#define DOMAIN_NOTCHK (0x3) #define DOMAIN_NOTCHK (0x3)
#define DOMAIN0 (0x0<<5) #define DOMAIN0 (0x0<<5)
#define DOMAIN1 (0x1<<5) #define DOMAIN1 (0x1<<5)
#define DOMAIN0_ATTR (DOMAIN_CHK<<0) #define DOMAIN0_ATTR (DOMAIN_CHK<<0)
#define DOMAIN1_ATTR (DOMAIN_FAULT<<2) #define DOMAIN1_ATTR (DOMAIN_FAULT<<2)
#define RW_CB (AP_RW|DOMAIN0|CB|DESC_SEC) /* Read/Write, cache, write back */ #define RW_CB (AP_RW|DOMAIN0|CB|DESC_SEC) /* Read/Write, cache, write back */
#define RW_CNB (AP_RW|DOMAIN0|CNB|DESC_SEC) /* Read/Write, cache, write through */ #define RW_CNB (AP_RW|DOMAIN0|CNB|DESC_SEC) /* Read/Write, cache, write through */
#define RW_NCNB (AP_RW|DOMAIN0|NCNB|DESC_SEC) /* Read/Write without cache and write buffer */ #define RW_NCNB (AP_RW|DOMAIN0|NCNB|DESC_SEC) /* Read/Write without cache and write buffer */
#define RW_FAULT (AP_RW|DOMAIN1|NCNB|DESC_SEC) /* Read/Write without cache and write buffer */ #define RW_FAULT (AP_RW|DOMAIN1|NCNB|DESC_SEC) /* Read/Write without cache and write buffer */
struct mem_desc { struct mem_desc {
rt_uint32_t vaddr_start; rt_uint32_t vaddr_start;
rt_uint32_t vaddr_end; rt_uint32_t vaddr_end;
rt_uint32_t paddr_start; rt_uint32_t paddr_start;
rt_uint32_t attr; rt_uint32_t attr;
}; };
void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size); void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size);

View File

@ -26,14 +26,14 @@
/*****************************/ /*****************************/
/* CPU Mode */ /* CPU Mode */
/*****************************/ /*****************************/
#define USERMODE 0x10 #define USERMODE 0x10
#define FIQMODE 0x11 #define FIQMODE 0x11
#define IRQMODE 0x12 #define IRQMODE 0x12
#define SVCMODE 0x13 #define SVCMODE 0x13
#define ABORTMODE 0x17 #define ABORTMODE 0x17
#define UNDEFMODE 0x1b #define UNDEFMODE 0x1b
#define MODEMASK 0x1f #define MODEMASK 0x1f
#define NOINT 0xc0 #define NOINT 0xc0
/** /**
* This function will initialize thread stack * This function will initialize thread stack
@ -46,30 +46,30 @@
* @return stack address * @return stack address
*/ */
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
rt_uint8_t *stack_addr, void *texit) rt_uint8_t *stack_addr, void *texit)
{ {
rt_uint32_t *stk; rt_uint32_t *stk;
stk = (rt_uint32_t*)stack_addr; stk = (rt_uint32_t*)stack_addr;
*(stk) = (rt_uint32_t)tentry; /* entry point */ *(stk) = (rt_uint32_t)tentry; /* entry point */
*(--stk) = (rt_uint32_t)texit; /* lr */ *(--stk) = (rt_uint32_t)texit; /* lr */
*(--stk) = 0; /* r12 */ *(--stk) = 0; /* r12 */
*(--stk) = 0; /* r11 */ *(--stk) = 0; /* r11 */
*(--stk) = 0; /* r10 */ *(--stk) = 0; /* r10 */
*(--stk) = 0; /* r9 */ *(--stk) = 0; /* r9 */
*(--stk) = 0; /* r8 */ *(--stk) = 0; /* r8 */
*(--stk) = 0; /* r7 */ *(--stk) = 0; /* r7 */
*(--stk) = 0; /* r6 */ *(--stk) = 0; /* r6 */
*(--stk) = 0; /* r5 */ *(--stk) = 0; /* r5 */
*(--stk) = 0; /* r4 */ *(--stk) = 0; /* r4 */
*(--stk) = 0; /* r3 */ *(--stk) = 0; /* r3 */
*(--stk) = 0; /* r2 */ *(--stk) = 0; /* r2 */
*(--stk) = 0; /* r1 */ *(--stk) = 0; /* r1 */
*(--stk) = (rt_uint32_t)parameter; /* r0 : argument */ *(--stk) = (rt_uint32_t)parameter; /* r0 : argument */
*(--stk) = SVCMODE; /* cpsr */ *(--stk) = SVCMODE; /* cpsr */
*(--stk) = SVCMODE; /* spsr */ *(--stk) = SVCMODE; /* spsr */
/* return task's current stack address */ /* return task's current stack address */
return (rt_uint8_t *)stk; return (rt_uint8_t *)stk;
} }

View File

@ -0,0 +1,327 @@
/*
* File : start.S
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2011-01-13 weety first version
*/
#define CONFIG_STACKSIZE 512
#define S_FRAME_SIZE (18*4) //72
@#define S_SPSR (17*4) //SPSR
@#define S_CPSR (16*4) //CPSR
#define S_PC (15*4) //R15
@#define S_LR (14*4) //R14
@#define S_SP (13*4) //R13
@#define S_IP (12*4) //R12
@#define S_FP (11*4) //R11
@#define S_R10 (10*4)
@#define S_R9 (9*4)
@#define S_R8 (8*4)
@#define S_R7 (7*4)
@#define S_R6 (6*4)
@#define S_R5 (5*4)
@#define S_R4 (4*4)
@#define S_R3 (3*4)
@#define S_R2 (2*4)
@#define S_R1 (1*4)
@#define S_R0 (0*4)
#define MODE_SYS 0x1F
#define MODE_FIQ 0x11
#define MODE_IRQ 0x12
#define MODE_SVC 0x13
#define MODE_ABT 0x17
#define MODE_UND 0x1B
#define MODEMASK 0x1F
#define NOINT 0xC0
.include "rt_low_level_gcc.inc"
@; stack table-----------------------------------------------------------------
.section .nobss, "w"
.space UND_STK_SIZE
.global UND_STACK_START
UND_STACK_START:
.space SVC_STK_SIZE
.align 2
.global SVC_STACK_START
SVC_STACK_START:
.space ABT_STK_SIZE
.align 2
.global ABT_STACK_START
ABT_STACK_START:
.space IRQ_STK_SIZE
.align 2
.global IRQ_STACK_START
IRQ_STACK_START:
.space FIQ_STK_SIZE
.align 2
.global FIQ_STACK_START
FIQ_STACK_START:
.skip SYS_STK_SIZE
.align 2
.global SYS_STACK_START
SYS_STACK_START:
@; Jump vector table-----------------------------------------------------------
.section .init, "ax"
.arm
.global entry
entry:
LDR PC, vector_reset
LDR PC, vector_undef
LDR PC, vector_swi
LDR PC, vector_pabt
LDR PC, vector_dabt
LDR PC, vector_resv
LDR PC, vector_irq
LDR PC, vector_fiq
vector_reset:
.word Reset_Handler
vector_undef:
.word Undef_Handler
vector_swi:
.word SWI_Handler
vector_pabt:
.word PAbt_Handler
vector_dabt:
.word DAbt_Handler
vector_resv:
.word Resv_Handler
vector_irq:
.word IRQ_Handler
vector_fiq:
.word FIQ_Handler
.balignl 16,0xdeadbeef
@;----------------- Reset Handler ---------------------------------------------
.global rt_low_level_init
.global main
.global Reset_Handler
Reset_Handler:
@; Set the cpu to SVC32 mode
MRS R0, CPSR
BIC R0, R0, #MODEMASK
ORR R0, R0, #MODE_SVC|NOINT
MSR CPSR, R0
LDR SP, =SVC_STACK_START
@; Call low level init function,
@; disable and clear all IRQs and remap internal ram to 0x00000000.
LDR R0, =rt_low_level_init
BLX R0
@; Copy Exception Vectors to Internal RAM
LDR R8, =entry @; Source
LDR R9, =0x00000000 @; Destination
CMP R8, R9
BEQ Setup_Stack
LDMIA R8!, {R0-R7} @; Load Vectors
STMIA R9!, {R0-R7} @; Store Vectors
LDMIA R8!, {R0-R7} @; Load Handler Addresses
STMIA R9!, {R0-R7} @; Store Handler Addresses
Setup_Stack:
@; Setup Stack for each mode
MRS R0, CPSR
BIC R0, R0, #MODEMASK
ORR R1, R0, #MODE_UND|NOINT
MSR CPSR_cxsf, R1 @; Undef mode
LDR SP, =UND_STACK_START
ORR R1, R0, #MODE_ABT|NOINT
MSR CPSR_cxsf, R1 @; Abort mode
LDR SP, =ABT_STACK_START
ORR R1, R0, #MODE_IRQ|NOINT
MSR CPSR_cxsf, R1 @; IRQ mode
LDR SP, =IRQ_STACK_START
ORR R1, R0, #MODE_FIQ|NOINT
MSR CPSR_cxsf, R1 @; FIQ mode
LDR SP, =FIQ_STACK_START
ORR R1, R0, #MODE_SYS|NOINT
MSR CPSR_cxsf,R1 @; SYS/User mode
LDR SP, =SYS_STACK_START
ORR R1, R0, #MODE_SVC|NOINT
MSR CPSR_cxsf, R1 @; SVC mode
LDR SP, =SVC_STACK_START
@; clear .bss
MOV R0, #0 @; get a zero
LDR R1, =__bss_start__ @; bss start
LDR R2, =__bss_end__ @; bss end
bss_clear_loop:
CMP R1, R2 @; check if data to clear
STRLO R0, [R1], #4 @; clear 4 bytes
BLO bss_clear_loop @; loop until done
@; call C++ constructors of global objects
LDR R0, =__ctors_start__
LDR R1, =__ctors_end__
ctor_loop:
CMP R0, R1
BEQ ctor_end
LDR R2, [R0], #4
STMFD SP!, {R0-R1}
MOV LR, PC
BX R2
LDMFD SP!, {R0-R1}
B ctor_loop
ctor_end:
@; Enter the C code
LDR R0, =main
BLX R0
@;----------------- Exception Handler -----------------------------------------
.global rt_hw_trap_udef
.global rt_hw_trap_swi
.global rt_hw_trap_pabt
.global rt_hw_trap_dabt
.global rt_hw_trap_resv
.global rt_hw_trap_irq
.global rt_hw_trap_fiq
.global rt_interrupt_enter
.global rt_interrupt_leave
.global rt_thread_switch_interrupt_flag
.global rt_interrupt_from_thread
.global rt_interrupt_to_thread
.align 5
Undef_Handler:
SUB SP, SP, #S_FRAME_SIZE
STMIA SP, {R0 - R12} @; Calling R0-R12
ADD R8, SP, #S_PC
STMDB R8, {SP, LR} @; Calling SP, LR
STR LR, [R8, #0] @; Save calling PC
MRS R6, SPSR
STR R6, [R8, #4] @; Save CPSR
STR R0, [R8, #8] @; Save SPSR
MOV R0, SP
BL rt_hw_trap_udef
.align 5
SWI_Handler:
BL rt_hw_trap_swi
.align 5
PAbt_Handler:
BL rt_hw_trap_pabt
.align 5
DAbt_Handler:
SUB SP, SP, #S_FRAME_SIZE
STMIA SP, {R0 - R12} @; Calling R0-R12
ADD R8, SP, #S_PC
STMDB R8, {SP, LR} @; Calling SP, LR
STR LR, [R8, #0] @; Save calling PC
MRS R6, SPSR
STR R6, [R8, #4] @; Save CPSR
STR R0, [R8, #8] @; Save SPSR
MOV R0, SP
BL rt_hw_trap_dabt
.align 5
Resv_Handler:
BL rt_hw_trap_resv
.align 5
FIQ_Handler:
STMFD SP!, {R0-R7,LR}
BL rt_hw_trap_fiq
LDMFD SP!, {R0-R7,LR}
SUBS PC, LR, #4
.align 5
IRQ_Handler:
STMFD SP!, {R0-R12,LR}
BL rt_interrupt_enter
BL rt_hw_trap_irq
BL rt_interrupt_leave
@; If rt_thread_switch_interrupt_flag set,
@; jump to rt_hw_context_switch_interrupt_do and don't return
LDR R0, =rt_thread_switch_interrupt_flag
LDR R1, [R0]
CMP R1, #1
BEQ rt_hw_context_switch_interrupt_do
LDMFD SP!, {R0-R12,LR}
SUBS PC, LR, #4
@;------ void rt_hw_context_switch_interrupt_do(rt_base_t flag) -----------------
rt_hw_context_switch_interrupt_do:
MOV R1, #0 @; Clear flag
STR R1, [R0] @; Save to flag variable
LDMFD SP!, {R0-R12,LR} @; Reload saved registers
STMFD SP!, {R0-R3} @; Save R0-R3
MOV R1, SP @; Save old task's SP to R1
ADD SP, SP, #16 @; Restore SP
SUB R2, LR, #4 @; Save old task's PC to R2
MRS R3, SPSR @; Get CPSR of interrupt thread
MSR CPSR_c, #MODE_SVC|NOINT @; Switch to SVC mode and no interrupt
STMFD SP!, {R2} @; Push old task's PC
STMFD SP!, {R4-R12,LR} @; Push old task's LR,R12-R4
MOV R4, R1 @; Special optimised code below
MOV R5, R3
LDMFD R4!, {R0-R3}
STMFD SP!, {R0-R3} @; Push old task's R3-R0
STMFD SP!, {R5} @; Push old task's CPSR
MRS R4, SPSR
STMFD SP!, {R4} @; Push old task's SPSR
LDR R4, =rt_interrupt_from_thread
LDR R5, [R4] @; R5 = stack ptr in old tasks's TCB
STR SP, [R5] @; Store SP in preempted tasks's TCB
LDR R6, =rt_interrupt_to_thread
LDR R6, [R6] @; R6 = stack ptr in new tasks's TCB
LDR SP, [R6] @; Get new task's stack pointer
LDMFD SP!, {R4} @; Pop new task's SPSR
MSR SPSR_cxsf, R4
LDMFD SP!, {R4} @; Pop new task's CPSR
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ @; pop new task's R0-R12,LR & PC

View File

@ -0,0 +1,296 @@
;/*
; * File : start.S
; * This file is part of RT-Thread RTOS
; * COPYRIGHT (C) 2006, RT-Thread Development Team
; *
; * This program is free software; you can redistribute it and/or modify
; * it under the terms of the GNU General Public License as published by
; * the Free Software Foundation; either version 2 of the License, or
; * (at your option) any later version.
; *
; * This program is distributed in the hope that it will be useful,
; * but WITHOUT ANY WARRANTY; without even the implied warranty of
; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; * GNU General Public License for more details.
; *
; * You should have received a copy of the GNU General Public License along
; * with this program; if not, write to the Free Software Foundation, Inc.,
; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; *
; * Change Logs:
; * Date Author Notes
; * 2011-01-13 weety first version
; */
#define S_FRAME_SIZE (18*4) ;72
;#define S_SPSR (17*4) ;SPSR
;#define S_CPSR (16*4) ;CPSR
#define S_PC (15*4) ;R15
;#define S_LR (14*4) ;R14
;#define S_SP (13*4) ;R13
;#define S_IP (12*4) ;R12
;#define S_FP (11*4) ;R11
;#define S_R10 (10*4)
;#define S_R9 (9*4)
;#define S_R8 (8*4)
;#define S_R7 (7*4)
;#define S_R6 (6*4)
;#define S_R5 (5*4)
;#define S_R4 (4*4)
;#define S_R3 (3*4)
;#define S_R2 (2*4)
;#define S_R1 (1*4)
;#define S_R0 (0*4)
#define MODE_SYS 0x1F
#define MODE_FIQ 0x11
#define MODE_IRQ 0x12
#define MODE_SVC 0x13
#define MODE_ABT 0x17
#define MODE_UND 0x1B
#define MODEMASK 0x1F
#define NOINT 0xC0
#include "rt_low_level_iar.inc"
MODULE ?cstartup
SECTION .noinit:DATA:NOROOT(3)
DATA
DS8 UND_STK_SIZE
PUBLIC UND_STACK_START
UND_STACK_START:
ALIGNRAM 2
DS8 ABT_STK_SIZE
PUBLIC ABT_STACK_START
ABT_STACK_START:
ALIGNRAM 2
DS8 FIQ_STK_SIZE
PUBLIC FIQ_STACK_START
FIQ_STACK_START:
ALIGNRAM 2
DS8 IRQ_STK_SIZE
PUBLIC IRQ_STACK_START
IRQ_STACK_START:
ALIGNRAM 2
DS8 SVC_STK_SIZE
PUBLIC SVC_STACK_START
SVC_STACK_START:
ALIGNRAM 2
DS8 SYS_STK_SIZE
PUBLIC SYS_STACK_START
SYS_STACK_START:
;--------------Jump vector table------------------------------------------------
SECTION .intvec:CODE:ROOT(2)
ARM
PUBLIC Entry_Point
Entry_Point:
__iar_init$$done: ; The interrupt vector is not needed
; until after copy initialization is done
LDR PC, vector_reset
LDR PC, vector_undef
LDR PC, vector_swi
LDR PC, vector_pabt
LDR PC, vector_dabt
LDR PC, vector_resv
LDR PC, vector_irq
LDR PC, vector_fiq
vector_reset:
DC32 Reset_Handler
vector_undef:
DC32 Undef_Handler
vector_swi:
DC32 SWI_Handler
vector_pabt:
DC32 PAbt_Handler
vector_dabt:
DC32 DAbt_Handler
vector_resv:
DC32 Resv_Handler
vector_irq:
DC32 IRQ_Handler
vector_fiq:
DC32 FIQ_Handler
;----------------- Reset Handler -----------------------------------------------
EXTERN rt_low_level_init
EXTERN ?main
PUBLIC __iar_program_start
__iar_program_start:
Reset_Handler:
; Set the cpu to SVC32 mode
MRS R0, CPSR
BIC R0, R0, #MODEMASK
ORR R0, R0, #MODE_SVC|NOINT
MSR CPSR_cxsf, R0
LDR SP, =SVC_STACK_START
; Call low level init function,
; disable and clear all IRQs and remap internal ram to 0x00000000.
LDR R0, =rt_low_level_init
BLX R0
; Copy Exception Vectors to Internal RAM
LDR R8, =Entry_Point ; Source
LDR R9, =0x00000000 ; Destination
CMP R8, R9
BEQ Setup_Stack
LDMIA R8!, {R0-R7} ; Load Vectors
STMIA R9!, {R0-R7} ; Store Vectors
LDMIA R8!, {R0-R7} ; Load Handler Addresses
STMIA R9!, {R0-R7} ; Store Handler Addresses
Setup_Stack:
; Setup Stack for each mode
MRS R0, CPSR
BIC R0, R0, #MODEMASK
ORR R1, R0, #MODE_UND|NOINT
MSR CPSR_cxsf, R1 ; Undef mode
LDR SP, =UND_STACK_START
ORR R1,R0,#MODE_ABT|NOINT
MSR CPSR_cxsf,R1 ; Abort mode
LDR SP, =ABT_STACK_START
ORR R1,R0,#MODE_IRQ|NOINT
MSR CPSR_cxsf,R1 ; IRQ mode
LDR SP, =IRQ_STACK_START
ORR R1,R0,#MODE_FIQ|NOINT
MSR CPSR_cxsf,R1 ; FIQ mode
LDR SP, =FIQ_STACK_START
ORR R1,R0,#MODE_SYS|NOINT
MSR CPSR_cxsf,R1 ; SYS/User mode
LDR SP, =SYS_STACK_START
ORR R1,R0,#MODE_SVC|NOINT
MSR CPSR_cxsf,R1 ; SVC mode
LDR SP, =SVC_STACK_START
; Enter the C code
LDR R0, =?main
BLX R0
;----------------- Exception Handler -------------------------------------------
IMPORT rt_hw_trap_udef
IMPORT rt_hw_trap_swi
IMPORT rt_hw_trap_pabt
IMPORT rt_hw_trap_dabt
IMPORT rt_hw_trap_resv
IMPORT rt_hw_trap_irq
IMPORT rt_hw_trap_fiq
IMPORT rt_interrupt_enter
IMPORT rt_interrupt_leave
IMPORT rt_thread_switch_interrupt_flag
IMPORT rt_interrupt_from_thread
IMPORT rt_interrupt_to_thread
SECTION .text:CODE:ROOT(2)
ARM
Undef_Handler:
SUB SP, SP, #S_FRAME_SIZE
STMIA SP, {R0 - R12} ; Calling R0-R12
ADD R8, SP, #S_PC
STMDB R8, {SP, LR} ; Calling SP, LR
STR LR, [R8, #0] ; Save calling PC
MRS R6, SPSR
STR R6, [R8, #4] ; Save CPSR
STR R0, [R8, #8] ; Save SPSR
MOV R0, SP
BL rt_hw_trap_udef
SWI_Handler:
BL rt_hw_trap_swi
PAbt_Handler:
BL rt_hw_trap_pabt
DAbt_Handler:
SUB SP, SP, #S_FRAME_SIZE
STMIA SP, {R0 - R12} ; Calling R0-R12
ADD R8, SP, #S_PC
STMDB R8, {SP, LR} ; Calling SP, LR
STR LR, [R8, #0] ; Save calling PC
MRS R6, SPSR
STR R6, [R8, #4] ; Save CPSR
STR R0, [R8, #8] ; Save SPSR
MOV R0, SP
BL rt_hw_trap_dabt
Resv_Handler:
BL rt_hw_trap_resv
IRQ_Handler:
STMFD SP!, {R0-R12,LR}
BL rt_interrupt_enter
BL rt_hw_trap_irq
BL rt_interrupt_leave
; If rt_thread_switch_interrupt_flag set,
; jump to rt_hw_context_switch_interrupt_do and don't return
LDR R0, =rt_thread_switch_interrupt_flag
LDR R1, [R0]
CMP R1, #1
BEQ rt_hw_context_switch_interrupt_do
LDMFD SP!, {R0-R12,LR}
SUBS PC, LR, #4
FIQ_Handler:
STMFD SP!, {R0-R7,LR}
BL rt_hw_trap_fiq
LDMFD SP!, {R0-R7,LR}
SUBS PC, LR, #4
;------ void rt_hw_context_switch_interrupt_do(rt_base_t flag) -----------------
rt_hw_context_switch_interrupt_do:
MOV R1, #0 ; Clear flag
STR R1, [R0] ; Save to flag variable
LDMFD SP!, {R0-R12,LR} ; Reload saved registers
STMFD SP!, {R0-R3} ; Save R0-R3
MOV R1, SP ; Save old task's SP to R1
ADD SP, SP, #16 ; Restore SP
SUB R2, LR, #4 ; Save old task's PC to R2
MRS R3, SPSR ; Get CPSR of interrupt thread
MSR CPSR_c, #MODE_SVC|NOINT ; Switch to SVC mode and no interrupt
STMFD SP!, {R2} ; Push old task's PC
STMFD SP!, {R4-R12,LR} ; Push old task's LR,R12-R4
MOV R4, R1 ; Special optimised code below
MOV R5, R3
LDMFD R4!, {R0-R3}
STMFD SP!, {R0-R3} ; Push old task's R3-R0
STMFD SP!, {R5} ; Push old task's CPSR
MRS R4, SPSR
STMFD SP!, {R4} ; Push old task's SPSR
LDR R4, =rt_interrupt_from_thread
LDR R5, [R4] ; R5 = stack ptr in old tasks's TCB
STR SP, [R5] ; Store SP in preempted tasks's TCB
LDR R6, =rt_interrupt_to_thread
LDR R6, [R6] ; R6 = stack ptr in new tasks's TCB
LDR SP, [R6] ; Get new task's stack pointer
LDMFD SP!, {R4} ; Pop new task's SPSR
MSR SPSR_cxsf, R4
LDMFD SP!, {R4} ; Pop new task's CPSR
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; pop new task's R0-R12,LR & PC
END

View File

@ -0,0 +1,338 @@
;/*
; * File : start_rvds.S
; * This file is part of RT-Thread RTOS
; * COPYRIGHT (C) 2006, RT-Thread Development Team
; *
; * This program is free software; you can redistribute it and/or modify
; * it under the terms of the GNU General Public License as published by
; * the Free Software Foundation; either version 2 of the License, or
; * (at your option) any later version.
; *
; * This program is distributed in the hope that it will be useful,
; * but WITHOUT ANY WARRANTY; without even the implied warranty of
; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; * GNU General Public License for more details.
; *
; * You should have received a copy of the GNU General Public License along
; * with this program; if not, write to the Free Software Foundation, Inc.,
; * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; *
; * Change Logs:
; * Date Author Notes
; * 2011-08-14 weety first version
; */
; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
S_FRAME_SIZE EQU (18*4) ;72
;S_SPSR EQU (17*4) ;SPSR
;S_CPSR EQU (16*4) ;CPSR
S_PC EQU (15*4) ;R15
;S_LR EQU (14*4) ;R14
;S_SP EQU (13*4) ;R13
;S_IP EQU (12*4) ;R12
;S_FP EQU (11*4) ;R11
;S_R10 EQU (10*4)
;S_R9 EQU (9*4)
;S_R8 EQU (8*4)
;S_R7 EQU (7*4)
;S_R6 EQU (6*4)
;S_R5 EQU (5*4)
;S_R4 EQU (4*4)
;S_R3 EQU (3*4)
;S_R2 EQU (2*4)
;S_R1 EQU (1*4)
;S_R0 EQU (0*4)
MODE_USR EQU 0X10
MODE_FIQ EQU 0X11
MODE_IRQ EQU 0X12
MODE_SVC EQU 0X13
MODE_ABT EQU 0X17
MODE_UND EQU 0X1B
MODE_SYS EQU 0X1F
MODEMASK EQU 0X1F
NOINT EQU 0xC0
;----------------------- Stack and Heap Definitions ----------------------------
AREA STACK, NOINIT, READWRITE, ALIGN=3
GET rt_low_level_keil.inc
;-------------- stack area -----------------------------------------------------
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem
SPACE UND_STK_SIZE
EXPORT UND_STACK_START
UND_STACK_START
ALIGN 8
SPACE ABT_STK_SIZE
EXPORT ABT_STACK_START
ABT_STACK_START
ALIGN 8
SPACE FIQ_STK_SIZE
EXPORT FIQ_STACK_START
FIQ_STACK_START
ALIGN 8
SPACE IRQ_STK_SIZE
EXPORT IRQ_STACK_START
IRQ_STACK_START
ALIGN 8
SPACE SVC_STK_SIZE
EXPORT SVC_STACK_START
SVC_STACK_START
ALIGN 8
SPACE SYS_STK_SIZE
EXPORT SYS_STACK_START
SYS_STACK_START
Stack_Top
Heap_Size EQU 0x00000000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem
SPACE Heap_Size
__heap_limit
;----------------------- CODE --------------------------------------------------
PRESERVE8
; Area Definition and Entry Point
; Startup Code must be linked first at Address at which it expects to run.
;--------------Jump vector table------------------------------------------------
EXPORT Entry_Point
AREA RESET, CODE, READONLY
ARM
Entry_Point
LDR PC, vector_reset
LDR PC, vector_undef
LDR PC, vector_swi
LDR PC, vector_pabt
LDR PC, vector_dabt
LDR PC, vector_resv
LDR PC, vector_irq
LDR PC, vector_fiq
vector_reset
DCD Reset_Handler
vector_undef
DCD Undef_Handler
vector_swi
DCD SWI_Handler
vector_pabt
DCD PAbt_Handler
vector_dabt
DCD DAbt_Handler
vector_resv
DCD Resv_Handler
vector_irq
DCD IRQ_Handler
vector_fiq
DCD FIQ_Handler
;----------------- Reset Handler -----------------------------------------------
IMPORT rt_low_level_init
IMPORT __main
EXPORT Reset_Handler
Reset_Handler
; set the cpu to SVC32 mode
MRS R0,CPSR
BIC R0,R0,#MODEMASK
ORR R0,R0,#MODE_SVC
MSR CPSR_CXSF,R0
LDR SP, =SVC_STACK_START
; Call low level init function,
; disable and clear all IRQs and remap internal ram to 0x00000000.
LDR R0, =rt_low_level_init
BLX R0
; Copy Exception Vectors to Internal RAM
LDR R8, =Entry_Point ; Source
LDR R9, =0x00000000 ; Destination
CMP R8, R9
BEQ Setup_Stack
LDMIA R8!, {R0-R7} ; Load Vectors
STMIA R9!, {R0-R7} ; Store Vectors
LDMIA R8!, {R0-R7} ; Load Handler Addresses
STMIA R9!, {R0-R7} ; Store Handler Addresses
Setup_Stack
; Setup Stack for each mode
MRS R0, CPSR
BIC R0, R0, #MODEMASK
ORR R1, R0, #MODE_UND:OR:NOINT
MSR CPSR_cxsf, R1 ; Undef mode
LDR SP, =UND_STACK_START
ORR R1,R0,#MODE_ABT:OR:NOINT
MSR CPSR_cxsf,R1 ; Abort mode
LDR SP, =ABT_STACK_START
ORR R1,R0,#MODE_IRQ:OR:NOINT
MSR CPSR_cxsf,R1 ; IRQ mode
LDR SP, =IRQ_STACK_START
ORR R1,R0,#MODE_FIQ:OR:NOINT
MSR CPSR_cxsf,R1 ; FIQ mode
LDR SP, =FIQ_STACK_START
ORR R1,R0,#MODE_SYS:OR:NOINT
MSR CPSR_cxsf,R1 ; SYS/User mode
LDR SP, =SYS_STACK_START
ORR R1,R0,#MODE_SVC:OR:NOINT
MSR CPSR_cxsf,R1 ; SVC mode
LDR SP, =SVC_STACK_START
; Enter the C code
LDR R0, =__main
BLX R0
;----------------- Exception Handler -------------------------------------------
IMPORT rt_hw_trap_udef
IMPORT rt_hw_trap_swi
IMPORT rt_hw_trap_pabt
IMPORT rt_hw_trap_dabt
IMPORT rt_hw_trap_resv
IMPORT rt_hw_trap_irq
IMPORT rt_hw_trap_fiq
IMPORT rt_interrupt_enter
IMPORT rt_interrupt_leave
IMPORT rt_thread_switch_interrupt_flag
IMPORT rt_interrupt_from_thread
IMPORT rt_interrupt_to_thread
Undef_Handler PROC
SUB SP, SP, #S_FRAME_SIZE
STMIA SP, {R0 - R12} ; Calling R0-R12
ADD R8, SP, #S_PC
STMDB R8, {SP, LR} ; Calling SP, LR
STR LR, [R8, #0] ; Save calling PC
MRS R6, SPSR
STR R6, [R8, #4] ; Save CPSR
STR R0, [R8, #8] ; Save SPSR
MOV R0, SP
BL rt_hw_trap_udef
ENDP
SWI_Handler PROC
BL rt_hw_trap_swi
ENDP
PAbt_Handler PROC
BL rt_hw_trap_pabt
ENDP
DAbt_Handler PROC
SUB SP, SP, #S_FRAME_SIZE
STMIA SP, {R0 - R12} ; Calling R0-R12
ADD R8, SP, #S_PC
STMDB R8, {SP, LR} ; Calling SP, LR
STR LR, [R8, #0] ; Save calling PC
MRS R6, SPSR
STR R6, [R8, #4] ; Save CPSR
STR R0, [R8, #8] ; Save SPSR
MOV R0, SP
BL rt_hw_trap_dabt
ENDP
Resv_Handler PROC
BL rt_hw_trap_resv
ENDP
FIQ_Handler PROC
STMFD SP!, {R0-R7,LR}
BL rt_hw_trap_fiq
LDMFD SP!, {R0-R7,LR}
SUBS PC, LR, #4
ENDP
IRQ_Handler PROC
STMFD SP!, {R0-R12,LR}
BL rt_interrupt_enter
BL rt_hw_trap_irq
BL rt_interrupt_leave
; If rt_thread_switch_interrupt_flag set,
; jump to rt_hw_context_switch_interrupt_do and don't return
LDR R0, =rt_thread_switch_interrupt_flag
LDR R1, [R0]
CMP R1, #1
BEQ rt_hw_context_switch_interrupt_do
LDMFD SP!, {R0-R12,LR}
SUBS PC, LR, #4
ENDP
;------ void rt_hw_context_switch_interrupt_do(rt_base_t flag) -----------------
rt_hw_context_switch_interrupt_do PROC
MOV R1, #0 ; Clear flag
STR R1, [R0] ; Save to flag variable
LDMFD SP!, {R0-R12,LR} ; Reload saved registers
STMFD SP!, {R0-R3} ; Save R0-R3
MOV R1, SP ; Save old task's SP to R1
ADD SP, SP, #16 ; Restore SP
SUB R2, LR, #4 ; Save old task's PC to R2
MRS R3, SPSR ; Get CPSR of interrupt thread
MSR CPSR_c, #MODE_SVC:OR:NOINT ; Switch to SVC mode and no interrupt
STMFD SP!, {R2} ; Push old task's PC
STMFD SP!, {R4-R12,LR} ; Push old task's LR,R12-R4
MOV R4, R1 ; Special optimised code below
MOV R5, R3
LDMFD R4!, {R0-R3}
STMFD SP!, {R0-R3} ; Push old task's R3-R0
STMFD SP!, {R5} ; Push old task's CPSR
MRS R4, SPSR
STMFD SP!, {R4} ; Push old task's SPSR
LDR R4, =rt_interrupt_from_thread
LDR R5, [R4] ; R5 = stack ptr in old tasks's TCB
STR SP, [R5] ; Store SP in preempted tasks's TCB
LDR R6, =rt_interrupt_to_thread
LDR R6, [R6] ; R6 = stack ptr in new tasks's TCB
LDR SP, [R6] ; Get new task's stack pointer
LDMFD SP!, {R4} ; Pop new task's SPSR
MSR SPSR_cxsf, R4
LDMFD SP!, {R4} ; Pop new task's CPSR
MSR SPSR_cxsf, R4
LDMFD SP!, {R0-R12,LR,PC}^ ; pop new task's R0-R12,LR & PC
ENDP
IF :DEF:__MICROLIB
EXPORT __heap_base
EXPORT __heap_limit
ELSE
; User Initial Stack & Heap
AREA |.text|, CODE, READONLY
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem
LDR R1, = (Stack_Mem + SYS_STK_SIZE)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR
ENDIF
END

View File

@ -25,7 +25,7 @@
#include <rtthread.h> #include <rtthread.h>
#include <rthw.h> #include <rthw.h>
#include "at91sam926x.h" #include <interrupt.h>
/** /**
* @addtogroup AT91SAM926X * @addtogroup AT91SAM926X
@ -37,6 +37,28 @@ extern struct rt_thread *rt_current_thread;
extern long list_thread(void); extern long list_thread(void);
#endif #endif
struct rt_hw_register
{
rt_uint32_t r0;
rt_uint32_t r1;
rt_uint32_t r2;
rt_uint32_t r3;
rt_uint32_t r4;
rt_uint32_t r5;
rt_uint32_t r6;
rt_uint32_t r7;
rt_uint32_t r8;
rt_uint32_t r9;
rt_uint32_t r10;
rt_uint32_t fp;
rt_uint32_t ip;
rt_uint32_t sp;
rt_uint32_t lr;
rt_uint32_t pc;
rt_uint32_t cpsr;
rt_uint32_t ORIG_r0;
};
/** /**
* this function will show registers of CPU * this function will show registers of CPU
* *
@ -105,7 +127,7 @@ void rt_hw_trap_pabt(struct rt_hw_register *regs)
rt_hw_show_register(regs); rt_hw_show_register(regs);
rt_kprintf("prefetch abort\n"); rt_kprintf("prefetch abort\n");
rt_kprintf("thread - %s stack:\n", rt_current_thread->name); rt_kprintf("thread - %s stack:\n", RT_NAME_MAX, rt_current_thread->name);
#ifdef RT_USING_FINSH #ifdef RT_USING_FINSH
list_thread(); list_thread();
@ -126,7 +148,7 @@ void rt_hw_trap_dabt(struct rt_hw_register *regs)
rt_hw_show_register(regs); rt_hw_show_register(regs);
rt_kprintf("data abort\n"); rt_kprintf("data abort\n");
rt_kprintf("thread - %s stack:\n", rt_current_thread->name); rt_kprintf("thread - %s stack:\n", RT_NAME_MAX, rt_current_thread->name);
#ifdef RT_USING_FINSH #ifdef RT_USING_FINSH
list_thread(); list_thread();
@ -149,21 +171,21 @@ void rt_hw_trap_resv(struct rt_hw_register *regs)
} }
extern struct rt_irq_desc irq_desc[]; extern struct rt_irq_desc irq_desc[];
rt_uint32_t rt_hw_interrupt_get_active(rt_uint32_t fiq_irq, rt_uint32_t* id);
extern void rt_hw_interrupt_ack(rt_uint32_t fiq_irq);
void rt_hw_trap_irq() void rt_hw_trap_irq()
{ {
rt_isr_handler_t isr_func; rt_isr_handler_t isr_func;
rt_uint32_t irqstat, irq, mask; rt_uint32_t irqstat, irq;
void *param; void *param;
//rt_kprintf("irq interrupt request\n"); //rt_kprintf("irq interrupt request\n");
/* get irq number */ /* get irq number */
irq = at91_sys_read(AT91_AIC_IVR); irqstat = rt_hw_interrupt_get_active(INT_IRQ, &irq);
/* clear pending register */
irqstat = at91_sys_read(AT91_AIC_ISR);
if (irqstat == 0) if (irqstat == 0)
{ {
rt_kprintf("No interrupt occur\n"); rt_kprintf("No interrupt occur\n");
at91_sys_write(AT91_AIC_EOICR, 0); rt_hw_interrupt_ack(INT_IRQ);
return; return;
} }
@ -173,7 +195,9 @@ void rt_hw_trap_irq()
/* turn to interrupt service routine */ /* turn to interrupt service routine */
isr_func(irq, param); isr_func(irq, param);
at91_sys_write(AT91_AIC_EOICR, 0x55555555); //EIOCR must be write any value after interrupt, or else can't response next interrupt // EIOCR must be write any value after interrupt,
// or else can't response next interrupt
rt_hw_interrupt_ack(INT_IRQ);
irq_desc[irq].counter ++; irq_desc[irq].counter ++;
} }