first
This commit is contained in:
1197
rt-thread/libcpu/arm/lpc24xx/LPC24xx.h
Normal file
1197
rt-thread/libcpu/arm/lpc24xx/LPC24xx.h
Normal file
File diff suppressed because it is too large
Load Diff
23
rt-thread/libcpu/arm/lpc24xx/SConscript
Normal file
23
rt-thread/libcpu/arm/lpc24xx/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/lpc24xx/context_gcc.S
Normal file
95
rt-thread/libcpu/arm/lpc24xx/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
|
||||
* 2008-12-11 XuXinming first version
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \addtogroup LPC2478
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
#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
|
107
rt-thread/libcpu/arm/lpc24xx/context_rvds.S
Normal file
107
rt-thread/libcpu/arm/lpc24xx/context_rvds.S
Normal file
@@ -0,0 +1,107 @@
|
||||
;/*
|
||||
; * 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
|
||||
; * 2011-07-22 Bernard added thumb mode porting
|
||||
; */
|
||||
|
||||
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
|
||||
TST lr, #0x01
|
||||
BEQ _ARM_MODE
|
||||
ORR r4, r4, #0x20 ; it's thumb code
|
||||
|
||||
_ARM_MODE
|
||||
STMFD sp!, {r4} ; push cpsr
|
||||
|
||||
STR sp, [r0] ; store sp in preempted tasks TCB
|
||||
LDR sp, [r1] ; get new task stack pointer
|
||||
|
||||
LDMFD sp!, {r4} ; pop new task cpsr to spsr
|
||||
MSR spsr_cxsf, r4
|
||||
BIC r4, r4, #0x20 ; must be ARM mode
|
||||
MSR cpsr_cxsf, r4
|
||||
|
||||
LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc, copy spsr to cpsr
|
||||
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 cpsr to spsr
|
||||
MSR spsr_cxsf, r4
|
||||
BIC r4, r4, #0x20 ; must be ARM mode
|
||||
MSR cpsr_cxsf, r4
|
||||
|
||||
LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc, copy spsr to cpsr
|
||||
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
|
19
rt-thread/libcpu/arm/lpc24xx/cpu.c
Normal file
19
rt-thread/libcpu/arm/lpc24xx/cpu.c
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2008-12-11 XuXinming first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "LPC24xx.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LPC2478
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/*@}*/
|
103
rt-thread/libcpu/arm/lpc24xx/interrupt.c
Normal file
103
rt-thread/libcpu/arm/lpc24xx/interrupt.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2008-12-11 XuXinming first version
|
||||
* 2013-03-29 aozima Modify the interrupt interface implementations.
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include "LPC24xx.h"
|
||||
|
||||
#define MAX_HANDLERS 32
|
||||
|
||||
/* exception and interrupt handler table */
|
||||
struct rt_irq_desc irq_desc[MAX_HANDLERS];
|
||||
|
||||
extern rt_uint32_t rt_interrupt_nest;
|
||||
|
||||
/* exception and interrupt handler table */
|
||||
rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
|
||||
rt_uint32_t rt_thread_switch_interrupt_flag;
|
||||
|
||||
/**
|
||||
* @addtogroup LPC2478
|
||||
*/
|
||||
/*@{*/
|
||||
void rt_hw_interrupt_handler(int vector, void *param)
|
||||
{
|
||||
rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
|
||||
}
|
||||
|
||||
void rt_hw_interrupt_init(void)
|
||||
{
|
||||
register int i;
|
||||
|
||||
rt_uint32_t *vect_addr, *vect_cntl;
|
||||
|
||||
/* initialize VIC*/
|
||||
VICIntEnClr = 0xffffffff;
|
||||
VICVectAddr = 0;
|
||||
VICIntSelect = 0;
|
||||
|
||||
/* init exceptions table */
|
||||
rt_memset(irq_desc, 0x00, sizeof(irq_desc));
|
||||
for(i=0; i < MAX_HANDLERS; i++)
|
||||
{
|
||||
irq_desc[i].handler = rt_hw_interrupt_handler;
|
||||
|
||||
vect_addr = (rt_uint32_t *)(VIC_BASE_ADDR + 0x100 + i*4);
|
||||
vect_cntl = (rt_uint32_t *)(VIC_BASE_ADDR + 0x200 + i*4);
|
||||
*vect_addr = (rt_uint32_t)&irq_desc[i];
|
||||
*vect_cntl = 0xF;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
void rt_hw_interrupt_mask(int vector)
|
||||
{
|
||||
VICIntEnClr = (1 << vector);
|
||||
}
|
||||
|
||||
void rt_hw_interrupt_umask(int vector)
|
||||
{
|
||||
VICIntEnable = (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 = handler;
|
||||
irq_desc[vector].param = param;
|
||||
}
|
||||
}
|
||||
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
/*@}*/
|
63
rt-thread/libcpu/arm/lpc24xx/stack.c
Normal file
63
rt-thread/libcpu/arm/lpc24xx/stack.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2008-12-11 XuXinming first version
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
#include "LPC24xx.h"
|
||||
|
||||
/**
|
||||
* @addtogroup LPC2478
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
||||
/* cpsr */
|
||||
if ((rt_uint32_t)tentry & 0x01)
|
||||
*(--stk) = SVCMODE | 0x20; /* thumb mode */
|
||||
else
|
||||
*(--stk) = SVCMODE; /* arm mode */
|
||||
|
||||
/* return task's current stack address */
|
||||
return (rt_uint8_t *)stk;
|
||||
}
|
||||
|
||||
/*@}*/
|
282
rt-thread/libcpu/arm/lpc24xx/start_gcc.S
Normal file
282
rt-thread/libcpu/arm/lpc24xx/start_gcc.S
Normal file
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2008-12-11 XuXinming first version
|
||||
* 2011-03-17 Bernard update to 0.4.x
|
||||
*/
|
||||
|
||||
#define WDMOD (0xE0000000 + 0x00)
|
||||
#define VICIntEnClr (0xFFFFF000 + 0x014)
|
||||
#define VICVectAddr (0xFFFFF000 + 0xF00)
|
||||
#define VICIntSelect (0xFFFFF000 + 0x00C)
|
||||
#define PLLCFG (0xE01FC000 + 0x084)
|
||||
#define PLLCON (0xE01FC000 + 0x080)
|
||||
#define PLLFEED (0xE01FC000 + 0x08C)
|
||||
#define PLLSTAT (0xE01FC000 + 0x088)
|
||||
#define CCLKCFG (0xE01FC000 + 0x104)
|
||||
#define MEMMAP (0xE01FC000 + 0x040)
|
||||
#define SCS (0xE01FC000 + 0x1A0)
|
||||
#define CLKSRCSEL (0xE01FC000 + 0x10C)
|
||||
#define MAMCR (0xE01FC000 + 0x000)
|
||||
#define MAMTIM (0xE01FC000 + 0x004)
|
||||
|
||||
/* stack memory */
|
||||
.section .bss.noinit
|
||||
.equ IRQ_STACK_SIZE, 0x00000200
|
||||
.equ FIQ_STACK_SIZE, 0x00000100
|
||||
.equ UDF_STACK_SIZE, 0x00000004
|
||||
.equ ABT_STACK_SIZE, 0x00000004
|
||||
.equ SVC_STACK_SIZE, 0x00000200
|
||||
|
||||
.space IRQ_STACK_SIZE
|
||||
IRQ_STACK:
|
||||
|
||||
.space FIQ_STACK_SIZE
|
||||
FIQ_STACK:
|
||||
|
||||
.space UDF_STACK_SIZE
|
||||
UDF_STACK:
|
||||
|
||||
.space ABT_STACK_SIZE
|
||||
ABT_STACK:
|
||||
|
||||
.space SVC_STACK_SIZE
|
||||
SVC_STACK:
|
||||
|
||||
.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
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
.text
|
||||
.code 32
|
||||
|
||||
/* the system entry */
|
||||
reset:
|
||||
/* enter svc mode */
|
||||
msr cpsr_c, #SVCMODE|NOINT
|
||||
|
||||
/*watch dog disable */
|
||||
ldr r0,=WDMOD
|
||||
ldr r1,=0x0
|
||||
str r1,[r0]
|
||||
|
||||
/* all interrupt disable */
|
||||
ldr r0,=VICIntEnClr
|
||||
ldr r1,=0xffffffff
|
||||
str r1,[r0]
|
||||
|
||||
ldr r1, =VICVectAddr
|
||||
ldr r0, =0x00
|
||||
str r0, [r1]
|
||||
|
||||
ldr r1, =VICIntSelect
|
||||
ldr r0, =0x00
|
||||
str r0, [r1]
|
||||
|
||||
/* setup stack */
|
||||
bl stack_setup
|
||||
|
||||
/* 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
|
||||
|
||||
.equ USERMODE, 0x10
|
||||
.equ FIQMODE, 0x11
|
||||
.equ IRQMODE, 0x12
|
||||
.equ SVCMODE, 0x13
|
||||
.equ ABORTMODE, 0x17
|
||||
.equ UNDEFMODE, 0x1b
|
||||
.equ MODEMASK, 0x1f
|
||||
.equ NOINT, 0xc0
|
||||
|
||||
/* exception handlers */
|
||||
vector_undef: bl rt_hw_trap_udef
|
||||
vector_swi: bl rt_hw_trap_swi
|
||||
vector_pabt: bl rt_hw_trap_pabt
|
||||
vector_dabt: bl rt_hw_trap_dabt
|
||||
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, =UDF_STACK
|
||||
|
||||
orr r1,r0,#ABORTMODE|NOINT
|
||||
msr cpsr_cxsf,r1 /* abort mode */
|
||||
ldr sp, =ABT_STACK
|
||||
|
||||
orr r1,r0,#IRQMODE|NOINT
|
||||
msr cpsr_cxsf,r1 /* IRQ mode */
|
||||
ldr sp, =IRQ_STACK
|
||||
|
||||
orr r1,r0,#FIQMODE|NOINT
|
||||
msr cpsr_cxsf,r1 /* FIQ mode */
|
||||
ldr sp, =FIQ_STACK
|
||||
|
||||
bic r0,r0,#MODEMASK
|
||||
orr r1,r0,#SVCMODE|NOINT
|
||||
msr cpsr_cxsf,r1 /* SVC mode */
|
||||
ldr sp, =SVC_STACK
|
||||
|
||||
/* USER mode is not initialized. */
|
||||
mov pc,lr /* The LR register may be not valid for the mode changes.*/
|
1641
rt-thread/libcpu/arm/lpc24xx/start_rvds.S
Normal file
1641
rt-thread/libcpu/arm/lpc24xx/start_rvds.S
Normal file
File diff suppressed because it is too large
Load Diff
143
rt-thread/libcpu/arm/lpc24xx/trap.c
Normal file
143
rt-thread/libcpu/arm/lpc24xx/trap.c
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2008-12-11 XuXinming first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
|
||||
#include "LPC24xx.h"
|
||||
|
||||
//#define BSP_INT_DEBUG
|
||||
|
||||
/**
|
||||
* @addtogroup LPC2478
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/**
|
||||
* this function will show registers of CPU
|
||||
*
|
||||
* @param regs the registers point
|
||||
*/
|
||||
void rt_hw_show_register (struct rt_hw_register *regs)
|
||||
{
|
||||
rt_kprintf("Execption:\n");
|
||||
rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3);
|
||||
rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7);
|
||||
rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10);
|
||||
rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip);
|
||||
rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc);
|
||||
rt_kprintf("cpsr:0x%08x\n", regs->cpsr);
|
||||
}
|
||||
|
||||
/**
|
||||
* When ARM7TDMI comes across an instruction which it cannot handle,
|
||||
* it takes the undefined instruction trap.
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_udef(struct rt_hw_register *regs)
|
||||
{
|
||||
rt_kprintf("undefined instruction\n");
|
||||
rt_hw_show_register(regs);
|
||||
if (rt_thread_self() != RT_NULL)
|
||||
rt_kprintf("Current Thread: %s\n", rt_thread_self()->parent.name);
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* The software interrupt instruction (SWI) is used for entering
|
||||
* Supervisor mode, usually to request a particular supervisor
|
||||
* function.
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_swi(struct rt_hw_register *regs)
|
||||
{
|
||||
rt_kprintf("software interrupt\n");
|
||||
rt_hw_show_register(regs);
|
||||
if (rt_thread_self() != RT_NULL)
|
||||
rt_kprintf("Current Thread: %s\n", rt_thread_self()->parent.name);
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* An abort indicates that the current memory access cannot be completed,
|
||||
* which occurs during an instruction prefetch.
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_pabt(struct rt_hw_register *regs)
|
||||
{
|
||||
rt_kprintf("prefetch abort\n");
|
||||
rt_hw_show_register(regs);
|
||||
if (rt_thread_self() != RT_NULL)
|
||||
rt_kprintf("Current Thread: %s\n", rt_thread_self()->parent.name);
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* An abort indicates that the current memory access cannot be completed,
|
||||
* which occurs during a data access.
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_dabt(struct rt_hw_register *regs)
|
||||
{
|
||||
rt_kprintf("Data Abort ");
|
||||
rt_hw_show_register(regs);
|
||||
if (rt_thread_self() != RT_NULL)
|
||||
rt_kprintf("Current Thread: %s\n", rt_thread_self()->parent.name);
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Normally, system will never reach here
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_resv(struct rt_hw_register *regs)
|
||||
{
|
||||
rt_kprintf("not used\n");
|
||||
rt_hw_show_register(regs);
|
||||
if (rt_thread_self() != RT_NULL)
|
||||
rt_kprintf("Current Thread: %s\n", rt_thread_self()->parent.name);
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
extern rt_isr_handler_t isr_table[];
|
||||
void rt_hw_trap_irq(void)
|
||||
{
|
||||
int irqno;
|
||||
struct rt_irq_desc* irq;
|
||||
extern struct rt_irq_desc irq_desc[];
|
||||
|
||||
irq = (struct rt_irq_desc*) VICVectAddr;
|
||||
irqno = ((rt_uint32_t) irq - (rt_uint32_t) &irq_desc[0])/sizeof(struct rt_irq_desc);
|
||||
|
||||
/* invoke isr */
|
||||
irq->handler(irqno, irq->param);
|
||||
}
|
||||
|
||||
void rt_hw_trap_fiq(void)
|
||||
{
|
||||
rt_kprintf("fast interrupt request\n");
|
||||
}
|
||||
|
||||
/*@}*/
|
Reference in New Issue
Block a user