原始版本
This commit is contained in:
23
RT_Thread/libcpu/arm/AT91SAM7X/SConscript
Normal file
23
RT_Thread/libcpu/arm/AT91SAM7X/SConscript
Normal file
@ -0,0 +1,23 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
if rtconfig.PLATFORM in ['armcc', 'armclang']:
|
||||
src += Glob('*_rvds.S')
|
||||
|
||||
if rtconfig.PLATFORM in ['gcc']:
|
||||
src += Glob('*_init.S')
|
||||
src += Glob('*_gcc.S')
|
||||
|
||||
if rtconfig.PLATFORM in ['iccarm']:
|
||||
src += Glob('*_iar.S')
|
||||
|
||||
group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
95
RT_Thread/libcpu/arm/AT91SAM7X/context_gcc.S
Normal file
95
RT_Thread/libcpu/arm/AT91SAM7X/context_gcc.S
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-03-13 Bernard first version
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \addtogroup xgs3c4510
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
#define NOINT 0xc0
|
||||
|
||||
/*
|
||||
* rt_base_t rt_hw_interrupt_disable();
|
||||
*/
|
||||
.globl 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);
|
||||
*/
|
||||
.globl rt_hw_interrupt_enable
|
||||
rt_hw_interrupt_enable:
|
||||
msr cpsr, r0
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
|
||||
* r0 --> from
|
||||
* r1 --> to
|
||||
*/
|
||||
.globl rt_hw_context_switch
|
||||
rt_hw_context_switch:
|
||||
stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC)
|
||||
stmfd sp!, {r0-r12, lr} @ push lr & register file
|
||||
|
||||
mrs r4, cpsr
|
||||
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 cpsr_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
|
||||
*/
|
||||
.globl rt_hw_context_switch_to
|
||||
rt_hw_context_switch_to:
|
||||
ldr sp, [r0] @ get new task stack pointer
|
||||
|
||||
ldmfd sp!, {r4} @ pop new task spsr
|
||||
msr spsr_cxsf, r4
|
||||
ldmfd sp!, {r4} @ pop new task cpsr
|
||||
msr cpsr_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);
|
||||
*/
|
||||
.globl rt_thread_switch_interrupt_flag
|
||||
.globl rt_interrupt_from_thread
|
||||
.globl rt_interrupt_to_thread
|
||||
.globl rt_hw_context_switch_interrupt
|
||||
rt_hw_context_switch_interrupt:
|
||||
ldr r2, =rt_thread_switch_interrupt_flag
|
||||
ldr r3, [r2]
|
||||
cmp r3, #1
|
||||
beq _reswitch
|
||||
mov r3, #1 @ set rt_thread_switch_interrupt_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
|
||||
103
RT_Thread/libcpu/arm/AT91SAM7X/context_rvds.S
Normal file
103
RT_Thread/libcpu/arm/AT91SAM7X/context_rvds.S
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2009-01-20 Bernard first version
|
||||
*/
|
||||
|
||||
NOINT EQU 0xc0 ; disable interrupt in psr
|
||||
|
||||
AREA |.text|, CODE, READONLY, ALIGN=2
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
;/*
|
||||
; * rt_base_t rt_hw_interrupt_disable();
|
||||
; */
|
||||
rt_hw_interrupt_disable PROC
|
||||
EXPORT rt_hw_interrupt_disable
|
||||
MRS r0, cpsr
|
||||
ORR r1, r0, #NOINT
|
||||
MSR cpsr_c, r1
|
||||
BX lr
|
||||
ENDP
|
||||
|
||||
;/*
|
||||
; * void rt_hw_interrupt_enable(rt_base_t level);
|
||||
; */
|
||||
rt_hw_interrupt_enable PROC
|
||||
EXPORT rt_hw_interrupt_enable
|
||||
MSR cpsr_c, r0
|
||||
BX lr
|
||||
ENDP
|
||||
|
||||
;/*
|
||||
; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
|
||||
; * r0 --> from
|
||||
; * r1 --> to
|
||||
; */
|
||||
rt_hw_context_switch PROC
|
||||
EXPORT 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 cpsr_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);
|
||||
; * r0 --> to
|
||||
; */
|
||||
rt_hw_context_switch_to PROC
|
||||
EXPORT 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 cpsr_cxsf, r4
|
||||
|
||||
LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc
|
||||
ENDP
|
||||
|
||||
;/*
|
||||
; * 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
|
||||
|
||||
rt_hw_context_switch_interrupt PROC
|
||||
EXPORT rt_hw_context_switch_interrupt
|
||||
LDR r2, =rt_thread_switch_interrupt_flag
|
||||
LDR r3, [r2]
|
||||
CMP r3, #1
|
||||
BEQ _reswitch
|
||||
MOV r3, #1 ; set rt_thread_switch_interrupt_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]
|
||||
BX lr
|
||||
ENDP
|
||||
|
||||
END
|
||||
20
RT_Thread/libcpu/arm/AT91SAM7X/cpu.c
Normal file
20
RT_Thread/libcpu/arm/AT91SAM7X/cpu.c
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-08-23 Bernard first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup AT91SAM7X
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
|
||||
/*@}*/
|
||||
110
RT_Thread/libcpu/arm/AT91SAM7X/interrupt.c
Normal file
110
RT_Thread/libcpu/arm/AT91SAM7X/interrupt.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-08-23 Bernard first version
|
||||
* 2013-03-29 aozima Modify the interrupt interface implementations.
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
#define MAX_HANDLERS 32
|
||||
|
||||
/* exception and interrupt handler table */
|
||||
struct rt_irq_desc irq_desc[MAX_HANDLERS];
|
||||
|
||||
extern rt_atomic_t rt_interrupt_nest;
|
||||
|
||||
rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
|
||||
rt_uint32_t rt_thread_switch_interrupt_flag;
|
||||
|
||||
/**
|
||||
* @addtogroup AT91SAM7
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
static void rt_hw_interrupt_handler(int vector, void *param)
|
||||
{
|
||||
rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will initialize hardware interrupt
|
||||
*/
|
||||
void rt_hw_interrupt_init(void)
|
||||
{
|
||||
rt_base_t index;
|
||||
|
||||
/* init exceptions table */
|
||||
for(index=0; index < MAX_HANDLERS; index++)
|
||||
{
|
||||
irq_desc[index].handler = (rt_isr_handler_t)rt_hw_interrupt_handler;
|
||||
irq_desc[index].param = RT_NULL;
|
||||
}
|
||||
|
||||
for (index = 0; index < MAX_HANDLERS; index ++)
|
||||
{
|
||||
AT91C_BASE_AIC->AIC_SVR[index] = (rt_uint32_t)rt_hw_interrupt_handler;
|
||||
}
|
||||
|
||||
/* init interrupt nest, and context in thread sp */
|
||||
rt_interrupt_nest = 0;
|
||||
rt_interrupt_from_thread = 0;
|
||||
rt_interrupt_to_thread = 0;
|
||||
rt_thread_switch_interrupt_flag = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will mask a interrupt.
|
||||
* @param vector the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_mask(int vector)
|
||||
{
|
||||
/* disable interrupt */
|
||||
AT91C_BASE_AIC->AIC_IDCR = 1 << vector;
|
||||
|
||||
/* clear interrupt */
|
||||
AT91C_BASE_AIC->AIC_ICCR = 1 << vector;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will un-mask a interrupt.
|
||||
* @param vector the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_umask(int vector)
|
||||
{
|
||||
AT91C_BASE_AIC->AIC_IECR = 1 << vector;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will install a interrupt service routine to a interrupt.
|
||||
* @param vector the interrupt number
|
||||
* @param handler the interrupt service routine to be installed
|
||||
* @param param the parameter for interrupt service routine
|
||||
* @name unused.
|
||||
*
|
||||
* @return the old handler
|
||||
*/
|
||||
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
||||
void *param, const char *name)
|
||||
{
|
||||
rt_isr_handler_t old_handler = RT_NULL;
|
||||
if(vector >= 0 && vector < MAX_HANDLERS)
|
||||
{
|
||||
old_handler = irq_desc[vector].handler;
|
||||
if (handler != RT_NULL)
|
||||
{
|
||||
irq_desc[vector].handler = (rt_isr_handler_t)handler;
|
||||
irq_desc[vector].param = param;
|
||||
}
|
||||
}
|
||||
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
59
RT_Thread/libcpu/arm/AT91SAM7X/stack.c
Normal file
59
RT_Thread/libcpu/arm/AT91SAM7X/stack.c
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-08-23 Bernard the first version
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
|
||||
#define SVCMODE 0x13
|
||||
|
||||
/**
|
||||
* @addtogroup AT91SAM7
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/**
|
||||
* This function will initialize thread stack
|
||||
*
|
||||
* @param tentry the entry of thread
|
||||
* @param parameter the parameter of entry
|
||||
* @param stack_addr the beginning stack address
|
||||
* @param texit the function will be called when thread exit
|
||||
*
|
||||
* @return stack address
|
||||
*/
|
||||
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
|
||||
rt_uint8_t *stack_addr, void *texit)
|
||||
{
|
||||
rt_uint32_t *stk;
|
||||
|
||||
stack_addr += sizeof(rt_uint32_t);
|
||||
stack_addr = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 8);
|
||||
stk = (rt_uint32_t *)stack_addr;
|
||||
*(--stk) = (rt_uint32_t)tentry; /* entry point */
|
||||
*(--stk) = (rt_uint32_t)texit; /* lr */
|
||||
*(--stk) = 0xdeadbeef; /* r12 */
|
||||
*(--stk) = 0xdeadbeef; /* r11 */
|
||||
*(--stk) = 0xdeadbeef; /* r10 */
|
||||
*(--stk) = 0xdeadbeef; /* r9 */
|
||||
*(--stk) = 0xdeadbeef; /* r8 */
|
||||
*(--stk) = 0xdeadbeef; /* r7 */
|
||||
*(--stk) = 0xdeadbeef; /* r6 */
|
||||
*(--stk) = 0xdeadbeef; /* r5 */
|
||||
*(--stk) = 0xdeadbeef; /* r4 */
|
||||
*(--stk) = 0xdeadbeef; /* r3 */
|
||||
*(--stk) = 0xdeadbeef; /* r2 */
|
||||
*(--stk) = 0xdeadbeef; /* r1 */
|
||||
*(--stk) = (rt_uint32_t)parameter; /* r0 : argument */
|
||||
*(--stk) = SVCMODE; /* cpsr */
|
||||
*(--stk) = SVCMODE; /* spsr */
|
||||
|
||||
/* return task's current stack address */
|
||||
return (rt_uint8_t *)stk;
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
275
RT_Thread/libcpu/arm/AT91SAM7X/start_gcc.S
Normal file
275
RT_Thread/libcpu/arm/AT91SAM7X/start_gcc.S
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-08-31 Bernard first version
|
||||
*/
|
||||
|
||||
/* Internal Memory Base Addresses */
|
||||
.equ FLASH_BASE, 0x00100000
|
||||
.equ RAM_BASE, 0x00200000
|
||||
|
||||
/* Stack Configuration */
|
||||
.equ TOP_STACK, 0x00204000
|
||||
.equ UND_STACK_SIZE, 0x00000100
|
||||
.equ SVC_STACK_SIZE, 0x00000400
|
||||
.equ ABT_STACK_SIZE, 0x00000100
|
||||
.equ FIQ_STACK_SIZE, 0x00000100
|
||||
.equ IRQ_STACK_SIZE, 0x00000100
|
||||
.equ USR_STACK_SIZE, 0x00000004
|
||||
|
||||
/* ARM architecture definitions */
|
||||
.equ MODE_USR, 0x10
|
||||
.equ MODE_FIQ, 0x11
|
||||
.equ MODE_IRQ, 0x12
|
||||
.equ MODE_SVC, 0x13
|
||||
.equ MODE_ABT, 0x17
|
||||
.equ MODE_UND, 0x1B
|
||||
.equ MODE_SYS, 0x1F
|
||||
|
||||
.equ I_BIT, 0x80 /* when this bit is set, IRQ is disabled */
|
||||
.equ F_BIT, 0x40 /* when this bit is set, FIQ is disabled */
|
||||
|
||||
.section .init, "ax"
|
||||
.code 32
|
||||
.align 0
|
||||
.globl _start
|
||||
_start:
|
||||
b reset
|
||||
ldr pc, _vector_undef
|
||||
ldr pc, _vector_swi
|
||||
ldr pc, _vector_pabt
|
||||
ldr pc, _vector_dabt
|
||||
nop /* reserved vector */
|
||||
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
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
/* the system entry */
|
||||
reset:
|
||||
/* disable watchdog */
|
||||
ldr r0, =0xFFFFFD40
|
||||
ldr r1, =0x00008000
|
||||
str r1, [r0, #0x04]
|
||||
|
||||
/* enable the main oscillator */
|
||||
ldr r0, =0xFFFFFC00
|
||||
ldr r1, =0x00000601
|
||||
str r1, [r0, #0x20]
|
||||
|
||||
/* wait for main oscillator to stabilize */
|
||||
moscs_loop:
|
||||
ldr r2, [r0, #0x68]
|
||||
ands r2, r2, #1
|
||||
beq moscs_loop
|
||||
|
||||
/* set up the PLL */
|
||||
ldr r1, =0x00191C05
|
||||
str r1, [r0, #0x2C]
|
||||
|
||||
/* wait for PLL to lock */
|
||||
pll_loop:
|
||||
ldr r2, [r0, #0x68]
|
||||
ands r2, r2, #0x04
|
||||
beq pll_loop
|
||||
|
||||
/* select clock */
|
||||
ldr r1, =0x00000007
|
||||
str r1, [r0, #0x30]
|
||||
|
||||
#ifdef __FLASH_BUILD__
|
||||
/* copy exception vectors into internal sram */
|
||||
/*
|
||||
mov r8, #RAM_BASE
|
||||
ldr r9, =_start
|
||||
ldmia r9!, {r0-r7}
|
||||
stmia r8!, {r0-r7}
|
||||
ldmia r9!, {r0-r6}
|
||||
stmia r8!, {r0-r6}
|
||||
*/
|
||||
#endif
|
||||
|
||||
/* setup stack for each mode */
|
||||
ldr r0, =TOP_STACK
|
||||
|
||||
/* set stack */
|
||||
/* undefined instruction mode */
|
||||
msr cpsr_c, #MODE_UND|I_BIT|F_BIT
|
||||
mov sp, r0
|
||||
sub r0, r0, #UND_STACK_SIZE
|
||||
|
||||
/* abort mode */
|
||||
msr cpsr_c, #MODE_ABT|I_BIT|F_BIT
|
||||
mov sp, r0
|
||||
sub r0, r0, #ABT_STACK_SIZE
|
||||
|
||||
/* FIQ mode */
|
||||
msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT
|
||||
mov sp, r0
|
||||
sub r0, r0, #FIQ_STACK_SIZE
|
||||
|
||||
/* IRQ mode */
|
||||
msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT
|
||||
mov sp, r0
|
||||
sub r0, r0, #IRQ_STACK_SIZE
|
||||
|
||||
/* supervisor mode */
|
||||
msr cpsr_c, #MODE_SVC|I_BIT|F_BIT
|
||||
mov sp, r0
|
||||
|
||||
/* remap SRAM to 0x0000 */
|
||||
/*
|
||||
ldr r0, =0xFFFFFF00
|
||||
mov r1, #0x01
|
||||
str r1, [r0]
|
||||
*/
|
||||
|
||||
/* mask all IRQs */
|
||||
ldr r1, =0xFFFFF124
|
||||
ldr r0, =0XFFFFFFFF
|
||||
str r0, [r1]
|
||||
|
||||
/* copy .data to SRAM */
|
||||
ldr r1, =_sidata /* .data start in image */
|
||||
ldr r2, =_edata /* .data end in image */
|
||||
ldr r3, =_sdata /* sram data start */
|
||||
data_loop:
|
||||
ldr r0, [r1, #0]
|
||||
str r0, [r3]
|
||||
|
||||
add r1, r1, #4
|
||||
add r3, r3, #4
|
||||
|
||||
cmp r3, r2 /* check if data to clear */
|
||||
blo data_loop /* loop until done */
|
||||
|
||||
/* 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
|
||||
|
||||
/* exception handlers */
|
||||
vector_undef: b vector_undef
|
||||
vector_swi : b vector_swi
|
||||
vector_pabt : b vector_pabt
|
||||
vector_dabt : b vector_dabt
|
||||
vector_resv : b vector_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
|
||||
* 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
|
||||
|
||||
vector_fiq:
|
||||
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]
|
||||
|
||||
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, #I_BIT|F_BIT
|
||||
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
|
||||
517
RT_Thread/libcpu/arm/AT91SAM7X/start_rvds.S
Normal file
517
RT_Thread/libcpu/arm/AT91SAM7X/start_rvds.S
Normal file
@ -0,0 +1,517 @@
|
||||
;/*****************************************************************************/
|
||||
;/* SAM7.S: Startup file for Atmel AT91SAM7 device series */
|
||||
;/*****************************************************************************/
|
||||
;/* <<< Use Configuration Wizard in Context Menu >>> */
|
||||
;/*****************************************************************************/
|
||||
;/* This file is part of the uVision/ARM development tools. */
|
||||
;/* Copyright (c) 2005-2006 Keil Software. All rights reserved. */
|
||||
;/* This software may only be used under the terms of a valid, current, */
|
||||
;/* end user licence from KEIL for a compatible version of KEIL software */
|
||||
;/* development tools. Nothing else gives you the right to use this software. */
|
||||
;/*****************************************************************************/
|
||||
|
||||
|
||||
;/*
|
||||
; * The SAM7.S code is executed after CPU Reset. This file may be
|
||||
; * translated with the following SET symbols. In uVision these SET
|
||||
; * symbols are entered under Options - ASM - Define.
|
||||
; *
|
||||
; * REMAP: when set the startup code remaps exception vectors from
|
||||
; * on-chip RAM to address 0.
|
||||
; *
|
||||
; * RAM_INTVEC: when set the startup code copies exception vectors
|
||||
; * from on-chip Flash to on-chip RAM.
|
||||
; */
|
||||
|
||||
|
||||
; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
|
||||
|
||||
; 2009-12-28 MingBai Bug fix (USR mode stack removed).
|
||||
; 2009-12-29 MingBai Merge svc and irq stack, add abort handler.
|
||||
|
||||
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
|
||||
|
||||
I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled
|
||||
F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled
|
||||
|
||||
|
||||
; Internal Memory Base Addresses
|
||||
FLASH_BASE EQU 0x00100000
|
||||
RAM_BASE EQU 0x00200000
|
||||
|
||||
|
||||
;// <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 0x00000000
|
||||
SVC_Stack_Size EQU 0x00000000
|
||||
ABT_Stack_Size EQU 0x00000000
|
||||
FIQ_Stack_Size EQU 0x00000000
|
||||
IRQ_Stack_Size EQU 0x00000100
|
||||
USR_Stack_Size EQU 0x00000000
|
||||
|
||||
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
|
||||
|
||||
|
||||
; Reset Controller (RSTC) definitions
|
||||
RSTC_BASE EQU 0xFFFFFD00 ; RSTC Base Address
|
||||
RSTC_MR EQU 0x08 ; RSTC_MR Offset
|
||||
|
||||
;/*
|
||||
;// <e> Reset Controller (RSTC)
|
||||
;// <o1.0> URSTEN: User Reset Enable
|
||||
;// <i> Enables NRST Pin to generate Reset
|
||||
;// <o1.8..11> ERSTL: External Reset Length <0-15>
|
||||
;// <i> External Reset Time in 2^(ERSTL+1) Slow Clock Cycles
|
||||
;// </e>
|
||||
;*/
|
||||
RSTC_SETUP EQU 1
|
||||
RSTC_MR_Val EQU 0xA5000401
|
||||
|
||||
|
||||
; Embedded Flash Controller (EFC) definitions
|
||||
EFC_BASE EQU 0xFFFFFF00 ; EFC Base Address
|
||||
EFC0_FMR EQU 0x60 ; EFC0_FMR Offset
|
||||
EFC1_FMR EQU 0x70 ; EFC1_FMR Offset
|
||||
|
||||
;// <e> Embedded Flash Controller 0 (EFC0)
|
||||
;// <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255>
|
||||
;// <i> Number of Master Clock Cycles in 1us
|
||||
;// <o1.8..9> FWS: Flash Wait State
|
||||
;// <0=> Read: 1 cycle / Write: 2 cycles
|
||||
;// <1=> Read: 2 cycle / Write: 3 cycles
|
||||
;// <2=> Read: 3 cycle / Write: 4 cycles
|
||||
;// <3=> Read: 4 cycle / Write: 4 cycles
|
||||
;// </e>
|
||||
EFC0_SETUP EQU 1
|
||||
EFC0_FMR_Val EQU 0x00320100
|
||||
|
||||
;// <e> Embedded Flash Controller 1 (EFC1)
|
||||
;// <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255>
|
||||
;// <i> Number of Master Clock Cycles in 1us
|
||||
;// <o1.8..9> FWS: Flash Wait State
|
||||
;// <0=> Read: 1 cycle / Write: 2 cycles
|
||||
;// <1=> Read: 2 cycle / Write: 3 cycles
|
||||
;// <2=> Read: 3 cycle / Write: 4 cycles
|
||||
;// <3=> Read: 4 cycle / Write: 4 cycles
|
||||
;// </e>
|
||||
EFC1_SETUP EQU 0
|
||||
EFC1_FMR_Val EQU 0x00320100
|
||||
|
||||
|
||||
; Watchdog Timer (WDT) definitions
|
||||
WDT_BASE EQU 0xFFFFFD40 ; WDT Base Address
|
||||
WDT_MR EQU 0x04 ; WDT_MR Offset
|
||||
|
||||
;// <e> Watchdog Timer (WDT)
|
||||
;// <o1.0..11> WDV: Watchdog Counter Value <0-4095>
|
||||
;// <o1.16..27> WDD: Watchdog Delta Value <0-4095>
|
||||
;// <o1.12> WDFIEN: Watchdog Fault Interrupt Enable
|
||||
;// <o1.13> WDRSTEN: Watchdog Reset Enable
|
||||
;// <o1.14> WDRPROC: Watchdog Reset Processor
|
||||
;// <o1.28> WDDBGHLT: Watchdog Debug Halt
|
||||
;// <o1.29> WDIDLEHLT: Watchdog Idle Halt
|
||||
;// <o1.15> WDDIS: Watchdog Disable
|
||||
;// </e>
|
||||
WDT_SETUP EQU 1
|
||||
WDT_MR_Val EQU 0x00008000
|
||||
|
||||
|
||||
; Power Mangement Controller (PMC) definitions
|
||||
PMC_BASE EQU 0xFFFFFC00 ; PMC Base Address
|
||||
PMC_MOR EQU 0x20 ; PMC_MOR Offset
|
||||
PMC_MCFR EQU 0x24 ; PMC_MCFR Offset
|
||||
PMC_PLLR EQU 0x2C ; PMC_PLLR Offset
|
||||
PMC_MCKR EQU 0x30 ; PMC_MCKR Offset
|
||||
PMC_SR EQU 0x68 ; PMC_SR Offset
|
||||
PMC_MOSCEN EQU (1<<0) ; Main Oscillator Enable
|
||||
PMC_OSCBYPASS EQU (1<<1) ; Main Oscillator Bypass
|
||||
PMC_OSCOUNT EQU (0xFF<<8) ; Main OScillator Start-up Time
|
||||
PMC_DIV EQU (0xFF<<0) ; PLL Divider
|
||||
PMC_PLLCOUNT EQU (0x3F<<8) ; PLL Lock Counter
|
||||
PMC_OUT EQU (0x03<<14) ; PLL Clock Frequency Range
|
||||
PMC_MUL EQU (0x7FF<<16) ; PLL Multiplier
|
||||
PMC_USBDIV EQU (0x03<<28) ; USB Clock Divider
|
||||
PMC_CSS EQU (3<<0) ; Clock Source Selection
|
||||
PMC_PRES EQU (7<<2) ; Prescaler Selection
|
||||
PMC_MOSCS EQU (1<<0) ; Main Oscillator Stable
|
||||
PMC_LOCK EQU (1<<2) ; PLL Lock Status
|
||||
PMC_MCKRDY EQU (1<<3) ; Master Clock Status
|
||||
|
||||
;// <e> Power Mangement Controller (PMC)
|
||||
;// <h> Main Oscillator
|
||||
;// <o1.0> MOSCEN: Main Oscillator Enable
|
||||
;// <o1.1> OSCBYPASS: Oscillator Bypass
|
||||
;// <o1.8..15> OSCCOUNT: Main Oscillator Startup Time <0-255>
|
||||
;// </h>
|
||||
;// <h> Phase Locked Loop (PLL)
|
||||
;// <o2.0..7> DIV: PLL Divider <0-255>
|
||||
;// <o2.16..26> MUL: PLL Multiplier <0-2047>
|
||||
;// <i> PLL Output is multiplied by MUL+1
|
||||
;// <o2.14..15> OUT: PLL Clock Frequency Range
|
||||
;// <0=> 80..160MHz <1=> Reserved
|
||||
;// <2=> 150..220MHz <3=> Reserved
|
||||
;// <o2.8..13> PLLCOUNT: PLL Lock Counter <0-63>
|
||||
;// <o2.28..29> USBDIV: USB Clock Divider
|
||||
;// <0=> None <1=> 2 <2=> 4 <3=> Reserved
|
||||
;// </h>
|
||||
;// <o3.0..1> CSS: Clock Source Selection
|
||||
;// <0=> Slow Clock
|
||||
;// <1=> Main Clock
|
||||
;// <2=> Reserved
|
||||
;// <3=> PLL Clock
|
||||
;// <o3.2..4> PRES: Prescaler
|
||||
;// <0=> None
|
||||
;// <1=> Clock / 2 <2=> Clock / 4
|
||||
;// <3=> Clock / 8 <4=> Clock / 16
|
||||
;// <5=> Clock / 32 <6=> Clock / 64
|
||||
;// <7=> Reserved
|
||||
;// </e>
|
||||
PMC_SETUP EQU 1
|
||||
PMC_MOR_Val EQU 0x00000601
|
||||
PMC_PLLR_Val EQU 0x00191C05
|
||||
PMC_MCKR_Val EQU 0x00000007
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Vectors LDR PC,Reset_Addr
|
||||
LDR PC,Undef_Addr
|
||||
LDR PC,SWI_Addr
|
||||
LDR PC,PAbt_Addr
|
||||
LDR PC,DAbt_Addr
|
||||
NOP ; Reserved Vector
|
||||
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 Abort_Handler
|
||||
DAbt_Handler B Abort_Handler
|
||||
FIQ_Handler B FIQ_Handler
|
||||
|
||||
|
||||
; Reset Handler
|
||||
|
||||
EXPORT Reset_Handler
|
||||
Reset_Handler
|
||||
|
||||
|
||||
; Setup RSTC
|
||||
IF RSTC_SETUP != 0
|
||||
LDR R0, =RSTC_BASE
|
||||
LDR R1, =RSTC_MR_Val
|
||||
STR R1, [R0, #RSTC_MR]
|
||||
ENDIF
|
||||
|
||||
|
||||
; Setup EFC0
|
||||
IF EFC0_SETUP != 0
|
||||
LDR R0, =EFC_BASE
|
||||
LDR R1, =EFC0_FMR_Val
|
||||
STR R1, [R0, #EFC0_FMR]
|
||||
ENDIF
|
||||
|
||||
; Setup EFC1
|
||||
IF EFC1_SETUP != 0
|
||||
LDR R0, =EFC_BASE
|
||||
LDR R1, =EFC1_FMR_Val
|
||||
STR R1, [R0, #EFC1_FMR]
|
||||
ENDIF
|
||||
|
||||
; Setup WDT
|
||||
IF WDT_SETUP != 0
|
||||
LDR R0, =WDT_BASE
|
||||
LDR R1, =WDT_MR_Val
|
||||
STR R1, [R0, #WDT_MR]
|
||||
ENDIF
|
||||
|
||||
|
||||
; Setup PMC
|
||||
IF PMC_SETUP != 0
|
||||
LDR R0, =PMC_BASE
|
||||
|
||||
; Setup Main Oscillator
|
||||
LDR R1, =PMC_MOR_Val
|
||||
STR R1, [R0, #PMC_MOR]
|
||||
|
||||
; Wait until Main Oscillator is stablilized
|
||||
IF (PMC_MOR_Val:AND:PMC_MOSCEN) != 0
|
||||
MOSCS_Loop LDR R2, [R0, #PMC_SR]
|
||||
ANDS R2, R2, #PMC_MOSCS
|
||||
BEQ MOSCS_Loop
|
||||
ENDIF
|
||||
|
||||
; Setup the PLL
|
||||
IF (PMC_PLLR_Val:AND:PMC_MUL) != 0
|
||||
LDR R1, =PMC_PLLR_Val
|
||||
STR R1, [R0, #PMC_PLLR]
|
||||
|
||||
; Wait until PLL is stabilized
|
||||
PLL_Loop LDR R2, [R0, #PMC_SR]
|
||||
ANDS R2, R2, #PMC_LOCK
|
||||
BEQ PLL_Loop
|
||||
ENDIF
|
||||
|
||||
; Select Clock
|
||||
IF (PMC_MCKR_Val:AND:PMC_CSS) == 1 ; Main Clock Selected
|
||||
LDR R1, =PMC_MCKR_Val
|
||||
AND R1, #PMC_CSS
|
||||
STR R1, [R0, #PMC_MCKR]
|
||||
WAIT_Rdy1 LDR R2, [R0, #PMC_SR]
|
||||
ANDS R2, R2, #PMC_MCKRDY
|
||||
BEQ WAIT_Rdy1
|
||||
LDR R1, =PMC_MCKR_Val
|
||||
STR R1, [R0, #PMC_MCKR]
|
||||
WAIT_Rdy2 LDR R2, [R0, #PMC_SR]
|
||||
ANDS R2, R2, #PMC_MCKRDY
|
||||
BEQ WAIT_Rdy2
|
||||
ELIF (PMC_MCKR_Val:AND:PMC_CSS) == 3 ; PLL Clock Selected
|
||||
LDR R1, =PMC_MCKR_Val
|
||||
AND R1, #PMC_PRES
|
||||
STR R1, [R0, #PMC_MCKR]
|
||||
WAIT_Rdy1 LDR R2, [R0, #PMC_SR]
|
||||
ANDS R2, R2, #PMC_MCKRDY
|
||||
BEQ WAIT_Rdy1
|
||||
LDR R1, =PMC_MCKR_Val
|
||||
STR R1, [R0, #PMC_MCKR]
|
||||
WAIT_Rdy2 LDR R2, [R0, #PMC_SR]
|
||||
ANDS R2, R2, #PMC_MCKRDY
|
||||
BEQ WAIT_Rdy2
|
||||
ENDIF ; Select Clock
|
||||
ENDIF ; PMC_SETUP
|
||||
|
||||
|
||||
; Copy Exception Vectors to Internal RAM
|
||||
|
||||
IF :DEF:RAM_INTVEC
|
||||
ADR R8, Vectors ; Source
|
||||
LDR R9, =RAM_BASE ; 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
|
||||
ENDIF
|
||||
|
||||
|
||||
; Remap on-chip RAM to address 0
|
||||
|
||||
MC_BASE EQU 0xFFFFFF00 ; MC Base Address
|
||||
MC_RCR EQU 0x00 ; MC_RCR Offset
|
||||
|
||||
IF :DEF:REMAP
|
||||
LDR R0, =MC_BASE
|
||||
MOV R1, #1
|
||||
STR R1, [R0, #MC_RCR] ; Remap
|
||||
ENDIF
|
||||
|
||||
|
||||
; 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
|
||||
IF :DEF:__MICROLIB
|
||||
|
||||
EXPORT __initial_sp
|
||||
|
||||
ELSE
|
||||
|
||||
; No usr mode stack here.
|
||||
;MOV SP, R0
|
||||
;SUB SL, SP, #USR_Stack_Size
|
||||
|
||||
ENDIF
|
||||
|
||||
|
||||
; 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
|
||||
IMPORT rt_hw_trap_abort
|
||||
IMPORT rt_interrupt_nest
|
||||
|
||||
Abort_Handler PROC
|
||||
EXPORT Abort_Handler
|
||||
stmfd sp!, {r0-r12,lr}
|
||||
LDR r0, =rt_interrupt_nest
|
||||
LDR r1, [r0]
|
||||
CMP r1, #0
|
||||
DeadLoop BHI DeadLoop ; Abort happened in irq mode, halt system.
|
||||
bl rt_interrupt_enter
|
||||
bl rt_hw_trap_abort
|
||||
bl rt_interrupt_leave
|
||||
b SWITCH
|
||||
ENDP
|
||||
|
||||
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
|
||||
SWITCH 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|F_Bit|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 + IRQ_Stack_Size)
|
||||
LDR R2, = (Heap_Mem + Heap_Size)
|
||||
LDR R3, = Stack_Mem
|
||||
BX LR
|
||||
ENDIF
|
||||
|
||||
END
|
||||
49
RT_Thread/libcpu/arm/AT91SAM7X/trap.c
Normal file
49
RT_Thread/libcpu/arm/AT91SAM7X/trap.c
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-08-25 Bernard first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
/**
|
||||
* @addtogroup AT91SAM7
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
void rt_hw_trap_irq(void)
|
||||
{
|
||||
int irqno;
|
||||
extern struct rt_irq_desc irq_desc[];
|
||||
|
||||
/* get interrupt number */
|
||||
irqno = AT91C_BASE_AIC->AIC_ISR;
|
||||
|
||||
/* invoke isr with parameters */
|
||||
irq_desc[irqno].handler(irqno, irq_desc[irqno].param);
|
||||
|
||||
/* end of interrupt */
|
||||
AT91C_BASE_AIC->AIC_EOICR = 0;
|
||||
}
|
||||
|
||||
void rt_hw_trap_fiq(void)
|
||||
{
|
||||
rt_kprintf("fast interrupt request\n");
|
||||
}
|
||||
|
||||
extern struct rt_thread* rt_current_thread;
|
||||
void rt_hw_trap_abort(void)
|
||||
{
|
||||
rt_kprintf("Abort occured!!! Thread [%s] suspended.\n",rt_current_thread->parent.name);
|
||||
rt_thread_suspend(rt_current_thread);
|
||||
rt_schedule();
|
||||
|
||||
}
|
||||
/*@}*/
|
||||
Reference in New Issue
Block a user