2020-01-10 10:38:21 +08:00
|
|
|
/*
|
2020-01-15 16:46:19 +08:00
|
|
|
* Copyright (c) 2006-2020, RT-Thread Development Team
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*
|
|
|
|
* Change Logs:
|
2020-01-10 10:38:21 +08:00
|
|
|
* Date Author Notes
|
|
|
|
* 2018-10-06 ZhaoXiaowei the first version
|
|
|
|
*/
|
|
|
|
|
2020-02-26 15:32:44 +08:00
|
|
|
/*
|
|
|
|
*enable gtimer
|
|
|
|
*/
|
|
|
|
.globl rt_hw_gtimer_enable
|
|
|
|
rt_hw_gtimer_enable:
|
2020-02-26 15:43:23 +08:00
|
|
|
MOV X0,#1
|
2020-02-26 15:32:44 +08:00
|
|
|
MSR CNTP_CTL_EL0,X0
|
|
|
|
RET
|
|
|
|
|
|
|
|
/*
|
|
|
|
*set gtimer CNTP_TVAL_EL0 value
|
|
|
|
*/
|
|
|
|
.globl rt_hw_set_gtimer_val
|
|
|
|
rt_hw_set_gtimer_val:
|
|
|
|
MSR CNTP_TVAL_EL0,X0
|
|
|
|
RET
|
|
|
|
|
2020-03-19 18:31:55 +08:00
|
|
|
/*
|
|
|
|
*get gtimer CNTP_TVAL_EL0 value
|
|
|
|
*/
|
|
|
|
.globl rt_hw_get_gtimer_val
|
|
|
|
rt_hw_get_gtimer_val:
|
|
|
|
MRS X0,CNTP_TVAL_EL0
|
|
|
|
RET
|
|
|
|
|
|
|
|
|
|
|
|
.globl rt_hw_get_cntpct_val
|
|
|
|
rt_hw_get_cntpct_val:
|
|
|
|
MRS X0, CNTPCT_EL0
|
|
|
|
RET
|
|
|
|
|
2020-02-26 15:32:44 +08:00
|
|
|
/*
|
|
|
|
*get gtimer frq value
|
|
|
|
*/
|
|
|
|
.globl rt_hw_get_gtimer_frq
|
|
|
|
rt_hw_get_gtimer_frq:
|
|
|
|
MRS X0,CNTFRQ_EL0
|
|
|
|
RET
|
|
|
|
|
2020-01-10 10:38:21 +08:00
|
|
|
.macro SAVE_CONTEXT
|
|
|
|
|
|
|
|
/* Switch to use the EL0 stack pointer. */
|
|
|
|
MSR SPSEL, #0
|
|
|
|
|
|
|
|
/* Save the entire context. */
|
|
|
|
STP X0, X1, [SP, #-0x10]!
|
|
|
|
STP X2, X3, [SP, #-0x10]!
|
|
|
|
STP X4, X5, [SP, #-0x10]!
|
|
|
|
STP X6, X7, [SP, #-0x10]!
|
|
|
|
STP X8, X9, [SP, #-0x10]!
|
|
|
|
STP X10, X11, [SP, #-0x10]!
|
|
|
|
STP X12, X13, [SP, #-0x10]!
|
|
|
|
STP X14, X15, [SP, #-0x10]!
|
|
|
|
STP X16, X17, [SP, #-0x10]!
|
|
|
|
STP X18, X19, [SP, #-0x10]!
|
|
|
|
STP X20, X21, [SP, #-0x10]!
|
|
|
|
STP X22, X23, [SP, #-0x10]!
|
|
|
|
STP X24, X25, [SP, #-0x10]!
|
|
|
|
STP X26, X27, [SP, #-0x10]!
|
|
|
|
STP X28, X29, [SP, #-0x10]!
|
|
|
|
STP X30, XZR, [SP, #-0x10]!
|
|
|
|
|
|
|
|
MRS X0, CurrentEL
|
|
|
|
CMP X0, 0xc
|
|
|
|
B.EQ 3f
|
|
|
|
CMP X0, 0x8
|
|
|
|
B.EQ 2f
|
|
|
|
CMP X0, 0x4
|
|
|
|
B.EQ 1f
|
|
|
|
B .
|
|
|
|
3:
|
|
|
|
MRS X3, SPSR_EL3
|
|
|
|
/* Save the ELR. */
|
|
|
|
MRS X2, ELR_EL3
|
|
|
|
B 0f
|
|
|
|
2:
|
|
|
|
MRS X3, SPSR_EL2
|
|
|
|
/* Save the ELR. */
|
|
|
|
MRS X2, ELR_EL2
|
|
|
|
B 0f
|
|
|
|
1:
|
|
|
|
MRS X3, SPSR_EL1
|
|
|
|
MRS X2, ELR_EL1
|
|
|
|
B 0f
|
|
|
|
0:
|
|
|
|
|
|
|
|
STP X2, X3, [SP, #-0x10]!
|
|
|
|
|
|
|
|
MOV X0, SP /* Move SP into X0 for saving. */
|
|
|
|
|
|
|
|
/* Switch to use the ELx stack pointer. */
|
|
|
|
MSR SPSEL, #1
|
|
|
|
|
|
|
|
.endm
|
|
|
|
|
|
|
|
.macro SAVE_CONTEXT_T
|
|
|
|
|
|
|
|
/* Switch to use the EL0 stack pointer. */
|
|
|
|
MSR SPSEL, #0
|
|
|
|
|
|
|
|
/* Save the entire context. */
|
|
|
|
STP X0, X1, [SP, #-0x10]!
|
|
|
|
STP X2, X3, [SP, #-0x10]!
|
|
|
|
STP X4, X5, [SP, #-0x10]!
|
|
|
|
STP X6, X7, [SP, #-0x10]!
|
|
|
|
STP X8, X9, [SP, #-0x10]!
|
|
|
|
STP X10, X11, [SP, #-0x10]!
|
|
|
|
STP X12, X13, [SP, #-0x10]!
|
|
|
|
STP X14, X15, [SP, #-0x10]!
|
|
|
|
STP X16, X17, [SP, #-0x10]!
|
|
|
|
STP X18, X19, [SP, #-0x10]!
|
|
|
|
STP X20, X21, [SP, #-0x10]!
|
|
|
|
STP X22, X23, [SP, #-0x10]!
|
|
|
|
STP X24, X25, [SP, #-0x10]!
|
|
|
|
STP X26, X27, [SP, #-0x10]!
|
|
|
|
STP X28, X29, [SP, #-0x10]!
|
|
|
|
STP X30, XZR, [SP, #-0x10]!
|
|
|
|
|
|
|
|
MRS X0, CurrentEL
|
|
|
|
CMP X0, 0xc
|
|
|
|
B.EQ 3f
|
|
|
|
CMP X0, 0x8
|
|
|
|
B.EQ 2f
|
|
|
|
CMP X0, 0x4
|
|
|
|
B.EQ 1f
|
|
|
|
B .
|
|
|
|
3:
|
|
|
|
MRS X3, SPSR_EL3
|
|
|
|
MOV X2, X30
|
|
|
|
B 0f
|
|
|
|
2:
|
|
|
|
MRS X3, SPSR_EL2
|
|
|
|
MOV X2, X30
|
|
|
|
B 0f
|
|
|
|
1:
|
|
|
|
MRS X3, SPSR_EL1
|
|
|
|
MOV X2, X30
|
|
|
|
B 0f
|
|
|
|
0:
|
|
|
|
|
|
|
|
STP X2, X3, [SP, #-0x10]!
|
|
|
|
|
|
|
|
MOV X0, SP /* Move SP into X0 for saving. */
|
|
|
|
|
|
|
|
/* Switch to use the ELx stack pointer. */
|
|
|
|
MSR SPSEL, #1
|
|
|
|
|
|
|
|
.endm
|
|
|
|
|
|
|
|
.macro RESTORE_CONTEXT
|
|
|
|
|
|
|
|
/* Switch to use the EL0 stack pointer. */
|
|
|
|
MSR SPSEL, #0
|
|
|
|
|
|
|
|
/* Set the SP to point to the stack of the task being restored. */
|
|
|
|
MOV SP, X0
|
|
|
|
|
|
|
|
LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */
|
|
|
|
|
|
|
|
MRS X0, CurrentEL
|
|
|
|
CMP X0, 0xc
|
|
|
|
B.EQ 3f
|
|
|
|
CMP X0, 0x8
|
|
|
|
B.EQ 2f
|
|
|
|
CMP X0, 0x4
|
|
|
|
B.EQ 1f
|
|
|
|
B .
|
|
|
|
3:
|
|
|
|
MSR SPSR_EL3, X3
|
|
|
|
MSR ELR_EL3, X2
|
|
|
|
B 0f
|
|
|
|
2:
|
|
|
|
MSR SPSR_EL2, X3
|
|
|
|
MSR ELR_EL2, X2
|
|
|
|
B 0f
|
|
|
|
1:
|
|
|
|
MSR SPSR_EL1, X3
|
|
|
|
MSR ELR_EL1, X2
|
|
|
|
B 0f
|
|
|
|
0:
|
|
|
|
|
|
|
|
LDP X30, XZR, [SP], #0x10
|
|
|
|
LDP X28, X29, [SP], #0x10
|
|
|
|
LDP X26, X27, [SP], #0x10
|
|
|
|
LDP X24, X25, [SP], #0x10
|
|
|
|
LDP X22, X23, [SP], #0x10
|
|
|
|
LDP X20, X21, [SP], #0x10
|
|
|
|
LDP X18, X19, [SP], #0x10
|
|
|
|
LDP X16, X17, [SP], #0x10
|
|
|
|
LDP X14, X15, [SP], #0x10
|
|
|
|
LDP X12, X13, [SP], #0x10
|
|
|
|
LDP X10, X11, [SP], #0x10
|
|
|
|
LDP X8, X9, [SP], #0x10
|
|
|
|
LDP X6, X7, [SP], #0x10
|
|
|
|
LDP X4, X5, [SP], #0x10
|
|
|
|
LDP X2, X3, [SP], #0x10
|
|
|
|
LDP X0, X1, [SP], #0x10
|
|
|
|
|
|
|
|
/* Switch to use the ELx stack pointer. _RB_ Might not be required. */
|
|
|
|
MSR SPSEL, #1
|
|
|
|
|
|
|
|
ERET
|
|
|
|
|
|
|
|
.endm
|
|
|
|
|
|
|
|
.text
|
|
|
|
/*
|
|
|
|
* rt_base_t rt_hw_interrupt_disable();
|
|
|
|
*/
|
|
|
|
.globl rt_hw_interrupt_disable
|
|
|
|
rt_hw_interrupt_disable:
|
|
|
|
MRS X0, DAIF
|
|
|
|
MSR DAIFSet, #3
|
|
|
|
DSB SY
|
|
|
|
RET
|
|
|
|
|
|
|
|
/*
|
|
|
|
* void rt_hw_interrupt_enable(rt_base_t level);
|
|
|
|
*/
|
|
|
|
.globl rt_hw_interrupt_enable
|
|
|
|
rt_hw_interrupt_enable:
|
|
|
|
DSB SY
|
|
|
|
MOV X1, #0xC0
|
|
|
|
ANDS X0, X0, X1
|
|
|
|
B.NE rt_hw_interrupt_enable_exit
|
|
|
|
MSR DAIFClr, #3
|
|
|
|
rt_hw_interrupt_enable_exit:
|
|
|
|
RET
|
|
|
|
|
|
|
|
/*
|
|
|
|
* void rt_hw_context_switch_to(rt_ubase_t to);
|
|
|
|
* r0 --> to
|
|
|
|
*/
|
|
|
|
.globl rt_hw_context_switch_to
|
|
|
|
rt_hw_context_switch_to:
|
|
|
|
LDR X0, [X0]
|
|
|
|
RESTORE_CONTEXT
|
|
|
|
|
|
|
|
.text
|
|
|
|
/*
|
|
|
|
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
|
|
|
|
* r0 --> from
|
|
|
|
* r1 --> to
|
|
|
|
*/
|
|
|
|
.globl rt_hw_context_switch
|
|
|
|
rt_hw_context_switch:
|
|
|
|
|
|
|
|
MOV X8,X0
|
|
|
|
MOV X9,X1
|
|
|
|
|
|
|
|
SAVE_CONTEXT_T
|
|
|
|
|
|
|
|
STR X0, [X8] // store sp in preempted tasks TCB
|
|
|
|
LDR X0, [X9] // get new task stack pointer
|
|
|
|
|
|
|
|
RESTORE_CONTEXT
|
|
|
|
|
|
|
|
/*
|
|
|
|
* void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t 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:
|
|
|
|
ADR X2, rt_thread_switch_interrupt_flag
|
|
|
|
LDR X3, [X2]
|
|
|
|
CMP X3, #1
|
|
|
|
B.EQ _reswitch
|
|
|
|
ADR X4, rt_interrupt_from_thread // set rt_interrupt_from_thread
|
|
|
|
MOV X3, #1 // set rt_thread_switch_interrupt_flag to 1
|
|
|
|
STR X0, [X4]
|
|
|
|
STR X3, [X2]
|
|
|
|
_reswitch:
|
|
|
|
ADR X2, rt_interrupt_to_thread // set rt_interrupt_to_thread
|
|
|
|
STR X1, [X2]
|
|
|
|
RET
|
|
|
|
|
|
|
|
.text
|
|
|
|
|
|
|
|
// -- Exception handlers ----------------------------------
|
|
|
|
|
|
|
|
.align 8
|
|
|
|
.globl vector_fiq
|
|
|
|
vector_fiq:
|
|
|
|
SAVE_CONTEXT
|
|
|
|
STP X0, X1, [SP, #-0x10]!
|
|
|
|
BL rt_hw_trap_fiq
|
|
|
|
LDP X0, X1, [SP], #0x10
|
|
|
|
RESTORE_CONTEXT
|
|
|
|
|
|
|
|
.globl rt_interrupt_enter
|
|
|
|
.globl rt_interrupt_leave
|
|
|
|
.globl rt_thread_switch_interrupt_flag
|
|
|
|
.globl rt_interrupt_from_thread
|
|
|
|
.globl rt_interrupt_to_thread
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
|
|
|
.align 8
|
|
|
|
.globl vector_irq
|
|
|
|
vector_irq:
|
|
|
|
SAVE_CONTEXT
|
|
|
|
STP X0, X1, [SP, #-0x10]!
|
|
|
|
|
|
|
|
BL rt_interrupt_enter
|
|
|
|
BL rt_hw_trap_irq
|
|
|
|
BL rt_interrupt_leave
|
|
|
|
|
|
|
|
LDP X0, X1, [SP], #0x10
|
|
|
|
|
|
|
|
// if rt_thread_switch_interrupt_flag set, jump to
|
|
|
|
// rt_hw_context_switch_interrupt_do and don't return
|
|
|
|
ADR X1, rt_thread_switch_interrupt_flag
|
|
|
|
LDR X2, [X1]
|
|
|
|
CMP X2, #1
|
|
|
|
B.NE vector_irq_exit
|
|
|
|
|
|
|
|
MOV X2, #0 // clear flag
|
|
|
|
STR X2, [X1]
|
|
|
|
|
|
|
|
ADR X3, rt_interrupt_from_thread
|
|
|
|
LDR X4, [X3]
|
|
|
|
STR x0, [X4] // store sp in preempted tasks's TCB
|
|
|
|
|
|
|
|
ADR x3, rt_interrupt_to_thread
|
|
|
|
LDR X4, [X3]
|
|
|
|
LDR x0, [X4] // get new task's stack pointer
|
|
|
|
|
|
|
|
vector_irq_exit:
|
|
|
|
RESTORE_CONTEXT
|
|
|
|
|
|
|
|
// -------------------------------------------------
|
|
|
|
|
|
|
|
.align 8
|
|
|
|
.globl vector_error
|
|
|
|
vector_error:
|
|
|
|
SAVE_CONTEXT
|
|
|
|
BL rt_hw_trap_error
|
|
|
|
B .
|