📄 sysalib.s
字号:
/* sysALib.s - Atmel AT91M55800A project:H6K */
/*
modification history
--------------------
12.23.2004 written.
*/
/*
DESCRIPTION
This module contains system-dependent routines written in assembly
language. It contains the entry code, sysInit(), for VxWorks images
that start running from RAM, such as 'vxWorks'. These images are
loaded into memory by some external program (e.g., a boot ROM) and then
started. The routine sysInit() must come first in the text segment.
Its job is to perform the minimal setup needed to call the generic C
routine usrInit().
sysInit() masks interrupts in the processor and the interrupt
controller and sets the initial stack pointer. Other hardware and
device initialisation is performed later in the sysHwInit routine in
sysLib.c.
NOTE
The routines in this module don't use the "C" frame pointer %r11@ ! or
establish a stack frame.
SEE ALSO:
.I "ARM Architecture Reference Manual,"
.I "ARM 7TDMI Data Sheet,"
.I "Atmel AT91M40400 16/32-Bit Microcontroller, Data Sheet,"
.I "Atmel AT91EB01 Evaluation Board, User Guide."
*/
#define _ASMLANGUAGE
#include "vxWorks.h"
#if ((CPU == ARM7TDMI) || (CPU == ARM7TDMI_T))
#include "arch/arm/arm.h" /* included by default on new architectures */
#endif
#include "regs.h"
#include "sysLib.h"
#include "config.h"
/* internals */
.globl _sysInit /* start of system code */
.globl _sysIntStackSplit /* routine to split interrupt stack */
/* externals */
.extern _usrInit /* system initialization routine */
.extern _vxSvcIntStackBase /* base of SVC-mode interrupt stack */
.extern _vxSvcIntStackEnd /* end of SVC-mode interrupt stack */
.extern _vxIrqIntStackBase /* base of IRQ-mode interrupt stack */
.extern _vxIrqIntStackEnd /* end of IRQ-mode interrupt stack */
.text
.balign 4
/*******************************************************************************
*
* sysInit - start after boot
*
* This routine is the system start-up entry point for VxWorks in RAM, the
* first code executed after booting. It disables interrupts, sets up
* the stack, and jumps to the C routine usrInit() in usrConfig.c.
*
* The initial stack is set to grow down from the address of sysInit(). This
* stack is used only by usrInit() and is never used again. Memory for the
* stack must be accounted for when determining the system load address.
*
* NOTE: This routine should not be called by the user.
*
* RETURNS: N/A
* sysInit () /@ THIS IS NOT A CALLABLE ROUTINE @/
*/
_ARM_FUNCTION(_sysInit)
/* disable interrupts and force SVC32 mode, just like reset */
MRS r1, cpsr
BIC r1, r1, #MASK_MODE
ORR r1, r1, #MODE_SVC32 | I_BIT | F_BIT
MSR cpsr, r1
/* disable individual interrupts in the interrupt controller */
LDR r2, =AT91_AIC_BASE /* R2-> interrupt controller */
MVN r1, #0 /* R1 = FFFFFFFF */
STR r1, [r2, #AT91_AIC_IDCR - AT91_AIC_BASE] /* IRQs & FIQ */
/* clear interrupts as well */
STR r1, [r2, #AT91_AIC_ICCR - AT91_AIC_BASE] /* IRQs & FIQ */
/*
* Perform 8 End of Interrupt Commands as well, to ensure that
* no interrupt is stacked, leaving the hardware stack in the
* interrupt controller unbalanced.
*/
MOV r1, #8
1:
STR r1, [r2, #AT91_AIC_EOICR - AT91_AIC_BASE]
SUBS r1, r1, #1
BPL 1b
/*
* Initialise stack pointer: set it so stack grows down.
*/
MOV sp, #(AT91_ON_CHIP_RAM_BASE_ADRS+AT91_ON_CHIP_RAM_BANK_SIZE)
/* now call usrInit */
MOV fp, #0 /* initialise frame pointer */
MOV r0, #BOOT_WARM_AUTOBOOT /* pass startType */
#if (ARM_THUMB)
LDR r12, L$_usrInit
BX r12
#else
B _usrInit
#endif /* (ARM_THUMB) */
/*******************************************************************************
*
* sysIntStackSplit - split interrupt stack and set interrupt stack pointers
*
* This routine is called, via a function pointer, during kernel
* initialisation. It splits the allocated interrupt stack into IRQ and
* SVC-mode stacks and sets the processor's IRQ stack pointer. Note that
* the pointer passed points to the bottom of the stack allocated i.e.
* highest address+1.
*
* IRQ stack needs 6 words per nested interrupt;
* SVC-mode will need a good deal more for the C interrupt handlers.
* For now, use ratio 1:7 with any excess allocated to the SVC-mode stack
* at the lowest address.
*
* Note that FIQ is not handled by VxWorks so no stack is allocated for it.
*
* The stacks and the variables that describe them look like this.
* .CS
*
* - HIGH MEMORY -
* ------------------------ <--- vxIrqIntStackBase (r0 on entry)
* | |
* | IRQ-mode |
* | interrupt stack |
* | |
* ------------------------ <--{ vxIrqIntStackEnd
* | | { vxSvcIntStackBase
* | SVC-mode |
* | interrupt stack |
* | |
* ------------------------ <--- vxSvcIntStackEnd
* - LOW MEMORY -
* .CE
*
* NOTE: This routine should not be called by the user.
* void sysIntStackSplit
* (
* char *pBotStack /@ pointer to bottom of interrupt stack @/
* long size /@ size of stack @/
* )
*/
_ARM_FUNCTION_CALLED_FROM_C(_sysIntStackSplit)
/*
* r0 = base of space allocated for stacks (i.e. highest address)
* r1 = size of space
*/
SUB r2, r0, r1 /* r2->lowest usable address */
LDR r3, L$_vxSvcIntStackEnd
STR r2, [r3] /* == end of SVC-mode stack */
SUB r2, r0, r1, ASR #3 /* leave 1/8 for IRQ */
LDR r3, L$_vxSvcIntStackBase
STR r2, [r3]
/* now allocate IRQ stack, setting irq_sp */
LDR r3, L$_vxIrqIntStackEnd
STR r2, [r3]
LDR r3, L$_vxIrqIntStackBase
STR r0, [r3]
MRS r2, cpsr
BIC r3, r2, #MASK_MODE
ORR r3, r3, #MODE_IRQ32 | I_BIT /* set irq_sp */
MSR cpsr, r3
MOV sp, r0
/* switch back to original mode and return */
MSR cpsr, r2
#if (ARM_THUMB)
BX lr
#else
MOV pc, lr
#endif /* (ARM_THUMB) */
/******************************************************************************/
/*
* PC-relative-addressable pointers - note "_" after "$" to stop
* preprocessor performing substitution.
*/
.balign 4
L$_vxSvcIntStackBase:
.long _vxSvcIntStackBase
L$_vxSvcIntStackEnd:
.long _vxSvcIntStackEnd
L$_vxIrqIntStackBase:
.long _vxIrqIntStackBase
L$_vxIrqIntStackEnd:
.long _vxIrqIntStackEnd
#if (ARM_THUMB)
L$_usrInit:
.long _usrInit
#endif /* (ARM_THUMB) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -