summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
authorRbb666 <[email protected]>2024-04-11 08:47:53 +0800
committerMeco Man <[email protected]>2024-04-16 22:49:51 -0400
commit0afc0678949d732d7ece2ac15ac541cd88ac855b (patch)
tree6f4d77ad26af1e87cdc3a9f78f032cfdd63798b5 /libcpu
parent6fc3a0864d8f8713be2ee245058edac9298e30de (diff)
[bsp][renesas]Add cortex-r52 rzt2m adaptation
Diffstat (limited to 'libcpu')
-rw-r--r--libcpu/Kconfig8
-rw-r--r--libcpu/arm/cortex-r52/SConscript23
-rw-r--r--libcpu/arm/cortex-r52/armv8.h80
-rw-r--r--libcpu/arm/cortex-r52/backtrace.c545
-rw-r--r--libcpu/arm/cortex-r52/backtrace.h83
-rw-r--r--libcpu/arm/cortex-r52/context_ccs.asm260
-rw-r--r--libcpu/arm/cortex-r52/context_gcc.S252
-rw-r--r--libcpu/arm/cortex-r52/context_iar.S260
-rw-r--r--libcpu/arm/cortex-r52/cp15.h21
-rw-r--r--libcpu/arm/cortex-r52/cp15_gcc.S167
-rw-r--r--libcpu/arm/cortex-r52/cpuport.c42
-rw-r--r--libcpu/arm/cortex-r52/cpuport.h89
-rw-r--r--libcpu/arm/cortex-r52/gicv3.c682
-rw-r--r--libcpu/arm/cortex-r52/gicv3.h197
-rw-r--r--libcpu/arm/cortex-r52/interrupt.c282
-rw-r--r--libcpu/arm/cortex-r52/interrupt.h54
-rw-r--r--libcpu/arm/cortex-r52/stack.c64
-rw-r--r--libcpu/arm/cortex-r52/start_ccs.asm552
-rw-r--r--libcpu/arm/cortex-r52/start_gcc.S504
-rw-r--r--libcpu/arm/cortex-r52/start_iar.S334
-rw-r--r--libcpu/arm/cortex-r52/trap.c318
-rw-r--r--libcpu/arm/cortex-r52/vector_ccs.asm34
-rw-r--r--libcpu/arm/cortex-r52/vector_gcc.S41
-rw-r--r--libcpu/arm/cortex-r52/vector_iar.S45
24 files changed, 4937 insertions, 0 deletions
diff --git a/libcpu/Kconfig b/libcpu/Kconfig
index 5d36b7f51e..200c2f6295 100644
--- a/libcpu/Kconfig
+++ b/libcpu/Kconfig
@@ -54,6 +54,10 @@ config ARCH_ARM_CORTEX_M
bool
select ARCH_ARM
+config ARCH_ARM_CORTEX_R
+ bool
+ select ARCH_ARM
+
config ARCH_ARM_CORTEX_FPU
bool
@@ -109,6 +113,10 @@ config ARCH_ARM_CORTEX_R
select ARCH_ARM
select RT_USING_HW_ATOMIC
+config ARCH_ARM_CORTEX_R52
+ bool
+ select ARCH_ARM_CORTEX_R
+
config ARCH_ARM_MMU
bool
select RT_USING_CACHE
diff --git a/libcpu/arm/cortex-r52/SConscript b/libcpu/arm/cortex-r52/SConscript
new file mode 100644
index 0000000000..b259a94c94
--- /dev/null
+++ b/libcpu/arm/cortex-r52/SConscript
@@ -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('CPU', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/libcpu/arm/cortex-r52/armv8.h b/libcpu/arm/cortex-r52/armv8.h
new file mode 100644
index 0000000000..797223ed35
--- /dev/null
+++ b/libcpu/arm/cortex-r52/armv8.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ */
+#ifndef __ARMV8_H__
+#define __ARMV8_H__
+
+/* the exception stack without VFP registers */
+struct rt_hw_exp_stack
+{
+ unsigned long r0;
+ unsigned long r1;
+ unsigned long r2;
+ unsigned long r3;
+ unsigned long r4;
+ unsigned long r5;
+ unsigned long r6;
+ unsigned long r7;
+ unsigned long r8;
+ unsigned long r9;
+ unsigned long r10;
+ unsigned long fp;
+ unsigned long ip;
+ unsigned long sp;
+ unsigned long lr;
+ unsigned long pc;
+ unsigned long cpsr;
+};
+
+struct rt_hw_stack
+{
+ unsigned long cpsr;
+ unsigned long r0;
+ unsigned long r1;
+ unsigned long r2;
+ unsigned long r3;
+ unsigned long r4;
+ unsigned long r5;
+ unsigned long r6;
+ unsigned long r7;
+ unsigned long r8;
+ unsigned long r9;
+ unsigned long r10;
+ unsigned long fp;
+ unsigned long ip;
+ unsigned long lr;
+ unsigned long pc;
+};
+
+#define USERMODE 0x10
+#define FIQMODE 0x11
+#define IRQMODE 0x12
+#define SVCMODE 0x13
+#define MONITORMODE 0x16
+#define ABORTMODE 0x17
+#define HYPMODE 0x1b
+#define UNDEFMODE 0x1b
+#define MODEMASK 0x1f
+#define NOINT 0xc0
+
+#define T_Bit (1<<5)
+#define F_Bit (1<<6)
+#define I_Bit (1<<7)
+#define A_Bit (1<<8)
+#define E_Bit (1<<9)
+#define J_Bit (1<<24)
+
+#define PABT_EXCEPTION 0x1
+#define DABT_EXCEPTION 0x2
+#define UND_EXCEPTION 0x3
+#define SWI_EXCEPTION 0x4
+#define RESV_EXCEPTION 0xF
+
+void rt_hw_show_register(struct rt_hw_exp_stack *regs);
+
+#endif
diff --git a/libcpu/arm/cortex-r52/backtrace.c b/libcpu/arm/cortex-r52/backtrace.c
new file mode 100644
index 0000000000..ca7ec26138
--- /dev/null
+++ b/libcpu/arm/cortex-r52/backtrace.c
@@ -0,0 +1,545 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2019-03-29 Jesven the first version
+ */
+
+#ifndef __ICCARM__
+#ifndef __CHECKER__
+#if !defined (__ARM_EABI__)
+#warning Your compiler does not have EABI support.
+#warning ARM unwind is known to compile only with EABI compilers.
+#warning Change compiler or disable ARM_UNWIND option.
+#elif (__GNUC__ == 4 && __GNUC_MINOR__ <= 2) && !defined(__clang__)
+#warning Your compiler is too buggy; it is known to not compile ARM unwind support.
+#warning Change compiler or disable ARM_UNWIND option.
+#endif
+#endif /* __CHECKER__ */
+
+#include <rtthread.h>
+#include <rthw.h>
+#include <backtrace.h>
+
+#define DBG_TAG "BACKTRACE"
+#define DBG_LVL DBG_INFO
+#include <rtdbg.h>
+
+#ifdef RT_USING_SMART
+#include <lwp.h>
+#include <lwp_user_mm.h>
+#include <lwp_arch.h>
+#endif
+
+rt_inline void arm_get_current_stackframe(struct pt_regs *regs, struct stackframe *frame)
+{
+ frame->fp = frame_pointer(regs);
+ frame->sp = regs->ARM_sp;
+ frame->lr = regs->ARM_lr;
+ frame->pc = regs->ARM_pc;
+}
+
+struct unwind_ctrl_block {
+ unsigned long vrs[16]; /* virtual register set */
+ const unsigned long *insn; /* pointer to the current instructions word */
+ unsigned long sp_high; /* highest value of sp allowed */
+ /*
+ * 1 : check for stack overflow for each register pop.
+ * 0 : save overhead if there is plenty of stack remaining.
+ */
+ int check_each_pop;
+ int entries; /* number of entries left to interpret */
+ int byte; /* current byte number in the instructions word */
+};
+
+enum regs
+{
+#ifdef CONFIG_THUMB2_KERNEL
+ FP = 7,
+#else
+ FP = 11,
+#endif
+ SP = 13,
+ LR = 14,
+ PC = 15
+};
+
+static int core_kernel_text(unsigned long addr)
+{
+ return 1;
+}
+
+/* Convert a prel31 symbol to an absolute address */
+#define prel31_to_addr(ptr) \
+ ({ \
+ /* sign-extend to 32 bits */ \
+ long offset = (((long)*(ptr)) << 1) >> 1; \
+ (unsigned long)(ptr) + offset; \
+ })
+
+/*
+ * Binary search in the unwind index. The entries are
+ * guaranteed to be sorted in ascending order by the linker.
+ *
+ * start = first entry
+ * origin = first entry with positive offset (or stop if there is no such entry)
+ * stop - 1 = last entry
+ */
+static const struct unwind_idx *search_index(unsigned long addr,
+ const struct unwind_idx *start,
+ const struct unwind_idx *origin,
+ const struct unwind_idx *stop)
+{
+ unsigned long addr_prel31;
+
+ LOG_D("%s(%08lx, %x, %x, %x)",
+ __func__, addr, start, origin, stop);
+
+ /*
+ * only search in the section with the matching sign. This way the
+ * prel31 numbers can be compared as unsigned longs.
+ */
+ if (addr < (unsigned long)start)
+ /* negative offsets: [start; origin) */
+ stop = origin;
+ else
+ /* positive offsets: [origin; stop) */
+ start = origin;
+
+ /* prel31 for address relavive to start */
+ addr_prel31 = (addr - (unsigned long)start) & 0x7fffffff;
+
+ while (start < stop - 1)
+ {
+ const struct unwind_idx *mid = start + ((stop - start) >> 1);
+
+ /*
+ * As addr_prel31 is relative to start an offset is needed to
+ * make it relative to mid.
+ */
+ if (addr_prel31 - ((unsigned long)mid - (unsigned long)start) <
+ mid->addr_offset)
+ stop = mid;
+ else
+ {
+ /* keep addr_prel31 relative to start */
+ addr_prel31 -= ((unsigned long)mid -
+ (unsigned long)start);
+ start = mid;
+ }
+ }
+
+ if (start->addr_offset <= addr_prel31)
+ return start;
+ else
+ {
+ LOG_W("unwind: Unknown symbol address %08lx", addr);
+ return RT_NULL;
+ }
+}
+
+static const struct unwind_idx *unwind_find_origin(
+ const struct unwind_idx *start, const struct unwind_idx *stop)
+{
+ LOG_D("%s(%x, %x)", __func__, start, stop);
+ while (start < stop)
+ {
+ const struct unwind_idx *mid = start + ((stop - start) >> 1);
+
+ if (mid->addr_offset >= 0x40000000)
+ /* negative offset */
+ start = mid + 1;
+ else
+ /* positive offset */
+ stop = mid;
+ }
+ LOG_D("%s -> %x", __func__, stop);
+ return stop;
+}
+
+static const struct unwind_idx *unwind_find_idx(unsigned long addr, const struct unwind_idx **origin_idx, const struct unwind_idx exidx_start[], const struct unwind_idx exidx_end[])
+{
+ const struct unwind_idx *idx = RT_NULL;
+
+ LOG_D("%s(%08lx)", __func__, addr);
+
+ if (core_kernel_text(addr))
+ {
+ if (!*origin_idx)
+ *origin_idx =
+ unwind_find_origin(exidx_start,
+ exidx_end);
+
+ /* main unwind table */
+ idx = search_index(addr, exidx_start,
+ *origin_idx,
+ exidx_end);
+ }
+
+ LOG_D("%s: idx = %x", __func__, idx);
+ return idx;
+}
+
+static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl)
+{
+ unsigned long ret;
+
+ if (ctrl->entries <= 0)
+ {
+ LOG_W("unwind: Corrupt unwind table");
+ return 0;
+ }
+
+ ret = (*ctrl->insn >> (ctrl->byte * 8)) & 0xff;
+
+ if (ctrl->byte == 0)
+ {
+ ctrl->insn++;
+ ctrl->entries--;
+ ctrl->byte = 3;
+ }
+ else
+ ctrl->byte--;
+
+ return ret;
+}
+
+/* Before poping a register check whether it is feasible or not */
+static int unwind_pop_register(struct unwind_ctrl_block *ctrl,
+ unsigned long **vsp, unsigned int reg)
+{
+ if (ctrl->check_each_pop)
+ if (*vsp >= (unsigned long *)ctrl->sp_high)
+ return -URC_FAILURE;
+
+ ctrl->vrs[reg] = *(*vsp)++;
+ return URC_OK;
+}
+
+/* Helper functions to execute the instructions */
+static int unwind_exec_pop_subset_r4_to_r13(struct unwind_ctrl_block *ctrl,
+ unsigned long mask)
+{
+ unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
+ int load_sp, reg = 4;
+
+ load_sp = mask & (1 << (13 - 4));
+ while (mask)
+ {
+ if (mask & 1)
+ if (unwind_pop_register(ctrl, &vsp, reg))
+ return -URC_FAILURE;
+ mask >>= 1;
+ reg++;
+ }
+ if (!load_sp)
+ ctrl->vrs[SP] = (unsigned long)vsp;
+
+ return URC_OK;
+}
+
+static int unwind_exec_pop_r4_to_rN(struct unwind_ctrl_block *ctrl,
+ unsigned long insn)
+{
+ unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
+ int reg;
+
+ /* pop R4-R[4+bbb] */
+ for (reg = 4; reg <= 4 + (insn & 7); reg++)
+ if (unwind_pop_register(ctrl, &vsp, reg))
+ return -URC_FAILURE;
+
+ if (insn & 0x8)
+ if (unwind_pop_register(ctrl, &vsp, 14))
+ return -URC_FAILURE;
+
+ ctrl->vrs[SP] = (unsigned long)vsp;
+
+ return URC_OK;
+}
+
+static int unwind_exec_pop_subset_r0_to_r3(struct unwind_ctrl_block *ctrl,
+ unsigned long mask)
+{
+ unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
+ int reg = 0;
+
+ /* pop R0-R3 according to mask */
+ while (mask)
+ {
+ if (mask & 1)
+ if (unwind_pop_register(ctrl, &vsp, reg))
+ return -URC_FAILURE;
+ mask >>= 1;
+ reg++;
+ }
+ ctrl->vrs[SP] = (unsigned long)vsp;
+
+ return URC_OK;
+}
+
+/*
+ * Execute the current unwind instruction.
+ */
+static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
+{
+ unsigned long insn = unwind_get_byte(ctrl);
+ int ret = URC_OK;
+
+ LOG_D("%s: insn = %08lx", __func__, insn);
+
+ if ((insn & 0xc0) == 0x00)
+ ctrl->vrs[SP] += ((insn & 0x3f) << 2) + 4;
+ else if ((insn & 0xc0) == 0x40)
+ ctrl->vrs[SP] -= ((insn & 0x3f) << 2) + 4;
+ else if ((insn & 0xf0) == 0x80)
+ {
+ unsigned long mask;
+
+ insn = (insn << 8) | unwind_get_byte(ctrl);
+ mask = insn & 0x0fff;
+ if (mask == 0)
+ {
+ LOG_W("unwind: 'Refuse to unwind' instruction %04lx",
+ insn);
+ return -URC_FAILURE;
+ }
+
+ ret = unwind_exec_pop_subset_r4_to_r13(ctrl, mask);
+ if (ret)
+ goto error;
+ }
+ else if ((insn & 0xf0) == 0x90 &&
+ (insn & 0x0d) != 0x0d)
+ ctrl->vrs[SP] = ctrl->vrs[insn & 0x0f];
+ else if ((insn & 0xf0) == 0xa0)
+ {
+ ret = unwind_exec_pop_r4_to_rN(ctrl, insn);
+ if (ret)
+ goto error;
+ }
+ else if (insn == 0xb0)
+ {
+ if (ctrl->vrs[PC] == 0)
+ ctrl->vrs[PC] = ctrl->vrs[LR];
+ /* no further processing */
+ ctrl->entries = 0;
+ }
+ else if (insn == 0xb1)
+ {
+ unsigned long mask = unwind_get_byte(ctrl);
+
+ if (mask == 0 || mask & 0xf0)
+ {
+ LOG_W("unwind: Spare encoding %04lx",
+ (insn << 8) | mask);
+ return -URC_FAILURE;
+ }
+
+ ret = unwind_exec_pop_subset_r0_to_r3(ctrl, mask);
+ if (ret)
+ goto error;
+ }
+ else if (insn == 0xb2)
+ {
+ unsigned long uleb128 = unwind_get_byte(ctrl);
+
+ ctrl->vrs[SP] += 0x204 + (uleb128 << 2);
+ }
+ else
+ {
+ LOG_W("unwind: Unhandled instruction %02lx", insn);
+ return -URC_FAILURE;
+ }
+
+ LOG_D("%s: fp = %08lx sp = %08lx lr = %08lx pc = %08lx", __func__,
+ ctrl->vrs[FP], ctrl->vrs[SP], ctrl->vrs[LR], ctrl->vrs[PC]);
+
+error:
+ return ret;
+}
+
+#ifdef RT_BACKTRACE_FUNCTION_NAME
+static char *unwind_get_function_name(void *address)
+{
+ uint32_t flag_word = *(uint32_t *)((char*)address - 4);
+
+ if ((flag_word & 0xff000000) == 0xff000000)
+ {
+ return (char *)((char*)address - 4 - (flag_word & 0x00ffffff));
+ }
+ return RT_NULL;
+}
+#endif
+
+/*
+ * Unwind a single frame starting with *sp for the symbol at *pc. It
+ * updates the *pc and *sp with the new values.
+ */
+int unwind_frame(struct stackframe *frame, const struct unwind_idx **origin_idx, const struct unwind_idx exidx_start[], const struct unwind_idx exidx_end[])
+{
+ unsigned long low;
+ const struct unwind_idx *idx;
+ struct unwind_ctrl_block ctrl;
+ struct rt_thread *rt_c_thread;
+
+ /* store the highest address on the stack to avoid crossing it*/
+ low = frame->sp;
+ rt_c_thread = rt_thread_self();
+ ctrl.sp_high = (unsigned long)((char*)rt_c_thread->stack_addr + rt_c_thread->stack_size);
+
+ LOG_D("%s(pc = %08lx lr = %08lx sp = %08lx)", __func__,
+ frame->pc, frame->lr, frame->sp);
+
+ idx = unwind_find_idx(frame->pc, origin_idx, exidx_start, exidx_end);
+ if (!idx)
+ {
+ LOG_W("unwind: Index not found %08lx", frame->pc);
+ return -URC_FAILURE;
+ }
+
+#ifdef RT_BACKTRACE_FUNCTION_NAME
+ {
+ char *fun_name;
+ fun_name = unwind_get_function_name((void *)prel31_to_addr(&idx->addr_offset));
+ if (fun_name)
+ {
+ rt_kprintf("0x%08x @ %s\n", frame->pc, fun_name);
+ }
+ }
+#endif
+
+ ctrl.vrs[FP] = frame->fp;
+ ctrl.vrs[SP] = frame->sp;
+ ctrl.vrs[LR] = frame->lr;
+ ctrl.vrs[PC] = 0;
+
+ if (idx->insn == 1)
+ /* can't unwind */
+ return -URC_FAILURE;
+ else if ((idx->insn & 0x80000000) == 0)
+ /* prel31 to the unwind table */
+ ctrl.insn = (unsigned long *)prel31_to_addr(&idx->insn);
+ else if ((idx->insn & 0xff000000) == 0x80000000)
+ /* only personality routine 0 supported in the index */
+ ctrl.insn = &idx->insn;
+ else
+ {
+ LOG_W("unwind: Unsupported personality routine %08lx in the index at %x",
+ idx->insn, idx);
+ return -URC_FAILURE;
+ }
+
+ /* check the personality routine */
+ if ((*ctrl.insn & 0xff000000) == 0x80000000)
+ {
+ ctrl.byte = 2;
+ ctrl.entries = 1;
+ }
+ else if ((*ctrl.insn & 0xff000000) == 0x81000000)
+ {
+ ctrl.byte = 1;
+ ctrl.entries = 1 + ((*ctrl.insn & 0x00ff0000) >> 16);
+ }
+ else
+ {
+ LOG_W("unwind: Unsupported personality routine %08lx at %x",
+ *ctrl.insn, ctrl.insn);
+ return -URC_FAILURE;
+ }
+
+ ctrl.check_each_pop = 0;
+
+ while (ctrl.entries > 0)
+ {
+ int urc;
+ if ((ctrl.sp_high - ctrl.vrs[SP]) < sizeof(ctrl.vrs))
+ ctrl.check_each_pop = 1;
+ urc = unwind_exec_insn(&ctrl);
+ if (urc < 0)
+ return urc;
+ if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= ctrl.sp_high)
+ return -URC_FAILURE;
+ }
+
+ if (ctrl.vrs[PC] == 0)
+ ctrl.vrs[PC] = ctrl.vrs[LR];
+
+ /* check for infinite loop */
+ if (frame->pc == ctrl.vrs[PC])
+ return -URC_FAILURE;
+
+ frame->fp = ctrl.vrs[FP];
+ frame->sp = ctrl.vrs[SP];
+ frame->lr = ctrl.vrs[LR];
+ frame->pc = ctrl.vrs[PC];
+
+ return URC_OK;
+}
+
+void unwind_backtrace(struct pt_regs *regs, const struct unwind_idx exidx_start[], const struct unwind_idx exidx_end[])
+{
+ struct stackframe frame;
+ const struct unwind_idx *origin_idx = RT_NULL;
+
+ LOG_D("%s(regs = %x)", __func__, regs);
+
+ arm_get_current_stackframe(regs, &frame);
+
+#ifndef RT_BACKTRACE_FUNCTION_NAME
+ rt_kprintf("please use: addr2line -e rtthread.elf -a -f %08x", frame.pc);
+#endif
+ LOG_D("pc = %08x, sp = %08x", frame.pc, frame.sp);
+
+ while (1)
+ {
+ int urc;
+
+ urc = unwind_frame(&frame, &origin_idx, exidx_start, exidx_end);
+ if (urc < 0)
+ break;
+ //dump_backtrace_entry(where, frame.pc, frame.sp - 4);
+#ifndef RT_BACKTRACE_FUNCTION_NAME
+ rt_kprintf(" %08x", frame.pc);
+#endif
+ LOG_D("from: pc = %08x, frame = %08x", frame.pc, frame.sp - 4);
+ }
+ rt_kprintf("\n");
+}
+
+extern const struct unwind_idx __exidx_start[];
+extern const struct unwind_idx __exidx_end[];
+
+void rt_unwind(struct rt_hw_exp_stack *regs, unsigned int pc_adj)
+{
+ struct pt_regs e_regs;
+
+ e_regs.ARM_fp = regs->fp;
+ e_regs.ARM_sp = regs->sp;
+ e_regs.ARM_lr = regs->lr;
+ e_regs.ARM_pc = regs->pc - pc_adj;
+#ifdef RT_USING_SMART
+ if (!lwp_user_accessable((void *)e_regs.ARM_pc, sizeof (void *)))
+ {
+ e_regs.ARM_pc = regs->lr - sizeof(void *);
+ }
+#endif
+ rt_kprintf("backtrace:\n");
+ unwind_backtrace(&e_regs, __exidx_start, __exidx_end);
+}
+
+rt_err_t rt_backtrace(void)
+{
+ struct rt_hw_exp_stack regs;
+
+ __asm volatile ("mov %0, fp":"=r"(regs.fp));
+ __asm volatile ("mov %0, sp":"=r"(regs.sp));
+ __asm volatile ("mov %0, lr":"=r"(regs.lr));
+ __asm volatile ("mov %0, pc":"=r"(regs.pc));
+ rt_unwind(&regs, 8);
+ return RT_EOK;
+}
+#endif // (__ICCARM__) undefined
diff --git a/libcpu/arm/cortex-r52/backtrace.h b/libcpu/arm/cortex-r52/backtrace.h
new file mode 100644
index 0000000000..5e03c2afa7
--- /dev/null
+++ b/libcpu/arm/cortex-r52/backtrace.h
@@ -0,0 +1,83 @@
+#ifndef __BACKTRACE_H
+#define __BACKTRACE_H
+
+#ifndef __ASSEMBLY__
+#include <cpuport.h>
+
+/* Unwind reason code according the the ARM EABI documents */
+enum unwind_reason_code
+{
+ URC_OK = 0, /* operation completed successfully */
+ URC_CONTINUE_UNWIND = 8,
+ URC_FAILURE = 9 /* unspecified failure of some kind */
+};
+
+struct unwind_idx
+{
+ unsigned long addr_offset;
+ unsigned long insn;
+};
+
+struct unwind_table
+{
+ const struct unwind_idx *start;
+ const struct unwind_idx *origin;
+ const struct unwind_idx *stop;
+ unsigned long begin_addr;
+ unsigned long end_addr;
+};
+
+struct stackframe
+{
+ /*
+ * FP member should hold R7 when CONFIG_THUMB2_KERNEL is enabled
+ * and R11 otherwise.
+ */
+ unsigned long fp;
+ unsigned long sp;
+ unsigned long lr;
+ unsigned long pc;
+};
+
+struct pt_regs
+{
+ unsigned long uregs[18];
+};
+
+#define ARM_cpsr uregs[16]
+#define ARM_pc uregs[15]
+#define ARM_lr uregs[14]
+#define ARM_sp uregs[13]
+#define ARM_ip uregs[12]
+#define ARM_fp uregs[11]
+#define ARM_r10 uregs[10]
+#define ARM_r9 uregs[9]
+#define ARM_r8 uregs[8]
+#define ARM_r7 uregs[7]
+#define ARM_r6 uregs[6]
+#define ARM_r5 uregs[5]
+#define ARM_r4 uregs[4]
+#define ARM_r3 uregs[3]
+#define ARM_r2 uregs[2]
+#define ARM_r1 uregs[1]
+#define ARM_r0 uregs[0]
+#define ARM_ORIG_r0 uregs[17]
+
+#define instruction_pointer(regs) (regs)->ARM_pc
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define frame_pointer(regs) (regs)->ARM_r7
+#else
+#define frame_pointer(regs) (regs)->ARM_fp
+#endif
+
+int unwind_frame(struct stackframe *frame, const struct unwind_idx **origin_idx, const struct unwind_idx exidx_start[], const struct unwind_idx exidx_end[]);
+void unwind_backtrace(struct pt_regs *regs, const struct unwind_idx exidx_start[], const struct unwind_idx exidx_end[]);
+
+void rt_unwind(struct rt_hw_exp_stack *regs, unsigned int pc_adj);
+rt_err_t rt_backtrace(void);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __BACKTRACE_H */
+
diff --git a/libcpu/arm/cortex-r52/context_ccs.asm b/libcpu/arm/cortex-r52/context_ccs.asm
new file mode 100644
index 0000000000..6a734cb494
--- /dev/null
+++ b/libcpu/arm/cortex-r52/context_ccs.asm
@@ -0,0 +1,260 @@
+;/*
+; * 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
+; * 2013-05-24 Grissiom port to CCS
+; * 2013-05-26 Grissiom optimize for ARMv7
+; */
+
+ .text
+ .arm
+ .ref rt_thread_switch_interrupt_flag
+ .ref rt_interrupt_from_thread
+ .ref rt_interrupt_to_thread
+ .ref rt_interrupt_enter
+ .ref rt_interrupt_leave
+ .ref rt_hw_trap_irq
+
+;/*
+; * rt_base_t rt_hw_interrupt_disable();
+; */
+ .def rt_hw_interrupt_disable
+ .asmfunc
+rt_hw_interrupt_disable
+ MRS r0, cpsr
+ CPSID IF
+ BX lr
+ .endasmfunc
+
+;/*
+; * void rt_hw_interrupt_enable(rt_base_t level);
+; */
+ .def rt_hw_interrupt_enable
+ .asmfunc
+rt_hw_interrupt_enable
+ MSR cpsr_c, r0
+ BX lr
+ .endasmfunc
+
+;/*
+; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
+; * r0 --> from
+; * r1 --> to
+; */
+ .def rt_hw_context_switch
+ .asmfunc
+rt_hw_context_switch
+ STMDB sp!, {lr} ; push pc (lr should be pushed in place of PC)
+ STMDB sp!, {r0-r12, lr} ; push lr & register file
+
+ MRS r4, cpsr
+ TST lr, #0x01
+ ORRNE r4, r4, #0x20 ; it's thumb code
+
+ STMDB sp!, {r4} ; push cpsr
+
+ .if (__TI_VFP_SUPPORT__)
+ VMRS r4, fpexc
+ TST r4, #0x40000000
+ BEQ __no_vfp_frame1
+ VSTMDB sp!, {d0-d15}
+ VMRS r5, fpscr
+ ; TODO: add support for Common VFPv3.
+ ; Save registers like FPINST, FPINST2
+ STMDB sp!, {r5}
+__no_vfp_frame1
+ STMDB sp!, {r4}
+ .endif
+
+ STR sp, [r0] ; store sp in preempted tasks TCB
+ LDR sp, [r1] ; get new task stack pointer
+
+ .if (__TI_VFP_SUPPORT__)
+ LDMIA sp!, {r0} ; get fpexc
+ VMSR fpexc, r0 ; restore fpexc
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame2
+ LDMIA sp!, {r1} ; get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame2
+ .endif
+
+ LDMIA sp!, {r4} ; pop new task cpsr to spsr
+ MSR spsr_cxsf, r4
+
+ LDMIA sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc, copy spsr to cpsr
+ .endasmfunc
+
+;/*
+; * void rt_hw_context_switch_to(rt_uint32 to);
+; * r0 --> to
+; */
+ .def rt_hw_context_switch_to
+ .asmfunc
+rt_hw_context_switch_to
+ LDR sp, [r0] ; get new task stack pointer
+
+ .if (__TI_VFP_SUPPORT__)
+ LDMIA sp!, {r0} ; get fpexc
+ VMSR fpexc, r0
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_to
+ LDMIA sp!, {r1} ; get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame_to
+ .endif
+
+ LDMIA sp!, {r4} ; pop new task cpsr to spsr
+ MSR spsr_cxsf, r4
+
+ LDMIA sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc, copy spsr to cpsr
+ .endasmfunc
+
+;/*
+; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
+; */
+
+ .def rt_hw_context_switch_interrupt
+ .asmfunc
+rt_hw_context_switch_interrupt
+ LDR r2, pintflag
+ LDR r3, [r2]
+ CMP r3, #1
+ BEQ _reswitch
+ MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1
+ STR r3, [r2]
+ LDR r2, pfromthread ; set rt_interrupt_from_thread
+ STR r0, [r2]
+_reswitch
+ LDR r2, ptothread ; set rt_interrupt_to_thread
+ STR r1, [r2]
+ BX lr
+ .endasmfunc
+
+ .def IRQ_Handler
+IRQ_Handler
+ STMDB sp!, {r0-r12,lr}
+
+ .if (__TI_VFP_SUPPORT__)
+ VMRS r0, fpexc
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_str_irq
+ VSTMDB sp!, {d0-d15}
+ VMRS r1, fpscr
+ ; TODO: add support for Common VFPv3.
+ ; Save registers like FPINST, FPINST2
+ STMDB sp!, {r1}
+__no_vfp_frame_str_irq
+ STMDB sp!, {r0}
+ .endif
+
+ 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, pintflag
+ LDR r1, [r0]
+ CMP r1, #1
+ BEQ rt_hw_context_switch_interrupt_do
+
+ .if (__TI_VFP_SUPPORT__)
+ LDMIA sp!, {r0} ; get fpexc
+ VMSR fpexc, r0
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_ldr_irq
+ LDMIA sp!, {r1} ; get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame_ldr_irq
+ .endif
+
+ LDMIA sp!, {r0-r12,lr}
+ SUBS pc, lr, #4
+
+; /*
+; * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
+; */
+ .def rt_hw_context_switch_interrupt_do
+rt_hw_context_switch_interrupt_do
+ MOV r1, #0 ; clear flag
+ STR r1, [r0]
+
+ .if (__TI_VFP_SUPPORT__)
+ LDMIA sp!, {r0} ; get fpexc
+ VMSR fpexc, r0
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_do1
+ LDMIA sp!, {r1} ; get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame_do1
+ .endif
+
+ LDMIA sp!, {r0-r12,lr} ; reload saved registers
+ STMDB sp, {r0-r3} ; save r0-r3. We will restore r0-r3 in the SVC
+ ; mode so there is no need to update SP.
+ SUB r1, sp, #16 ; save the right SP value in r1, so we could restore r0-r3.
+ 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
+ CPSID IF, #0x13
+
+ STMDB sp!, {r2} ; push old task's pc
+ STMDB sp!, {r4-r12,lr} ; push old task's lr,r12-r4
+ LDMIA r1!, {r4-r7} ; restore r0-r3 of the interrupted thread
+ STMDB sp!, {r4-r7} ; push old task's r3-r0. We don't need to push/pop them to
+ ; r0-r3 because we just want to transfer the data and don't
+ ; use them here.
+ STMDB sp!, {r3} ; push old task's cpsr
+
+ .if (__TI_VFP_SUPPORT__)
+ VMRS r0, fpexc
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_do2
+ VSTMDB sp!, {d0-d15}
+ VMRS r1, fpscr
+ ; TODO: add support for Common VFPv3.
+ ; Save registers like FPINST, FPINST2
+ STMDB sp!, {r1}
+__no_vfp_frame_do2
+ STMDB sp!, {r0}
+ .endif
+
+ LDR r4, pfromthread
+ LDR r5, [r4]
+ STR sp, [r5] ; store sp in preempted tasks's TCB
+
+ LDR r6, ptothread
+ LDR r6, [r6]
+ LDR sp, [r6] ; get new task's stack pointer
+
+ .if (__TI_VFP_SUPPORT__)
+ LDMIA sp!, {r0} ; get fpexc
+ VMSR fpexc, r0
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_do3
+ LDMIA sp!, {r1} ; get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame_do3
+ .endif
+
+ LDMIA sp!, {r4} ; pop new task's cpsr to spsr
+ MSR spsr_cxsf, r4
+
+ LDMIA sp!, {r0-r12,lr,pc}^ ; pop new task's r0-r12,lr & pc, copy spsr to cpsr
+
+pintflag .word rt_thread_switch_interrupt_flag
+pfromthread .word rt_interrupt_from_thread
+ptothread .word rt_interrupt_to_thread
diff --git a/libcpu/arm/cortex-r52/context_gcc.S b/libcpu/arm/cortex-r52/context_gcc.S
new file mode 100644
index 0000000000..f02559ca45
--- /dev/null
+++ b/libcpu/arm/cortex-r52/context_gcc.S
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2024-03-01 Wangyuqiang first version
+ */
+
+/**
+ * @addtogroup cortex-r52
+ */
+/*@{*/
+
+//#include <rtconfig.h>
+
+ .text
+ .arm
+ .globl rt_thread_switch_interrupt_flag
+ .globl rt_interrupt_from_thread
+ .globl rt_interrupt_to_thread
+ .globl rt_interrupt_enter
+ .globl rt_interrupt_leave
+ .globl rt_hw_trap_irq
+
+/*
+ * rt_base_t rt_hw_interrupt_disable()
+ */
+ .globl rt_hw_interrupt_disable
+rt_hw_interrupt_disable:
+ MRS r0, cpsr
+ CPSID IF
+ BX lr
+
+/*
+ * void rt_hw_interrupt_enable(rt_base_t level)
+ */
+ .globl rt_hw_interrupt_enable
+rt_hw_interrupt_enable:
+ MSR cpsr_c, r0
+ BX 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:
+ STMDB sp!, {lr} @ push pc (lr should be pushed in place of PC)
+ STMDB sp!, {r0-r12, lr} @ push lr & register file
+
+ MRS r4, cpsr
+ TST lr, #0x01
+ ORRNE r4, r4, #0x20 @ it's thumb code
+
+ STMDB sp!, {r4} @ push cpsr
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ VMRS r4, fpexc
+ TST r4, #0x40000000
+ BEQ __no_vfp_frame1
+ VSTMDB sp!, {d0-d15}
+ VMRS r5, fpscr
+ @ TODO: add support for Common VFPv3.
+ @ Save registers like FPINST, FPINST2
+ STMDB sp!, {r5}
+__no_vfp_frame1:
+ STMDB sp!, {r4}
+#endif
+
+ STR sp, [r0] @ store sp in preempted tasks TCB
+ LDR sp, [r1] @ get new task stack pointer
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ LDMIA sp!, {r0} @ get fpexc
+ VMSR fpexc, r0 @ restore fpexc
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame2
+ LDMIA sp!, {r1} @ get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame2:
+ #endif
+
+ LDMIA sp!, {r4} @ pop new task cpsr to spsr
+ MSR spsr_cxsf, r4
+
+ LDMIA sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr
+
+/*
+ * 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
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ LDMIA sp!, {r0} @ get fpexc
+ VMSR fpexc, r0
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_to
+ LDMIA sp!, {r1} @ get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame_to:
+#endif
+
+ LDMIA sp!, {r4} @ pop new task cpsr to spsr
+ MSR spsr_cxsf, r4
+
+ LDMIA sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr
+
+/*
+ * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)@
+ */
+
+ .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]
+ BX lr
+
+ .globl IRQ_Handler
+IRQ_Handler:
+ STMDB sp!, {r0-r12,lr}
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ VMRS r0, fpexc
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_str_irq
+ VSTMDB sp!, {d0-d15}
+ VMRS r1, fpscr
+ @ TODO: add support for Common VFPv3.
+ @ Save registers like FPINST, FPINST2
+ STMDB sp!, {r1}
+__no_vfp_frame_str_irq:
+ STMDB sp!, {r0}
+#endif
+
+ 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
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ LDMIA sp!, {r0} @ get fpexc
+ VMSR fpexc, r0
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_ldr_irq
+ LDMIA sp!, {r1} @ get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame_ldr_irq:
+#endif
+
+ LDMIA sp!, {r0-r12,lr}
+ SUBS pc, lr, #4
+
+/*
+ * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
+ */
+ .globl rt_hw_context_switch_interrupt_do
+rt_hw_context_switch_interrupt_do:
+ MOV r1, #0 @ clear flag
+ STR r1, [r0]
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ LDMIA sp!, {r0} @ get fpexc
+ VMSR fpexc, r0
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_do1
+ LDMIA sp!, {r1} @ get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame_do1:
+#endif
+
+ LDMIA sp!, {r0-r12,lr} @ reload saved registers
+ STMDB sp, {r0-r3} @ save r0-r3. We will restore r0-r3 in the SVC
+ @ mode so there is no need to update SP.
+ SUB r1, sp, #16 @ save the right SP value in r1, so we could restore r0-r3.
+ 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
+ CPSID IF, #0x13
+
+ STMDB sp!, {r2} @ push old task's pc
+ STMDB sp!, {r4-r12,lr} @ push old task's lr,r12-r4
+ LDMIA r1!, {r4-r7} @ restore r0-r3 of the interrupted thread
+ STMDB sp!, {r4-r7} @ push old task's r3-r0. We don't need to push/pop them to
+ @ r0-r3 because we just want to transfer the data and don't
+ @ use them here.
+ STMDB sp!, {r3} @ push old task's cpsr
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ VMRS r0, fpexc
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_do2
+ VSTMDB sp!, {d0-d15}
+ VMRS r1, fpscr
+ @ TODO: add support for Common VFPv3.
+ @ Save registers like FPINST, FPINST2
+ STMDB sp!, {r1}
+__no_vfp_frame_do2:
+ STMDB sp!, {r0}
+#endif
+
+ 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
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ LDMIA sp!, {r0} @ get fpexc
+ VMSR fpexc, r0
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_do3
+ LDMIA sp!, {r1} @ get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame_do3:
+#endif
+
+ LDMIA sp!, {r4} @ pop new task's cpsr to spsr
+ MSR spsr_cxsf, r4
+
+ LDMIA sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
+
diff --git a/libcpu/arm/cortex-r52/context_iar.S b/libcpu/arm/cortex-r52/context_iar.S
new file mode 100644
index 0000000000..aca9f91a1b
--- /dev/null
+++ b/libcpu/arm/cortex-r52/context_iar.S
@@ -0,0 +1,260 @@
+;/*
+; * 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
+; * 2013-05-24 Grissiom port to CCS
+; * 2013-05-26 Grissiom optimize for ARMv7
+; * 2013-10-20 Grissiom port to GCC
+; * 2024-03-11 Wangyuqiang rzn2l adapt
+; */
+
+ SECTION .text:CODE(2)
+ ARM
+
+ IMPORT rt_thread_switch_interrupt_flag
+ IMPORT rt_interrupt_from_thread
+ IMPORT rt_interrupt_to_thread
+ IMPORT rt_interrupt_enter
+ IMPORT rt_interrupt_leave
+ IMPORT rt_hw_trap_irq
+
+;/*
+; * rt_base_t rt_hw_interrupt_disable();
+; */
+ EXPORT rt_hw_interrupt_disable
+rt_hw_interrupt_disable:
+ MRS r0, CPSR
+ CPSID I
+ BX lr
+
+;/*
+; * void rt_hw_interrupt_enable(rt_base_t level);
+; */
+ EXPORT rt_hw_interrupt_enable
+rt_hw_interrupt_enable:
+ MSR CPSR_c, r0
+ BX lr
+
+;/*
+; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to)
+; * r0 --> from
+; * r1 --> to
+; */
+ EXPORT rt_hw_context_switch
+rt_hw_context_switch:
+ STMDB sp!, {lr} ; push pc (lr should be pushed in place of PC)
+ STMDB sp!, {r0-r12, lr} ; push lr & register file
+
+ MRS r4, CPSR
+ TST lr, #0x01
+ ;ORRNE r4, r4, #0x20 ; it's thumb code
+ CMP r4, #0
+ BNE ne_label
+ne_label:
+ ORR r4, r4, #0x20
+ STMDB sp!, {r4} ; push cpsr
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ VMRS r4, fpexc
+ TST r4, #0x40000000
+ BEQ __no_vfp_frame1
+ VSTMDB sp!, {d0-d15}
+ VMRS r5, fpscr
+ ; TODO: add support for Common VFPv3.
+ ; Save registers like FPINST, FPINST2
+ STMDB sp!, {r5}
+__no_vfp_frame1:
+ STMDB sp!, {r4}
+#endif
+
+ STR sp, [r0] ; store sp in preempted tasks TCB
+ LDR sp, [r1] ; get new task stack pointer
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ LDMIA sp!, {r0} ;@ get fpexc
+ VMSR fpexc, r0 ;@ restore fpexc
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame2
+ LDMIA sp!, {r1} ;@ get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame2:
+ #endif
+
+ LDMIA sp!, {r4} ; pop new task cpsr to spsr
+ MSR spsr_cxsf, r4
+
+ LDMIA sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc, copy spsr to cpsr
+ MOV lr, pc
+ STMIA sp!, {lr}
+
+;/*
+; * void rt_hw_context_switch_to(rt_uint32 to)
+; * r0 --> to
+; */
+ EXPORT rt_hw_context_switch_to
+rt_hw_context_switch_to:
+ LDR sp, [r0] ; get new task stack pointer
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ LDMIA sp!, {r0} @ get fpexc
+ VMSR fpexc, r0
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_to
+ LDMIA sp!, {r1} @ get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame_to:
+#endif
+
+ LDMIA sp!, {r4} ; pop new task cpsr to spsr
+ MSR spsr_cxsf, r4
+
+ LDMIA sp!, {r0-r12, lr, pc}^
+
+;/*
+; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)@
+; */
+
+ EXPORT 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]
+ BX lr
+
+ EXPORT IRQ_Handler
+IRQ_Handler:
+ STMDB sp!, {r0-r12,lr}
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ VMRS r0, fpexc
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_str_irq
+ VSTMDB sp!, {d0-d15}
+ VMRS r1, fpscr
+ ; TODO: add support for Common VFPv3.
+ ; Save registers like FPINST, FPINST2
+ STMDB sp!, {r1}
+__no_vfp_frame_str_irq:
+ STMDB sp!, {r0}
+#endif
+
+ 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
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ LDMIA sp!, {r0} ; get fpexc
+ VMSR fpexc, r0
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_ldr_irq
+ LDMIA sp!, {r1} ; get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame_ldr_irq:
+#endif
+
+ LDMIA sp!, {r0-r12,lr}
+ SUBS pc, lr, #4
+
+;/*
+; * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
+; */
+ EXPORT rt_hw_context_switch_interrupt_do
+rt_hw_context_switch_interrupt_do:
+ MOV r1, #0 ; clear flag
+ STR r1, [r0]
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ LDMIA sp!, {r0} ; get fpexc
+ VMSR fpexc, r0
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_do1
+ LDMIA sp!, {r1} ; get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame_do1:
+#endif
+
+ LDMIA sp!, {r0-r12,lr} ; reload saved registers
+ STMDB sp, {r0-r3} ; save r0-r3. We will restore r0-r3 in the SVC
+ ; mode so there is no need to update SP.
+ SUB r1, sp, #16 ; save the right SP value in r1, so we could restore r0-r3.
+ 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
+ CPSID IF, #0x13
+
+ STMDB sp!, {r2} ; push old task's pc
+ STMDB sp!, {r4-r12,lr} ; push old task's lr,r12-r4
+ LDMIA r1!, {r4-r7} ; restore r0-r3 of the interrupted thread
+ STMDB sp!, {r4-r7} ; push old task's r3-r0. We don't need to push/pop them to
+ ; r0-r3 because we just want to transfer the data and don't
+ ; use them here.
+ STMDB sp!, {r3} ; push old task's cpsr
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ VMRS r0, fpexc
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_do2
+ VSTMDB sp!, {d0-d15}
+ VMRS r1, fpscr
+ ; TODO: add support for Common VFPv3.
+ ; Save registers like FPINST, FPINST2
+ STMDB sp!, {r1}
+__no_vfp_frame_do2:
+ STMDB sp!, {r0}
+#endif
+
+ 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
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ LDMIA sp!, {r0} ; get fpexc
+ VMSR fpexc, r0
+ TST r0, #0x40000000
+ BEQ __no_vfp_frame_do3
+ LDMIA sp!, {r1} ; get fpscr
+ VMSR fpscr, r1
+ VLDMIA sp!, {d0-d15}
+__no_vfp_frame_do3:
+#endif
+
+ LDMIA sp!, {r4} ; pop new task's cpsr to spsr
+ MSR spsr_cxsf, r4
+
+ LDMIA sp!, {r0-r12,lr,pc}^ ; pop new task's r0-r12,lr & pc, copy spsr to cpsr
+ MOV lr, pc
+ STMIA sp!, {r0-r12, lr}
+ STR pc, [sp]
+
+ END
diff --git a/libcpu/arm/cortex-r52/cp15.h b/libcpu/arm/cortex-r52/cp15.h
new file mode 100644
index 0000000000..9bab60997e
--- /dev/null
+++ b/libcpu/arm/cortex-r52/cp15.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011-2024, Shanghai Real-Thread Electronic Technology Co.,Ltd
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-08-29 RT-Thread first version
+ */
+
+#ifndef __CP15_H__
+#define __CP15_H__
+
+#define __get_cp(cp, op1, Rt, CRn, CRm, op2) \
+ __asm volatile("MRC p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : "=r" (Rt) : : "memory" )
+#define __set_cp(cp, op1, Rt, CRn, CRm, op2) \
+ __asm volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
+#define __get_cp64(cp, op1, Rt, CRm) \
+ __asm volatile("MRRC p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : "=r" (Rt) : : "memory" )
+#define __set_cp64(cp, op1, Rt, CRm) \
+ __asm volatile("MCRR p" # cp ", " # op1 ", %Q0, %R0, c" # CRm : : "r" (Rt) : "memory" )
+
+#endif
diff --git a/libcpu/arm/cortex-r52/cp15_gcc.S b/libcpu/arm/cortex-r52/cp15_gcc.S
new file mode 100644
index 0000000000..1d5b84d596
--- /dev/null
+++ b/libcpu/arm/cortex-r52/cp15_gcc.S
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2011-2022, Shanghai Real-Thread Electronic Technology Co.,Ltd
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-08-29 RT-Thread first version
+ */
+
+
+.globl rt_cpu_get_smp_id
+rt_cpu_get_smp_id:
+ mrc p15, #0, r0, c0, c0, #5
+ bx lr
+
+.globl rt_cpu_vector_set_base
+rt_cpu_vector_set_base:
+ /* clear SCTRL.V to customize the vector address */
+ mrc p15, #0, r1, c1, c0, #0
+ bic r1, #(1 << 13)
+ mcr p15, #0, r1, c1, c0, #0
+ /* set up the vector address */
+ mcr p15, #0, r0, c12, c0, #0
+ dsb
+ bx lr
+
+.globl rt_hw_cpu_dcache_enable
+rt_hw_cpu_dcache_enable:
+ mrc p15, #0, r0, c1, c0, #0
+ orr r0, r0, #0x00000004
+ mcr p15, #0, r0, c1, c0, #0
+ bx lr
+
+.globl rt_hw_cpu_icache_enable
+rt_hw_cpu_icache_enable:
+ mrc p15, #0, r0, c1, c0, #0
+ orr r0, r0, #0x00001000
+ mcr p15, #0, r0, c1, c0, #0
+ bx lr
+
+_FLD_MAX_WAY:
+ .word 0x3ff
+_FLD_MAX_IDX:
+ .word 0x7fff
+
+.globl rt_cpu_dcache_clean_flush
+rt_cpu_dcache_clean_flush:
+stmfd sp!, {r0-r12, lr}
+ bl v7_flush_dcache_all
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
+ dsb
+ isb
+ ldmfd sp!, {r0-r12, lr}
+ mov pc, lr
+
+v7_flush_dcache_all:
+ dmb @ ensure ordering with previous memory accesses
+ mrc p15, 1, r0, c0, c0, 1 @ read clidr
+ ands r3, r0, #0x7000000 @ extract loc from clidr
+ mov r3, r3, lsr #23 @ left align loc bit field
+ beq finished @ if loc is 0, then no need to clean
+ mov r10, #0 @ start clean at cache level 0
+loop1:
+ add r2, r10, r10, lsr #1 @ work out 3x current cache level
+ mov r1, r0, lsr r2 @ extract cache type bits from clidr
+ and r1, r1, #7 @ mask of the bits for current cache only
+ cmp r1, #2 @ see what cache we have at this level
+ blt skip @ skip if no cache, or just i-cache
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
+ isb @ isb to sych the new cssr&csidr
+ mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
+ and r2, r1, #7 @ extract the length of the cache lines
+ add r2, r2, #4 @ add 4 (line length offset)
+ ldr r4, =0x3ff
+ ands r4, r4, r1, lsr #3 @ find maximum number on the way size
+ clz r5, r4 @ find bit position of way size increment
+ ldr r7, =0x7fff
+ ands r7, r7, r1, lsr #13 @ extract max number of the index size
+loop2:
+ mov r9, r4 @ create working copy of max way size
+loop3:
+ orr r11, r10, r9, lsl r5 @ factor way and cache number into r11
+ orr r11, r11, r7, lsl r2 @ factor index number into r11
+ mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
+ subs r9, r9, #1 @ decrement the way
+ bge loop3
+ subs r7, r7, #1 @ decrement the index
+ bge loop2
+skip:
+ add r10, r10, #2 @ increment cache number
+ cmp r3, r10
+ bgt loop1
+finished:
+ mov r10, #0 @ swith back to cache level 0
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
+ dsb
+ isb
+ mov pc, lr
+#if 0
+ push {r4-r11}
+ dmb
+ mrc p15, #1, r0, c0, c0, #1 @ read clid register
+ ands r3, r0, #0x7000000 @ get level of coherency
+ mov r3, r3, lsr #23
+ beq finished
+ mov r10, #0
+loop1:
+ add r2, r10, r10, lsr #1
+ mov r1, r0, lsr r2
+ and r1, r1, #7
+ cmp r1, #2
+ blt skip
+ mcr p15, #2, r10, c0, c0, #0
+ isb
+ mrc p15, #1, r1, c0, c0, #0
+ and r2, r1, #7
+ add r2, r2, #4
+ ldr r4, _FLD_MAX_WAY
+ ands r4, r4, r1, lsr #3
+ clz r5, r4
+ ldr r7, _FLD_MAX_IDX
+ ands r7, r7, r1, lsr #13
+loop2:
+ mov r9, r4
+loop3:
+ orr r11, r10, r9, lsl r5
+ orr r11, r11, r7, lsl r2
+ mcr p15, #0, r11, c7, c14, #2
+ subs r9, r9, #1
+ bge loop3
+ subs r7, r7, #1
+ bge loop2
+skip:
+ add r10, r10, #2
+ cmp r3, r10
+ bgt loop1
+
+finished:
+ dsb
+ isb
+ pop {r4-r11}
+ bx lr
+#endif
+.globl rt_cpu_icache_flush
+rt_cpu_icache_flush:
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
+ dsb
+ isb
+ bx lr
+
+.globl rt_hw_cpu_dcache_disable
+rt_hw_cpu_dcache_disable:
+ push {r4-r11, lr}
+ bl rt_cpu_dcache_clean_flush
+ mrc p15, #0, r0, c1, c0, #0
+ bic r0, r0, #0x00000004
+ mcr p15, #0, r0, c1, c0, #0
+ pop {r4-r11, lr}
+ bx lr
+
+.globl rt_hw_cpu_icache_disable
+rt_hw_cpu_icache_disable:
+ mrc p15, #0, r0, c1, c0, #0
+ bic r0, r0, #0x00001000
+ mcr p15, #0, r0, c1, c0, #0
+ bx lr
diff --git a/libcpu/arm/cortex-r52/cpuport.c b/libcpu/arm/cortex-r52/cpuport.c
new file mode 100644
index 0000000000..16c3a5198a
--- /dev/null
+++ b/libcpu/arm/cortex-r52/cpuport.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011-2024, Shanghai Real-Thread Electronic Technology Co.,Ltd
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-08-29 RT-Thread first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+int rt_hw_cpu_id(void)
+{
+ int cpu_id;
+ __asm volatile (
+ "mrc p15, 0, %0, c0, c0, 5"
+ :"=r"(cpu_id)
+ );
+ cpu_id &= 0xf;
+ return cpu_id;
+}
+
+/**
+ * @addtogroup ARM CPU
+ */
+/*@{*/
+
+/** shutdown CPU */
+void rt_hw_cpu_shutdown()
+{
+ rt_uint32_t level;
+
+ rt_kprintf("shutdown...\n");
+
+ level = rt_hw_interrupt_disable();
+ while (level)
+ {
+ RT_ASSERT(0);
+ }
+}
+
+/*@}*/
diff --git a/libcpu/arm/cortex-r52/cpuport.h b/libcpu/arm/cortex-r52/cpuport.h
new file mode 100644
index 0000000000..8b408e054c
--- /dev/null
+++ b/libcpu/arm/cortex-r52/cpuport.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011-2024, Shanghai Real-Thread Electronic Technology Co.,Ltd
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-08-29 RT-Thread first version
+ */
+
+
+#ifndef CPUPORT_H__
+#define CPUPORT_H__
+
+/* the exception stack without VFP registers */
+struct rt_hw_exp_stack
+{
+ unsigned long r0;
+ unsigned long r1;
+ unsigned long r2;
+ unsigned long r3;
+ unsigned long r4;
+ unsigned long r5;
+ unsigned long r6;
+ unsigned long r7;
+ unsigned long r8;
+ unsigned long r9;
+ unsigned long r10;
+ unsigned long fp;
+ unsigned long ip;
+ unsigned long sp;
+ unsigned long lr;
+ unsigned long pc;
+ unsigned long cpsr;
+};
+
+struct rt_hw_stack
+{
+ unsigned long cpsr;
+ unsigned long r0;
+ unsigned long r1;
+ unsigned long r2;
+ unsigned long r3;
+ unsigned long r4;
+ unsigned long r5;
+ unsigned long r6;
+ unsigned long r7;
+ unsigned long r8;
+ unsigned long r9;
+ unsigned long r10;
+ unsigned long fp;
+ unsigned long ip;
+ unsigned long lr;
+ unsigned long pc;
+};
+
+#define USERMODE 0x10
+#define FIQMODE 0x11
+#define IRQMODE 0x12
+#define SVCMODE 0x13
+#define MONITORMODE 0x16
+#define ABORTMODE 0x17
+#define HYPMODE 0x1b
+#define UNDEFMODE 0x1b
+#define MODEMASK 0x1f
+#define NOINT 0xc0
+
+#define T_Bit (1<<5)
+#define F_Bit (1<<6)
+#define I_Bit (1<<7)
+#define A_Bit (1<<8)
+#define E_Bit (1<<9)
+#define J_Bit (1<<24)
+
+
+// rt_inline void rt_hw_isb(void)
+// {
+// __asm volatile ("isb":::"memory");
+// }
+
+// rt_inline void rt_hw_dmb(void)
+// {
+// __asm volatile ("dmb":::"memory");
+// }
+
+// rt_inline void rt_hw_dsb(void)
+// {
+// __asm volatile ("dsb":::"memory");
+// }
+
+#endif /*CPUPORT_H__*/
diff --git a/libcpu/arm/cortex-r52/gicv3.c b/libcpu/arm/cortex-r52/gicv3.c
new file mode 100644
index 0000000000..e9d92ab86c
--- /dev/null
+++ b/libcpu/arm/cortex-r52/gicv3.c
@@ -0,0 +1,682 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2013-07-20 Bernard first version
+ * 2014-04-03 Grissiom many enhancements
+ * 2018-11-22 Jesven add rt_hw_ipi_send()
+ * add rt_hw_ipi_handler_install()
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#include "gicv3.h"
+#include "cp15.h"
+
+#ifndef RT_CPUS_NR
+#define RT_CPUS_NR 1
+#endif
+
+struct arm_gic_v3
+{
+ rt_uint32_t offset; /* the first interrupt index in the vector table */
+ rt_uint32_t redist_hw_base[RT_CPUS_NR]; /* the pointer of the gic redistributor */
+ rt_uint32_t dist_hw_base; /* the base address of the gic distributor */
+ rt_uint32_t cpu_hw_base[RT_CPUS_NR]; /* the base addrees of the gic cpu interface */
+};
+
+/* 'ARM_GIC_MAX_NR' is the number of cores */
+static struct arm_gic_v3 _gic_table[ARM_GIC_MAX_NR];
+static unsigned int _gic_max_irq;
+
+/**
+ * @name: arm_gic_cpumask_to_affval
+ * @msg:
+ * @in param cpu_mask:
+ * @out param cluster_id: aff1 [0:7],aff2 [8:15],aff3 [16:23]
+ * @out param target_list: Target List. The set of PEs for which SGI interrupts will be generated. Each bit corresponds to the
+ * PE within a cluster with an Affinity 0 value equal to the bit number.
+ * @return {rt_uint32_t} 0 is finish , 1 is data valid
+ */
+rt_weak rt_uint32_t arm_gic_cpumask_to_affval(rt_uint32_t *cpu_mask, rt_uint32_t *cluster_id, rt_uint32_t *target_list)
+{
+ return 0;
+}
+
+rt_weak rt_uint64_t get_main_cpu_affval(void)
+{
+ return 0;
+}
+
+int arm_gic_get_active_irq(rt_uint32_t index)
+{
+ int irq;
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ __get_gicv3_reg(ICC_IAR1, irq);
+
+ irq = (irq & 0x1FFFFFF) + _gic_table[index].offset;
+ return irq;
+}
+
+void arm_gic_ack(rt_uint32_t index, int irq)
+{
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+ RT_ASSERT(irq >= 0);
+
+ __DSB();
+ __set_gicv3_reg(ICC_EOIR1, irq);
+}
+
+void arm_gic_mask(rt_uint32_t index, int irq)
+{
+ rt_uint32_t mask = 1U << (irq % 32U);
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq >= 0);
+
+ if (irq < 32)
+ {
+ rt_int32_t cpu_id = rt_hw_cpu_id();
+ RT_ASSERT((cpu_id) < RT_CPUS_NR);
+ GIC_RDISTSGI_ICENABLER0(_gic_table[index].redist_hw_base[cpu_id]) = mask;
+ }
+ else
+ {
+ GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
+ }
+}
+
+void arm_gic_umask(rt_uint32_t index, int irq)
+{
+ rt_uint32_t mask = 1U << (irq % 32U);
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ if (irq < 32)
+ {
+ rt_int32_t cpu_id = rt_hw_cpu_id();
+ RT_ASSERT((cpu_id) < RT_CPUS_NR);
+ GIC_RDISTSGI_ISENABLER0(_gic_table[index].redist_hw_base[cpu_id]) = mask;
+ }
+ else
+ {
+ GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask;
+ }
+}
+
+rt_uint32_t arm_gic_get_pending_irq(rt_uint32_t index, int irq)
+{
+ rt_uint32_t pend;
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ if (irq >= 16)
+ {
+ pend = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
+ }
+ else
+ {
+ /* INTID 0-15 Software Generated Interrupt */
+ pend = (GIC_DIST_SPENDSGI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
+ /* No CPU identification offered */
+ if (pend != 0U)
+ {
+ pend = 1U;
+ }
+ else
+ {
+ pend = 0U;
+ }
+ }
+
+ return (pend);
+}
+
+void arm_gic_set_pending_irq(rt_uint32_t index, int irq)
+{
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ if (irq >= 16)
+ {
+ GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) = 1U << (irq % 32U);
+ }
+ else
+ {
+ /* INTID 0-15 Software Generated Interrupt */
+ /* Forward the interrupt to the CPU interface that requested it */
+ GIC_DIST_SOFTINT(_gic_table[index].dist_hw_base) = (irq | 0x02000000U);
+ }
+}
+
+void arm_gic_clear_pending_irq(rt_uint32_t index, int irq)
+{
+ rt_uint32_t mask;
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ if (irq >= 16U)
+ {
+ mask = 1U << (irq % 32U);
+ GIC_DIST_PENDING_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
+ }
+ else
+ {
+ mask = 1U << ((irq % 4U) * 8U);
+ GIC_DIST_CPENDSGI(_gic_table[index].dist_hw_base, irq) = mask;
+ }
+}
+
+void arm_gic_set_configuration(rt_uint32_t index, int irq, rt_uint32_t config)
+{
+ rt_uint32_t icfgr;
+ rt_uint32_t shift;
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ icfgr = GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq);
+ shift = (irq % 16U) << 1U;
+
+ icfgr &= (~(3U << shift));
+ icfgr |= (config << shift);
+
+ GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq) = icfgr;
+}
+
+rt_uint32_t arm_gic_get_configuration(rt_uint32_t index, int irq)
+{
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ return (GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq) >> ((irq % 16U) >> 1U));
+}
+
+void arm_gic_clear_active(rt_uint32_t index, int irq)
+{
+ rt_uint32_t mask = 1U << (irq % 32U);
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ GIC_DIST_ACTIVE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
+}
+
+/* Set up the cpu mask for the specific interrupt */
+void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask)
+{
+ rt_uint32_t old_tgt;
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ old_tgt = GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq);
+
+ old_tgt &= ~(0x0FFUL << ((irq % 4U) * 8U));
+ old_tgt |= cpumask << ((irq % 4U) * 8U);
+
+ GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) = old_tgt;
+}
+
+rt_uint32_t arm_gic_get_target_cpu(rt_uint32_t index, int irq)
+{
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ return (GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
+}
+
+void arm_gic_set_priority(rt_uint32_t index, int irq, rt_uint32_t priority)
+{
+ rt_uint32_t mask;
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ if (irq < 32U)
+ {
+ rt_int32_t cpu_id = rt_hw_cpu_id();
+ RT_ASSERT((cpu_id) < RT_CPUS_NR);
+
+ mask = GIC_RDISTSGI_IPRIORITYR(_gic_table[index].redist_hw_base[cpu_id], irq);
+ mask &= ~(0xFFUL << ((irq % 4U) * 8U));
+ mask |= ((priority & 0xFFUL) << ((irq % 4U) * 8U));
+ GIC_RDISTSGI_IPRIORITYR(_gic_table[index].redist_hw_base[cpu_id], irq) = mask;
+ }
+ else
+ {
+ mask = GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq);
+ mask &= ~(0xFFUL << ((irq % 4U) * 8U));
+ mask |= ((priority & 0xFFUL) << ((irq % 4U) * 8U));
+ GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq) = mask;
+ }
+}
+
+rt_uint32_t arm_gic_get_priority(rt_uint32_t index, int irq)
+{
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ if (irq < 32U)
+ {
+ rt_int32_t cpu_id = rt_hw_cpu_id();
+
+ RT_ASSERT((cpu_id) < RT_CPUS_NR);
+ return (GIC_RDISTSGI_IPRIORITYR(_gic_table[index].redist_hw_base[cpu_id], irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
+ }
+ else
+ {
+ return (GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
+ }
+}
+
+void arm_gic_set_system_register_enable_mask(rt_uint32_t index, rt_uint32_t value)
+{
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ value &= 0xFFUL;
+ /* set priority mask */
+ __set_gicv3_reg(ICC_SRE, value);
+ __ISB();
+// __asm volatile ("isb 0xF"::
+// :"memory");
+}
+
+rt_uint32_t arm_gic_get_system_register_enable_mask(rt_uint32_t index)
+{
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+ rt_uint32_t value;
+
+ __get_gicv3_reg(ICC_SRE, value);
+ return value;
+}
+
+void arm_gic_set_interface_prior_mask(rt_uint32_t index, rt_uint32_t priority)
+{
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ priority &= 0xFFUL;
+ /* set priority mask */
+ __set_gicv3_reg(ICC_PMR, priority);
+}
+
+rt_uint32_t arm_gic_get_interface_prior_mask(rt_uint32_t index)
+{
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+ rt_uint32_t priority;
+
+ __get_gicv3_reg(ICC_PMR, priority);
+ return priority;
+}
+
+void arm_gic_set_binary_point(rt_uint32_t index, rt_uint32_t binary_point)
+{
+ index = index;
+ binary_point &= 0x7U;
+
+ __set_gicv3_reg(ICC_BPR1, binary_point);
+}
+
+rt_uint32_t arm_gic_get_binary_point(rt_uint32_t index)
+{
+ rt_uint32_t binary_point;
+
+ index = index;
+ __get_gicv3_reg(ICC_BPR1, binary_point);
+ return binary_point;
+}
+
+rt_uint32_t arm_gic_get_irq_status(rt_uint32_t index, int irq)
+{
+ rt_uint32_t pending;
+ rt_uint32_t active;
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ active = (GIC_DIST_ACTIVE_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
+ pending = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
+
+ return ((active << 1U) | pending);
+}
+
+rt_uint32_t arm_gic_get_high_pending_irq(rt_uint32_t index)
+{
+ rt_uint32_t irq;
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ index = index;
+ __get_gicv3_reg(ICC_HPPIR1, irq);
+ return irq;
+}
+
+rt_uint32_t arm_gic_get_interface_id(rt_uint32_t index)
+{
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ return GIC_CPU_IIDR(_gic_table[index].cpu_hw_base);
+}
+
+void arm_gic_set_group(rt_uint32_t index, int irq, rt_uint32_t group)
+{
+ rt_uint32_t igroupr;
+ rt_uint32_t shift;
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+ RT_ASSERT(group <= 1U);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ igroupr = GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq);
+ shift = (irq % 32U);
+ igroupr &= (~(1U << shift));
+ igroupr |= ((group & 0x1U) << shift);
+
+ GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq) = igroupr;
+}
+
+rt_uint32_t arm_gic_get_group(rt_uint32_t index, int irq)
+{
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ irq = irq - _gic_table[index].offset;
+ RT_ASSERT(irq > 0U);
+
+ return (GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
+}
+
+static int arm_gicv3_wait_rwp(rt_uint32_t index, rt_uint32_t irq)
+{
+ rt_uint32_t rwp_bit;
+ rt_uint32_t base;
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ if (irq < 32u)
+ {
+ rt_int32_t cpu_id = rt_hw_cpu_id();
+
+ RT_ASSERT((cpu_id) < RT_CPUS_NR);
+ base = _gic_table[index].redist_hw_base[cpu_id];
+ rwp_bit = GICR_CTLR_RWP;
+ }
+ else
+ {
+ base = _gic_table[index].dist_hw_base;
+ rwp_bit = GICD_CTLR_RWP;
+ }
+
+ while (__REG32(base) & rwp_bit)
+ {
+ ;
+ }
+
+ return 0;
+}
+
+int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start)
+{
+ rt_uint64_t cpu0_affval;
+ unsigned int gic_type, i;
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ _gic_table[index].dist_hw_base = dist_base;
+ _gic_table[index].offset = irq_start;
+
+ /* Find out how many interrupts are supported. */
+ gic_type = GIC_DIST_TYPE(dist_base);
+ _gic_max_irq = ((gic_type & 0x1fU) + 1U) * 32U;
+
+ /*
+ * The GIC only supports up to 1020 interrupt sources.
+ * Limit this to either the architected maximum, or the
+ * platform maximum.
+ */
+ if (_gic_max_irq > 1020U)
+ _gic_max_irq = 1020U;
+ if (_gic_max_irq > ARM_GIC_NR_IRQS) /* the platform maximum interrupts */
+ _gic_max_irq = ARM_GIC_NR_IRQS;
+
+ GIC_DIST_CTRL(dist_base) = 0x0U;
+ /* Wait for register write pending */
+ arm_gicv3_wait_rwp(0, 32);
+
+ /* Set all global interrupts to be level triggered, active low. */
+ for (i = 32U; i < _gic_max_irq; i += 16U)
+ GIC_DIST_CONFIG(dist_base, i) = 0x0U;
+
+ arm_gicv3_wait_rwp(0, 32);
+
+ cpu0_affval = get_main_cpu_affval();
+ /* Set all global interrupts to this CPU only. */
+ for (i = 32U; i < _gic_max_irq; i++)
+ {
+ GIC_DIST_IROUTER_LOW(dist_base, i) = cpu0_affval;
+ GIC_DIST_IROUTER_HIGH(dist_base, i) = cpu0_affval >> 32;
+ }
+
+ arm_gicv3_wait_rwp(0, 32);
+
+ /* Set priority on spi interrupts. */
+ for (i = 32U; i < _gic_max_irq; i += 4U)
+ GIC_DIST_PRI(dist_base, i) = 0xa0a0a0a0U;
+
+ arm_gicv3_wait_rwp(0, 32);
+ /* Disable all interrupts. */
+ for (i = 0U; i < _gic_max_irq; i += 32U)
+ {
+ GIC_DIST_PENDING_CLEAR(dist_base, i) = 0xffffffffU;
+ GIC_DIST_ENABLE_CLEAR(dist_base, i) = 0xffffffffU;
+ }
+
+ arm_gicv3_wait_rwp(0, 32);
+ /* All interrupts defaults to IGROUP1(IRQ). */
+ for (i = 0U; i < _gic_max_irq; i += 32U)
+ GIC_DIST_IGROUP(dist_base, i) = 0xffffffffU;
+
+ arm_gicv3_wait_rwp(0, 32);
+
+ /*
+ The Distributor control register (GICD_CTLR) must be configured to enable the interrupt groups and to set the routing mode.
+ Enable Affinity routing (ARE bits) The ARE bits in GICD_CTLR control whether affinity routing is enabled.
+ If affinity routing is not enabled, GICv3 can be configured for legacy operation.
+ Whether affinity routing is enabled or not can be controlled separately for Secure and Non-secure state.
+ Enables GICD_CTLR contains separate enable bits for Group 0, Secure Group 1 and Non-secure Group 1:
+ GICD_CTLR.EnableGrp1S enables distribution of Secure Group 1 interrupts.
+ GICD_CTLR.EnableGrp1NS enables distribution of Non-secure Group 1 interrupts.
+ GICD_CTLR.EnableGrp0 enables distribution of Group 0 interrupts.
+ */
+ GIC_DIST_CTRL(dist_base) = GICD_CTLR_ARE_NS | GICD_CTLR_ENGRP1NS;
+
+ return 0;
+}
+
+int arm_gic_redist_address_set(rt_uint32_t index, rt_uint32_t redist_addr, rt_uint32_t cpu_id)
+{
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+ RT_ASSERT((cpu_id) < RT_CPUS_NR);
+ _gic_table[index].redist_hw_base[cpu_id] = redist_addr;
+
+ return 0;
+}
+
+int arm_gic_cpu_interface_address_set(rt_uint32_t index, rt_uint32_t interface_addr, rt_uint32_t cpu_id)
+{
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+ RT_ASSERT((cpu_id) < RT_CPUS_NR);
+ _gic_table[index].cpu_hw_base[cpu_id] = interface_addr;
+
+ return 0;
+}
+
+int arm_gic_redist_init(rt_uint32_t index)
+{
+ unsigned int i;
+ rt_uint32_t base;
+ rt_int32_t cpu_id = rt_hw_cpu_id();
+
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+ RT_ASSERT((cpu_id) < RT_CPUS_NR);
+
+ base = _gic_table[index].redist_hw_base[cpu_id];
+ /* redistributor enable */
+ // 将原来的值的第二位清零,其他位保持不变
+ GIC_RDIST_WAKER(base) &= ~(1U << 1);
+ // 一直执行,直到GIC_RDIST_WAKER(base)的值的第2位(从0开始计数)为0
+ while (GIC_RDIST_WAKER(base) & (1 << 2))
+ {
+ ;
+ }
+
+ /* Disable all sgi and ppi interrupt */
+ GIC_RDISTSGI_ICENABLER0(base) = 0xFFFFFFFF;
+ arm_gicv3_wait_rwp(0, 0);
+
+ /* Clear all inetrrupt pending */
+ GIC_RDISTSGI_ICPENDR0(base) = 0xFFFFFFFF;
+
+ /* the corresponding interrupt is Group 1 or Non-secure Group 1. */
+ GIC_RDISTSGI_IGROUPR0(base, 0) = 0xFFFFFFFF;
+ GIC_RDISTSGI_IGRPMODR0(base, 0) = 0xFFFFFFFF;
+
+ /* Configure default priorities for SGI 0:15 and PPI 16:31. */
+ for (i = 0; i < 32; i += 4)
+ {
+ GIC_RDISTSGI_IPRIORITYR(base, i) = 0xa0a0a0a0U;
+ }
+
+ /* Trigger level for PPI interrupts*/
+ GIC_RDISTSGI_ICFGR1(base) = 0x0U; // PPI is level-sensitive.
+ return 0;
+}
+
+int arm_gic_cpu_init(rt_uint32_t index)
+{
+ rt_uint32_t value;
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
+
+ /* The Priority Mask sets the minimum priority an
+ * interrupt must have in order to be forwarded to the PE.
+ */
+ value = arm_gic_get_system_register_enable_mask(index);
+ value |= (1U << 0);
+
+ arm_gic_set_system_register_enable_mask(index, value);
+ __set_gicv3_reg(ICC_CTLR, 0);
+
+ arm_gic_set_interface_prior_mask(index, 0xFFU);
+
+ /* Enable group1 interrupt */
+ value = 0x1U;
+ __set_gicv3_reg(ICC_IGRPEN1, value);
+
+ /* The Binary Point register is used
+ * for priority grouping and preemption.
+ */
+ arm_gic_set_binary_point(0, 0);
+
+ /* ICC_BPR0_EL1 determines the preemption group for both
+ Group 0 and Group 1 interrupts.
+ */
+ value = 0x1U;
+ __set_gicv3_reg(ICC_CTLR, value);
+
+ return 0;
+}
+
+#ifdef RT_USING_SMP
+void arm_gic_secondary_cpu_init(void)
+{
+ arm_gic_redist_init(0);
+
+ arm_gic_cpu_init(0);
+}
+#endif
+
+void arm_gic_dump_type(rt_uint32_t index)
+{
+ unsigned int gic_type;
+
+ gic_type = GIC_DIST_TYPE(_gic_table[index].dist_hw_base);
+ rt_kprintf("GICv%d on %p, max IRQs: %d, %s security extension(%08x)\n",
+ (GIC_DIST_ICPIDR2(_gic_table[index].dist_hw_base) >> 4U) & 0xfUL,
+ _gic_table[index].dist_hw_base,
+ _gic_max_irq,
+ gic_type & (1U << 10U) ? "has" : "no",
+ gic_type);
+}
+
+void arm_gic_dump(rt_uint32_t index)
+{
+ unsigned int i, k;
+
+ k = arm_gic_get_high_pending_irq(0);
+ rt_kprintf("--- high pending priority: %d(%08x)\n", k, k);
+ rt_kprintf("--- hw mask ---\n");
+ for (i = 0U; i < _gic_max_irq / 32U; i++)
+ {
+ rt_kprintf("0x%08x, ",
+ GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base,
+ i * 32U));
+ }
+ rt_kprintf("\n--- hw pending ---\n");
+ for (i = 0U; i < _gic_max_irq / 32U; i++)
+ {
+ rt_kprintf("0x%08x, ",
+ GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base,
+ i * 32U));
+ }
+ rt_kprintf("\n--- hw active ---\n");
+ for (i = 0U; i < _gic_max_irq / 32U; i++)
+ {
+ rt_kprintf("0x%08x, ",
+ GIC_DIST_ACTIVE_SET(_gic_table[index].dist_hw_base,
+ i * 32U));
+ }
+ rt_kprintf("\n");
+}
+
+long gic_dump(void)
+{
+ arm_gic_dump_type(0);
+ arm_gic_dump(0);
+
+ return 0;
+}
diff --git a/libcpu/arm/cortex-r52/gicv3.h b/libcpu/arm/cortex-r52/gicv3.h
new file mode 100644
index 0000000000..e92c6cd9f7
--- /dev/null
+++ b/libcpu/arm/cortex-r52/gicv3.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2013-07-20 Bernard first version
+ */
+
+#ifndef __GIC_V3_H__
+#define __GIC_V3_H__
+
+#include <rthw.h>
+#include <board.h>
+
+#define __get_gicv3_reg(CR, Rt) __asm volatile("MRC " CR \
+ : "=r"(Rt) \
+ : \
+ : "memory")
+#define __set_gicv3_reg(CR, Rt) __asm volatile("MCR " CR \
+ : \
+ : "r"(Rt) \
+ : "memory")
+
+
+/* AArch32 System register interface to GICv3 */
+#define ICC_IAR0 "p15, 0, %0, c12, c8, 0"
+#define ICC_IAR1 "p15, 0, %0, c12, c12, 0"
+#define ICC_EOIR0 "p15, 0, %0, c12, c8, 1"
+#define ICC_EOIR1 "p15, 0, %0, c12, c12, 1"
+#define ICC_HPPIR0 "p15, 0, %0, c12, c8, 2"
+#define ICC_HPPIR1 "p15, 0, %0, c12, c12, 2"
+#define ICC_BPR0 "p15, 0, %0, c12, c8, 3"
+#define ICC_BPR1 "p15, 0, %0, c12, c12, 3"
+#define ICC_DIR "p15, 0, %0, c12, c11, 1"
+#define ICC_PMR "p15, 0, %0, c4, c6, 0"
+#define ICC_RPR "p15, 0, %0, c12, c11, 3"
+#define ICC_CTLR "p15, 0, %0, c12, c12, 4"
+#define ICC_MCTLR "p15, 6, %0, c12, c12, 4"
+#define ICC_SRE "p15, 0, %0, c12, c12, 5"
+#define ICC_HSRE "p15, 4, %0, c12, c9, 5"
+#define ICC_MSRE "p15, 6, %0, c12, c12, 5"
+#define ICC_IGRPEN0 "p15, 0, %0, c12, c12, 6"
+#define ICC_IGRPEN1 "p15, 0, %0, c12, c12, 7"
+#define ICC_MGRPEN1 "p15, 6, %0, c12, c12, 7"
+
+#define __REG32(x) (*((volatile unsigned int*)((rt_uint32_t)x)))
+
+#define ROUTED_TO_ALL (1)
+#define ROUTED_TO_SPEC (0)
+
+/** Macro to access the Distributor Control Register (GICD_CTLR)
+*/
+#define GICD_CTLR_RWP ((unsigned int)1<<31)
+#define GICD_CTLR_E1NWF (1<<7)
+#define GICD_CTLR_DS (1<<6) // 当两种安全模式被同时支持时,可以通过GICD_CTLR.DS==1关闭其中一个,只支持non-secure模式
+#define GICD_CTLR_ARE_NS (1<<5)
+#define GICD_CTLR_ARE_S (1<<4)
+#define GICD_CTLR_ENGRP1S (1<<2) // secure group 1
+#define GICD_CTLR_ENGRP1NS (1<<1) // non-secure group 1
+#define GICD_CTLR_ENGRP0 (1<<0) // group 0
+
+/** Macro to access the Redistributor Control Register (GICR_CTLR)
+*/
+#define GICR_CTLR_UWP (1<<31)
+#define GICR_CTLR_DPG1S (1<<26)
+#define GICR_CTLR_DPG1NS (1<<25)
+#define GICR_CTLR_DPG0 (1<<24)
+#define GICR_CTLR_RWP (1<<3)
+#define GICR_CTLR_IR (1<<2)
+#define GICR_CTLR_CES (1<<1)
+#define GICR_CTLR_EnableLPI (1<<0)
+
+/** Macro to access the Generic Interrupt Controller Interface (GICC)
+*/
+#define GIC_CPU_CTRL(hw_base) __REG32((hw_base) + 0x00U)
+#define GIC_CPU_PRIMASK(hw_base) __REG32((hw_base) + 0x04U)
+#define GIC_CPU_BINPOINT(hw_base) __REG32((hw_base) + 0x08U)
+#define GIC_CPU_INTACK(hw_base) __REG32((hw_base) + 0x0cU)
+#define GIC_CPU_EOI(hw_base) __REG32((hw_base) + 0x10U)
+#define GIC_CPU_RUNNINGPRI(hw_base) __REG32((hw_base) + 0x14U)
+#define GIC_CPU_HIGHPRI(hw_base) __REG32((hw_base) + 0x18U)
+#define GIC_CPU_IIDR(hw_base) __REG32((hw_base) + 0xFCU)
+
+/** Macro to access the Generic Interrupt Controller Distributor (GICD)
+*/
+#define GIC_DIST_CTRL(hw_base) __REG32((hw_base) + 0x000U)
+#define GIC_DIST_TYPE(hw_base) __REG32((hw_base) + 0x004U)
+#define GIC_DIST_IGROUP(hw_base, n) __REG32((hw_base) + 0x080U + ((n)/32U) * 4U)
+#define GIC_DIST_ENABLE_SET(hw_base, n) __REG32((hw_base) + 0x100U + ((n)/32U) * 4U)
+#define GIC_DIST_ENABLE_CLEAR(hw_base, n) __REG32((hw_base) + 0x180U + ((n)/32U) * 4U)
+#define GIC_DIST_PENDING_SET(hw_base, n) __REG32((hw_base) + 0x200U + ((n)/32U) * 4U)
+#define GIC_DIST_PENDING_CLEAR(hw_base, n) __REG32((hw_base) + 0x280U + ((n)/32U) * 4U)
+#define GIC_DIST_ACTIVE_SET(hw_base, n) __REG32((hw_base) + 0x300U + ((n)/32U) * 4U)
+#define GIC_DIST_ACTIVE_CLEAR(hw_base, n) __REG32((hw_base) + 0x380U + ((n)/32U) * 4U)
+#define GIC_DIST_PRI(hw_base, n) __REG32((hw_base) + 0x400U + ((n)/4U) * 4U)
+#define GIC_DIST_TARGET(hw_base, n) __REG32((hw_base) + 0x800U + ((n)/4U) * 4U)
+#define GIC_DIST_CONFIG(hw_base, n) __REG32((hw_base) + 0xc00U + ((n)/16U) * 4U)
+#define GIC_DIST_SOFTINT(hw_base) __REG32((hw_base) + 0xf00U)
+#define GIC_DIST_CPENDSGI(hw_base, n) __REG32((hw_base) + 0xf10U + ((n)/4U) * 4U)
+#define GIC_DIST_SPENDSGI(hw_base, n) __REG32((hw_base) + 0xf20U + ((n)/4U) * 4U)
+#define GIC_DIST_ICPIDR2(hw_base) __REG32((hw_base) + 0xfe8U)
+#define GIC_DIST_IROUTER_LOW(hw_base, n) __REG32((hw_base) + 0x6000U + (n)*8U)
+#define GIC_DIST_IROUTER_HIGH(hw_base, n) __REG32((hw_base) + 0x6000U + (n)*8U + 4)
+
+/* SGI base address is at 64K offset from Redistributor base address */
+#define GIC_RSGI_OFFSET 0x10000
+
+/** Macro to access the Generic Interrupt Controller Redistributor (GICD)
+*/
+#define GIC_RDIST_CTRL(hw_base) __REG32((hw_base) + 0x000U)
+#define GIC_RDIST_IIDR(hw_base) __REG32((hw_base) + 0x004U)
+#define GIC_RDIST_TYPER(hw_base) __REG32((hw_base) + 0x008U)
+#define GIC_RDIST_TSTATUSR(hw_base) __REG32((hw_base) + 0x010U)
+#define GIC_RDIST_WAKER(hw_base) __REG32((hw_base) + 0x014U)
+#define GIC_RDIST_SETLPIR(hw_base) __REG32((hw_base) + 0x040U)
+#define GIC_RDIST_CLRLPIR(hw_base) __REG32((hw_base) + 0x048U)
+#define GIC_RDIST_PROPBASER(hw_base) __REG32((hw_base) + 0x070U)
+#define GIC_RDIST_PENDBASER(hw_base) __REG32((hw_base) + 0x078U)
+#define GIC_RDIST_INVLPIR(hw_base) __REG32((hw_base) + 0x0A0U)
+#define GIC_RDIST_INVALLR(hw_base) __REG32((hw_base) + 0x0B0U)
+#define GIC_RDIST_SYNCR(hw_base) __REG32((hw_base) + 0x0C0U)
+
+#define GIC_RDISTSGI_IGROUPR0(hw_base, n) __REG32((hw_base) + GIC_RSGI_OFFSET + 0x080U + (n)*4U)
+#define GIC_RDISTSGI_ISENABLER0(hw_base) __REG32((hw_base) + GIC_RSGI_OFFSET + 0x100U)
+#define GIC_RDISTSGI_ICENABLER0(hw_base) __REG32((hw_base) + GIC_RSGI_OFFSET + 0x180U)
+#define GIC_RDISTSGI_ISPENDR0(hw_base) __REG32((hw_base) + GIC_RSGI_OFFSET + 0x200U)
+#define GIC_RDISTSGI_ICPENDR0(hw_base) __REG32((hw_base) + GIC_RSGI_OFFSET + 0x280U)
+#define GIC_RDISTSGI_ISACTIVER0(hw_base) __REG32((hw_base) + GIC_RSGI_OFFSET + 0x300U)
+#define GIC_RDISTSGI_ICACTIVER0(hw_base) __REG32((hw_base) + GIC_RSGI_OFFSET + 0x380U)
+#define GIC_RDISTSGI_IPRIORITYR(hw_base, n) __REG32((hw_base) + GIC_RSGI_OFFSET + 0x400U + ((n) / 4U) * 4U)
+#define GIC_RDISTSGI_ICFGR0(hw_base) __REG32((hw_base) + GIC_RSGI_OFFSET + 0xC00U)
+#define GIC_RDISTSGI_ICFGR1(hw_base) __REG32((hw_base) + GIC_RSGI_OFFSET + 0xC04U)
+#define GIC_RDISTSGI_IGRPMODR0(hw_base, n) __REG32((hw_base) + GIC_RSGI_OFFSET + 0xD00U + (n)*4)
+#define GIC_RDISTSGI_NSACR(hw_base) __REG32((hw_base) + GIC_RSGI_OFFSET + 0xE00U) // 当执行一个非安全模式到安全模式的访问
+
+#define GIC_RSGI_AFF1_OFFSET 16
+#define GIC_RSGI_AFF2_OFFSET 32
+#define GIC_RSGI_AFF3_OFFSET 48
+
+rt_uint32_t arm_gic_cpumask_to_affval(rt_uint32_t *cpu_mask, rt_uint32_t *cluster_id, rt_uint32_t *target_list);
+rt_uint64_t get_main_cpu_affval(void);
+int arm_gic_get_active_irq(rt_uint32_t index);
+void arm_gic_ack(rt_uint32_t index, int irq);
+
+void arm_gic_mask(rt_uint32_t index, int irq);
+void arm_gic_umask(rt_uint32_t index, int irq);
+
+rt_uint32_t arm_gic_get_pending_irq(rt_uint32_t index, int irq);
+void arm_gic_set_pending_irq(rt_uint32_t index, int irq);
+void arm_gic_clear_pending_irq(rt_uint32_t index, int irq);
+
+void arm_gic_set_configuration(rt_uint32_t index, int irq, rt_uint32_t config);
+rt_uint32_t arm_gic_get_configuration(rt_uint32_t index, int irq);
+
+void arm_gic_clear_active(rt_uint32_t index, int irq);
+
+void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask);
+rt_uint32_t arm_gic_get_target_cpu(rt_uint32_t index, int irq);
+
+void arm_gic_set_priority(rt_uint32_t index, int irq, rt_uint32_t priority);
+rt_uint32_t arm_gic_get_priority(rt_uint32_t index, int irq);
+
+void arm_gic_set_interface_prior_mask(rt_uint32_t index, rt_uint32_t priority);
+rt_uint32_t arm_gic_get_interface_prior_mask(rt_uint32_t index);
+
+void arm_gic_set_binary_point(rt_uint32_t index, rt_uint32_t binary_point);
+rt_uint32_t arm_gic_get_binary_point(rt_uint32_t index);
+
+rt_uint32_t arm_gic_get_irq_status(rt_uint32_t index, int irq);
+
+rt_uint32_t arm_gic_get_high_pending_irq(rt_uint32_t index);
+
+rt_uint32_t arm_gic_get_interface_id(rt_uint32_t index);
+
+void arm_gic_set_group(rt_uint32_t index, int irq, rt_uint32_t group);
+rt_uint32_t arm_gic_get_group(rt_uint32_t index, int irq);
+
+int arm_gic_redist_address_set(rt_uint32_t index, rt_uint32_t redist_addr, rt_uint32_t cpu_id);
+int arm_gic_cpu_interface_address_set(rt_uint32_t index, rt_uint32_t interface_addr, rt_uint32_t cpu_id);
+int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start);
+int arm_gic_cpu_init(rt_uint32_t index);
+int arm_gic_redist_init(rt_uint32_t index);
+
+void arm_gic_dump_type(rt_uint32_t index);
+void arm_gic_dump(rt_uint32_t index);
+
+void arm_gic_set_system_register_enable_mask(rt_uint32_t index, rt_uint32_t value);
+rt_uint32_t arm_gic_get_system_register_enable_mask(rt_uint32_t index);
+void arm_gic_secondary_cpu_init(void);
+
+void assemb_dsb_func();
+void assemb_isb_func();
+
+#endif
+
diff --git a/libcpu/arm/cortex-r52/interrupt.c b/libcpu/arm/cortex-r52/interrupt.c
new file mode 100644
index 0000000000..919a8bca51
--- /dev/null
+++ b/libcpu/arm/cortex-r52/interrupt.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2013-07-06 Bernard first version
+ * 2018-11-22 Jesven add smp support
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include "interrupt.h"
+
+#include "gicv3.h"
+
+/* exception and interrupt handler table */
+struct rt_irq_desc isr_table[MAX_HANDLERS];
+
+#ifndef RT_USING_SMP
+/* Those varibles will be accessed in ISR, so we need to share them. */
+rt_uint32_t rt_interrupt_from_thread = 0;
+rt_uint32_t rt_interrupt_to_thread = 0;
+rt_uint32_t rt_thread_switch_interrupt_flag = 0;
+
+#ifdef RT_USING_HOOK
+static void (*rt_interrupt_switch_hook)(void);
+
+void rt_interrupt_switch_sethook(void (*hook)(void))
+{
+ rt_interrupt_switch_hook = hook;
+}
+#endif
+
+void rt_interrupt_hook(void)
+{
+ RT_OBJECT_HOOK_CALL(rt_interrupt_switch_hook, ());
+}
+#endif
+
+const unsigned int VECTOR_BASE = 0x00;
+extern void rt_cpu_vector_set_base(unsigned int addr);
+extern int system_vectors;
+
+void rt_hw_vector_init(void)
+{
+ rt_cpu_vector_set_base((unsigned int)&system_vectors);
+}
+
+/**
+ * This function will initialize hardware interrupt
+ * Called by the primary cpu(cpu0)
+ */
+void rt_hw_interrupt_init(void)
+{
+ rt_uint32_t gic_dist_base;
+ rt_uint32_t gic_irq_start;
+
+ /* initialize vector table */
+ /* rt_hw_vector_init(); */
+
+ /* initialize exceptions table */
+ rt_memset(isr_table, 0x00, sizeof(isr_table));
+
+ /* initialize ARM GIC */
+ gic_dist_base = platform_get_gic_dist_base();
+ gic_irq_start = GIC_IRQ_START;
+
+ arm_gic_dist_init(0, gic_dist_base, gic_irq_start);
+
+ arm_gic_cpu_init(0);
+ arm_gic_redist_init(0);
+}
+
+/**
+ * This function will mask a interrupt.
+ * @param vector the interrupt number
+ */
+void rt_hw_interrupt_mask(int vector)
+{
+ arm_gic_mask(0, vector);
+}
+
+/**
+ * This function will un-mask a interrupt.
+ * @param vector the interrupt number
+ */
+void rt_hw_interrupt_umask(int vector)
+{
+ arm_gic_umask(0, vector);
+}
+
+/**
+ * This function returns the active interrupt number.
+ * @param none
+ */
+int rt_hw_interrupt_get_irq(void)
+{
+ return arm_gic_get_active_irq(0);
+}
+
+/**
+ * This function acknowledges the interrupt.
+ * @param vector the interrupt number
+ */
+void rt_hw_interrupt_ack(int vector)
+{
+ arm_gic_ack(0, vector);
+}
+
+/**
+ * This function set interrupt CPU targets.
+ * @param vector: the interrupt number
+ * cpu_mask: target cpus mask, one bit for one core
+ */
+void rt_hw_interrupt_set_target_cpus(int vector, unsigned int cpu_mask)
+{
+ arm_gic_set_cpu(0, vector, cpu_mask);
+}
+
+/**
+ * This function get interrupt CPU targets.
+ * @param vector: the interrupt number
+ * @return target cpus mask, one bit for one core
+ */
+unsigned int rt_hw_interrupt_get_target_cpus(int vector)
+{
+ return arm_gic_get_target_cpu(0, vector);
+}
+
+/**
+ * This function set interrupt triger mode.
+ * @param vector: the interrupt number
+ * mode: interrupt triger mode; 0: level triger, 1: edge triger
+ */
+void rt_hw_interrupt_set_triger_mode(int vector, unsigned int mode)
+{
+ arm_gic_set_configuration(0, vector, mode);
+}
+
+/**
+ * This function get interrupt triger mode.
+ * @param vector: the interrupt number
+ * @return interrupt triger mode; 0: level triger, 1: edge triger
+ */
+unsigned int rt_hw_interrupt_get_triger_mode(int vector)
+{
+ return arm_gic_get_configuration(0, vector);
+}
+
+/**
+ * This function set interrupt pending flag.
+ * @param vector: the interrupt number
+ */
+void rt_hw_interrupt_set_pending(int vector)
+{
+ arm_gic_set_pending_irq(0, vector);
+}
+
+/**
+ * This function get interrupt pending flag.
+ * @param vector: the interrupt number
+ * @return interrupt pending flag, 0: not pending; 1: pending
+ */
+unsigned int rt_hw_interrupt_get_pending(int vector)
+{
+ return arm_gic_get_pending_irq(0, vector);
+}
+
+/**
+ * This function clear interrupt pending flag.
+ * @param vector: the interrupt number
+ */
+void rt_hw_interrupt_clear_pending(int vector)
+{
+ arm_gic_clear_pending_irq(0, vector);
+}
+
+/**
+ * This function set interrupt priority value.
+ * @param vector: the interrupt number
+ * priority: the priority of interrupt to set
+ */
+void rt_hw_interrupt_set_priority(int vector, unsigned int priority)
+{
+ arm_gic_set_priority(0, vector, priority);
+}
+
+/**
+ * This function get interrupt priority.
+ * @param vector: the interrupt number
+ * @return interrupt priority value
+ */
+unsigned int rt_hw_interrupt_get_priority(int vector)
+{
+ return arm_gic_get_priority(0, vector);
+}
+
+/**
+ * This function set priority masking threshold.
+ * @param priority: priority masking threshold
+ */
+void rt_hw_interrupt_set_priority_mask(unsigned int priority)
+{
+ arm_gic_set_interface_prior_mask(0, priority);
+}
+
+/**
+ * This function get priority masking threshold.
+ * @param none
+ * @return priority masking threshold
+ */
+unsigned int rt_hw_interrupt_get_priority_mask(void)
+{
+ return arm_gic_get_interface_prior_mask(0);
+}
+
+/**
+ * This function set priority grouping field split point.
+ * @param bits: priority grouping field split point
+ * @return 0: success; -1: failed
+ */
+int rt_hw_interrupt_set_prior_group_bits(unsigned int bits)
+{
+ int status;
+
+ if (bits < 8)
+ {
+ arm_gic_set_binary_point(0, (7 - bits));
+ status = 0;
+ }
+ else
+ {
+ status = -1;
+ }
+
+ return (status);
+}
+
+/**
+ * This function get priority grouping field split point.
+ * @param none
+ * @return priority grouping field split point
+ */
+unsigned int rt_hw_interrupt_get_prior_group_bits(void)
+{
+ unsigned int bp;
+
+ bp = arm_gic_get_binary_point(0) & 0x07;
+
+ return (7 - bp);
+}
+
+/**
+ * This function will install a interrupt service routine to a interrupt.
+ * @param vector the interrupt number
+ * @param new_handler the interrupt service routine to be installed
+ * @param old_handler the old interrupt service routine
+ */
+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 < MAX_HANDLERS)
+ {
+ old_handler = isr_table[vector].handler;
+
+ if (handler != RT_NULL)
+ {
+#ifdef RT_USING_INTERRUPT_INFO
+ rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
+#endif /* RT_USING_INTERRUPT_INFO */
+ isr_table[vector].handler = handler;
+ isr_table[vector].param = param;
+ }
+ }
+
+ return old_handler;
+}
+
diff --git a/libcpu/arm/cortex-r52/interrupt.h b/libcpu/arm/cortex-r52/interrupt.h
new file mode 100644
index 0000000000..804943ea96
--- /dev/null
+++ b/libcpu/arm/cortex-r52/interrupt.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2013-07-06 Bernard first version
+ */
+
+#ifndef __INTERRUPT_H__
+#define __INTERRUPT_H__
+
+#include <rthw.h>
+
+#define INT_IRQ 0x00
+#define INT_FIQ 0x01
+
+#define IRQ_MODE_TRIG_LEVEL (0x00) /* Trigger: level triggered interrupt */
+#define IRQ_MODE_TRIG_EDGE (0x01) /* Trigger: edge triggered interrupt */
+
+void rt_hw_vector_init(void);
+
+void rt_hw_interrupt_init(void);
+void rt_hw_interrupt_mask(int vector);
+void rt_hw_interrupt_umask(int vector);
+
+int rt_hw_interrupt_get_irq(void);
+void rt_hw_interrupt_ack(int vector);
+
+void rt_hw_interrupt_set_target_cpus(int vector, unsigned int cpu_mask);
+unsigned int rt_hw_interrupt_get_target_cpus(int vector);
+
+void rt_hw_interrupt_set_triger_mode(int vector, unsigned int mode);
+unsigned int rt_hw_interrupt_get_triger_mode(int vector);
+
+void rt_hw_interrupt_set_pending(int vector);
+unsigned int rt_hw_interrupt_get_pending(int vector);
+void rt_hw_interrupt_clear_pending(int vector);
+
+void rt_hw_interrupt_set_priority(int vector, unsigned int priority);
+unsigned int rt_hw_interrupt_get_priority(int vector);
+
+void rt_hw_interrupt_set_priority_mask(unsigned int priority);
+unsigned int rt_hw_interrupt_get_priority_mask(void);
+
+int rt_hw_interrupt_set_prior_group_bits(unsigned int bits);
+unsigned int rt_hw_interrupt_get_prior_group_bits(void);
+
+rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
+ void *param, const char *name);
+
+#endif
+
diff --git a/libcpu/arm/cortex-r52/stack.c b/libcpu/arm/cortex-r52/stack.c
new file mode 100644
index 0000000000..540eb7146d
--- /dev/null
+++ b/libcpu/arm/cortex-r52/stack.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011-2024, Shanghai Real-Thread Electronic Technology Co.,Ltd
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-08-29 RT-Thread first version
+ */
+
+#include "armv8.h"
+#include <rtthread.h>
+//#include <board.h>
+
+/**
+ * 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 */
+
+#ifdef RT_USING_OSA
+ *(--stk) = 0; /* user lr */
+ *(--stk) = 0; /* user sp*/
+#endif
+#ifdef RT_USING_FPU
+ *(--stk) = 0; /* not use fpu*/
+#endif
+
+ /* return task's current stack address */
+ return (rt_uint8_t *)stk;
+}
+
+/*@}*/
diff --git a/libcpu/arm/cortex-r52/start_ccs.asm b/libcpu/arm/cortex-r52/start_ccs.asm
new file mode 100644
index 0000000000..4436646543
--- /dev/null
+++ b/libcpu/arm/cortex-r52/start_ccs.asm
@@ -0,0 +1,552 @@
+;-------------------------------------------------------------------------------
+; sys_core.asm
+;
+; (c) Texas Instruments 2009-2013, All rights reserved.
+;
+
+ .text
+ .arm
+
+ .ref _c_int00
+
+ .def _reset
+ .asmfunc
+_reset
+;-------------------------------------------------------------------------------
+; Initialize CPU Registers
+; After reset, the CPU is in the Supervisor mode (M = 10011)
+ mov r0, lr
+ mov r1, #0x0000
+ mov r2, #0x0000
+ mov r3, #0x0000
+ mov r4, #0x0000
+ mov r5, #0x0000
+ mov r6, #0x0000
+ mov r7, #0x0000
+ mov r8, #0x0000
+ mov r9, #0x0000
+ mov r10, #0x0000
+ mov r11, #0x0000
+ mov r12, #0x0000
+ mov r13, #0x0000
+ mrs r1, cpsr
+ msr spsr_cxsf, r1
+ ; Switch to FIQ mode (M = 10001)
+ cps #17
+ mov lr, r0
+ mov r8, #0x0000
+ mov r9, #0x0000
+ mov r10, #0x0000
+ mov r11, #0x0000
+ mov r12, #0x0000
+ mrs r1, cpsr
+ msr spsr_cxsf, r1
+ ; Switch to IRQ mode (M = 10010)
+ cps #18
+ mov lr, r0
+ mrs r1,cpsr
+ msr spsr_cxsf, r1
+ ; Switch to Abort mode (M = 10111)
+ cps #23
+ mov lr, r0
+ mrs r1,cpsr
+ msr spsr_cxsf, r1
+ ; Switch to Undefined Instruction Mode (M = 11011)
+ cps #27
+ mov lr, r0
+ mrs r1,cpsr
+ msr spsr_cxsf, r1
+ ; Switch to System Mode ( Shares User Mode registers ) (M = 11111)
+ cps #31
+ mov lr, r0
+ mrs r1,cpsr
+ msr spsr_cxsf, r1
+ ; Switch back to Supervisor Mode (M = 10011)
+ cps #19
+
+ ; Turn on FPV coprocessor
+ mrc p15, #0x00, r2, c1, c0, #0x02
+ orr r2, r2, #0xF00000
+ mcr p15, #0x00, r2, c1, c0, #0x02
+
+ .if (RT_VFP_LAZY_STACKING) = 0
+ fmrx r2, fpexc
+ orr r2, r2, #0x40000000
+ fmxr fpexc, r2
+
+ fmdrr d0, r1, r1
+ fmdrr d1, r1, r1
+ fmdrr d2, r1, r1
+ fmdrr d3, r1, r1
+ fmdrr d4, r1, r1
+ fmdrr d5, r1, r1
+ fmdrr d6, r1, r1
+ fmdrr d7, r1, r1
+ fmdrr d8, r1, r1
+ fmdrr d9, r1, r1
+ fmdrr d10, r1, r1
+ fmdrr d11, r1, r1
+ fmdrr d12, r1, r1
+ fmdrr d13, r1, r1
+ fmdrr d14, r1, r1
+ fmdrr d15, r1, r1
+ .endif
+
+;-------------------------------------------------------------------------------
+; Initialize Stack Pointers
+ cps #17
+ ldr sp, fiqSp
+ cps #18
+ ldr sp, irqSp
+ cps #23
+ ldr sp, abortSp
+ cps #27
+ ldr sp, undefSp
+ cps #31
+ ldr sp, userSp
+ cps #19
+ ldr sp, svcSp
+
+ bl next1
+next1
+ bl next2
+next2
+ bl next3
+next3
+ bl next4
+next4
+ ldr lr, int00ad
+ bx lr
+
+int00ad .word _c_int00
+userSp .word 0x08000000+0x00001000
+svcSp .word 0x08000000+0x00001000+0x00000100
+fiqSp .word 0x08000000+0x00001000+0x00000100+0x00000100
+irqSp .word 0x08000000+0x00001000+0x00000100+0x00000100+0x00000100
+abortSp .word 0x08000000+0x00001000+0x00000100+0x00000100+0x00000100+0x00000100
+undefSp .word 0x08000000+0x00001000+0x00000100+0x00000100+0x00000100+0x00000100+0x00000100
+
+ .endasmfunc
+
+;-------------------------------------------------------------------------------
+; Enable RAM ECC Support
+
+ .def _coreEnableRamEcc_
+ .asmfunc
+
+_coreEnableRamEcc_
+
+ stmfd sp!, {r0}
+ mrc p15, #0x00, r0, c1, c0, #0x01
+ orr r0, r0, #0x0C000000
+ mcr p15, #0x00, r0, c1, c0, #0x01
+ ldmfd sp!, {r0}
+ bx lr
+
+ .endasmfunc
+
+
+;-------------------------------------------------------------------------------
+; Disable RAM ECC Support
+
+ .def _coreDisableRamEcc_
+ .asmfunc
+
+_coreDisableRamEcc_
+
+ stmfd sp!, {r0}
+ mrc p15, #0x00, r0, c1, c0, #0x01
+ bic r0, r0, #0x0C000000
+ mcr p15, #0x00, r0, c1, c0, #0x01
+ ldmfd sp!, {r0}
+ bx lr
+
+ .endasmfunc
+
+
+;-------------------------------------------------------------------------------
+; Enable Flash ECC Support
+
+ .def _coreEnableFlashEcc_
+ .asmfunc
+
+_coreEnableFlashEcc_
+
+ stmfd sp!, {r0}
+ mrc p15, #0x00, r0, c1, c0, #0x01
+ orr r0, r0, #0x02000000
+ dmb
+ mcr p15, #0x00, r0, c1, c0, #0x01
+ ldmfd sp!, {r0}
+ bx lr
+
+ .endasmfunc
+
+
+;-------------------------------------------------------------------------------
+; Disable Flash ECC Support
+
+ .def _coreDisableFlashEcc_
+ .asmfunc
+
+_coreDisableFlashEcc_
+
+ stmfd sp!, {r0}
+ mrc p15, #0x00, r0, c1, c0, #0x01
+ bic r0, r0, #0x02000000
+ mcr p15, #0x00, r0, c1, c0, #0x01
+ ldmfd sp!, {r0}
+ bx lr
+
+ .endasmfunc
+
+;-------------------------------------------------------------------------------
+; Get data fault status register
+
+ .def _coreGetDataFault_
+ .asmfunc
+
+_coreGetDataFault_
+
+ mrc p15, #0, r0, c5, c0, #0
+ bx lr
+
+ .endasmfunc
+
+
+;-------------------------------------------------------------------------------
+; Clear data fault status register
+
+ .def _coreClearDataFault_
+ .asmfunc
+
+_coreClearDataFault_
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c5, c0, #0
+ ldmfd sp!, {r0}
+ bx lr
+
+ .endasmfunc
+
+
+;-------------------------------------------------------------------------------
+; Get instruction fault status register
+
+ .def _coreGetInstructionFault_
+ .asmfunc
+
+_coreGetInstructionFault_
+
+ mrc p15, #0, r0, c5, c0, #1
+ bx lr
+
+ .endasmfunc
+
+
+;-------------------------------------------------------------------------------
+; Clear instruction fault status register
+
+ .def _coreClearInstructionFault_
+ .asmfunc
+
+_coreClearInstructionFault_
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c5, c0, #1
+ ldmfd sp!, {r0}
+ bx lr
+
+ .endasmfunc
+
+
+;-------------------------------------------------------------------------------
+; Get data fault address register
+
+ .def _coreGetDataFaultAddress_
+ .asmfunc
+
+_coreGetDataFaultAddress_
+
+ mrc p15, #0, r0, c6, c0, #0
+ bx lr
+
+ .endasmfunc
+
+
+;-------------------------------------------------------------------------------
+; Clear data fault address register
+
+ .def _coreClearDataFaultAddress_
+ .asmfunc
+
+_coreClearDataFaultAddress_
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c6, c0, #0
+ ldmfd sp!, {r0}
+ bx lr
+
+ .endasmfunc
+
+
+;-------------------------------------------------------------------------------
+; Get instruction fault address register
+
+ .def _coreGetInstructionFaultAddress_
+ .asmfunc
+
+_coreGetInstructionFaultAddress_
+
+ mrc p15, #0, r0, c6, c0, #2
+ bx lr
+
+ .endasmfunc
+
+
+;-------------------------------------------------------------------------------
+; Clear instruction fault address register
+
+ .def _coreClearInstructionFaultAddress_
+ .asmfunc
+
+_coreClearInstructionFaultAddress_
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c6, c0, #2
+ ldmfd sp!, {r0}
+ bx lr
+
+ .endasmfunc
+
+
+;-------------------------------------------------------------------------------
+; Get auxiliary data fault status register
+
+ .def _coreGetAuxiliaryDataFault_
+ .asmfunc
+
+_coreGetAuxiliaryDataFault_
+
+ mrc p15, #0, r0, c5, c1, #0
+ bx lr
+
+ .endasmfunc
+
+
+;-------------------------------------------------------------------------------
+; Clear auxiliary data fault status register
+
+ .def _coreClearAuxiliaryDataFault_
+ .asmfunc
+
+_coreClearAuxiliaryDataFault_
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c5, c1, #0
+ ldmfd sp!, {r0}
+ bx lr
+
+ .endasmfunc
+
+
+;-------------------------------------------------------------------------------
+; Get auxiliary instruction fault status register
+
+ .def _coreGetAuxiliaryInstructionFault_
+ .asmfunc
+
+_coreGetAuxiliaryInstructionFault_
+
+ mrc p15, #0, r0, c5, c1, #1
+ bx lr
+
+ .endasmfunc
+
+;-------------------------------------------------------------------------------
+; Clear auxiliary instruction fault status register
+
+ .def _coreClearAuxiliaryInstructionFault_
+ .asmfunc
+
+_coreClearAuxiliaryInstructionFault_
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mrc p15, #0, r0, c5, c1, #1
+ ldmfd sp!, {r0}
+ bx lr
+
+ .endasmfunc
+
+;-------------------------------------------------------------------------------
+; Clear ESM CCM errorss
+
+ .def _esmCcmErrorsClear_
+ .asmfunc
+
+_esmCcmErrorsClear_
+
+ stmfd sp!, {r0-r2}
+ ldr r0, ESMSR1_REG ; load the ESMSR1 status register address
+ ldr r2, ESMSR1_ERR_CLR
+ str r2, [r0] ; clear the ESMSR1 register
+
+ ldr r0, ESMSR2_REG ; load the ESMSR2 status register address
+ ldr r2, ESMSR2_ERR_CLR
+ str r2, [r0] ; clear the ESMSR2 register
+
+ ldr r0, ESMSSR2_REG ; load the ESMSSR2 status register address
+ ldr r2, ESMSSR2_ERR_CLR
+ str r2, [r0] ; clear the ESMSSR2 register
+
+ ldr r0, ESMKEY_REG ; load the ESMKEY register address
+ mov r2, #0x5 ; load R2 with 0x5
+ str r2, [r0] ; clear the ESMKEY register
+
+ ldr r0, VIM_INTREQ ; load the INTREQ register address
+ ldr r2, VIM_INT_CLR
+ str r2, [r0] ; clear the INTREQ register
+ ldr r0, CCMR4_STAT_REG ; load the CCMR4 status register address
+ ldr r2, CCMR4_ERR_CLR
+ str r2, [r0] ; clear the CCMR4 status register
+ ldmfd sp!, {r0-r2}
+ bx lr
+
+ESMSR1_REG .word 0xFFFFF518
+ESMSR2_REG .word 0xFFFFF51C
+ESMSR3_REG .word 0xFFFFF520
+ESMKEY_REG .word 0xFFFFF538
+ESMSSR2_REG .word 0xFFFFF53C
+CCMR4_STAT_REG .word 0xFFFFF600
+ERR_CLR_WRD .word 0xFFFFFFFF
+CCMR4_ERR_CLR .word 0x00010000
+ESMSR1_ERR_CLR .word 0x80000000
+ESMSR2_ERR_CLR .word 0x00000004
+ESMSSR2_ERR_CLR .word 0x00000004
+VIM_INT_CLR .word 0x00000001
+VIM_INTREQ .word 0xFFFFFE20
+
+ .endasmfunc
+
+;-------------------------------------------------------------------------------
+; Work Around for Errata CORTEX-R4#57:
+;
+; Errata Description:
+; Conditional VMRS APSR_Nzcv, FPSCR May Evaluate With Incorrect Flags
+; Workaround:
+; Disable out-of-order single-precision floating point
+; multiply-accumulate instruction completion
+
+ .def _errata_CORTEXR4_57_
+ .asmfunc
+
+_errata_CORTEXR4_57_
+
+ push {r0}
+ mrc p15, #0, r0, c15, c0, #0 ; Read Secondary Auxiliary Control Register
+ orr r0, r0, #0x10000 ; Set BIT 16 (Set DOOFMACS)
+ mcr p15, #0, r0, c15, c0, #0 ; Write Secondary Auxiliary Control Register
+ pop {r0}
+ bx lr
+ .endasmfunc
+
+;-------------------------------------------------------------------------------
+; Work Around for Errata CORTEX-R4#66:
+;
+; Errata Description:
+; Register Corruption During A Load-Multiple Instruction At
+; an Exception Vector
+; Workaround:
+; Disable out-of-order completion for divide instructions in
+; Auxiliary Control register
+
+ .def _errata_CORTEXR4_66_
+ .asmfunc
+
+_errata_CORTEXR4_66_
+
+ push {r0}
+ mrc p15, #0, r0, c1, c0, #1 ; Read Auxiliary Control register
+ orr r0, r0, #0x80 ; Set BIT 7 (Disable out-of-order completion
+ ; for divide instructions.)
+ mcr p15, #0, r0, c1, c0, #1 ; Write Auxiliary Control register
+ pop {r0}
+ bx lr
+ .endasmfunc
+
+ .def turnon_VFP
+ .asmfunc
+turnon_VFP
+ ; Enable FPV
+ STMDB sp!, {r0}
+ fmrx r0, fpexc
+ orr r0, r0, #0x40000000
+ fmxr fpexc, r0
+ LDMIA sp!, {r0}
+ subs pc, lr, #4
+ .endasmfunc
+
+_push_svc_reg .macro
+ sub sp, sp, #17 * 4 ;/* Sizeof(struct rt_hw_exp_stack) */
+ stmia sp, {r0 - r12} ;/* Calling r0-r12 */
+ mov r0, sp
+ mrs r6, spsr ;/* Save CPSR */
+ str lr, [r0, #15*4] ;/* Push PC */
+ str r6, [r0, #16*4] ;/* Push CPSR */
+ cps #0x13
+ str sp, [r0, #13*4] ;/* Save calling SP */
+ str lr, [r0, #14*4] ;/* Save calling PC */
+ .endm
+
+ .ref rt_hw_trap_svc
+ .def vector_svc
+ .asmfunc
+vector_svc:
+ _push_svc_reg
+ bl rt_hw_trap_svc
+ sub pc, pc, #-4
+ .endasmfunc
+
+ .ref rt_hw_trap_pabt
+ .def vector_pabort
+ .asmfunc
+vector_pabort:
+ _push_svc_reg
+ bl rt_hw_trap_pabt
+ sub pc, pc, #-4
+ .endasmfunc
+
+ .ref rt_hw_trap_dabt
+ .def vector_dabort
+ .asmfunc
+vector_dabort:
+ _push_svc_reg
+ bl rt_hw_trap_dabt
+ sub pc, pc, #-4
+ .endasmfunc
+
+ .ref rt_hw_trap_resv
+ .def vector_resv
+ .asmfunc
+vector_resv:
+ _push_svc_reg
+ bl rt_hw_trap_resv
+ sub pc, pc, #-4
+ .endasmfunc
+
+;-------------------------------------------------------------------------------
+; C++ construct table pointers
+
+ .def __TI_PINIT_Base, __TI_PINIT_Limit
+ .weak SHT$$INIT_ARRAY$$Base, SHT$$INIT_ARRAY$$Limit
+
+__TI_PINIT_Base .long SHT$$INIT_ARRAY$$Base
+__TI_PINIT_Limit .long SHT$$INIT_ARRAY$$Limit
+
+;-------------------------------------------------------------------------------
diff --git a/libcpu/arm/cortex-r52/start_gcc.S b/libcpu/arm/cortex-r52/start_gcc.S
new file mode 100644
index 0000000000..787d3e44fb
--- /dev/null
+++ b/libcpu/arm/cortex-r52/start_gcc.S
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ */
+@-------------------------------------------------------------------------------
+@ sys_core.asm
+@
+@ (c) Texas Instruments 2009-2013, All rights reserved.
+@
+
+//#include <rtconfig.h>
+
+.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 I bit is set, IRQ is disabled
+.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled
+
+.equ UND_Stack_Size, 0x00000000
+.equ SVC_Stack_Size, 0x00000000
+.equ ABT_Stack_Size, 0x00000000
+.equ FIQ_Stack_Size, 0x00001000
+.equ IRQ_Stack_Size, 0x00001000
+
+.section .bss.noinit
+/* stack */
+.globl stack_start
+.globl stack_top
+
+.align 3
+stack_start:
+.rept (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + FIQ_Stack_Size + IRQ_Stack_Size)
+.byte 0
+.endr
+stack_top:
+
+.section .text, "ax"
+ .text
+ .arm
+
+ .globl _c_int00
+
+.globl _reset
+_reset:
+@-------------------------------------------------------------------------------
+@ Initialize CPU Registers
+@ After reset, the CPU is in the Supervisor mode (M = 10011)
+ mov r0, #0x0000
+ mov r1, #0x0000
+ mov r2, #0x0000
+ mov r3, #0x0000
+ mov r4, #0x0000
+ mov r5, #0x0000
+ mov r6, #0x0000
+ mov r7, #0x0000
+ mov r8, #0x0000
+ mov r9, #0x0000
+ mov r10, #0x0000
+ mov r11, #0x0000
+ mov r12, #0x0000
+ mov r13, #0x0000
+ mrs r1, cpsr
+ msr spsr_cxsf, r1
+
+ cpsid if, #19
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING)
+ @ Turn on FPV coprocessor
+ mrc p15, #0x00, r2, c1, c0, #0x02
+ orr r2, r2, #0xF00000
+ mcr p15, #0x00, r2, c1, c0, #0x02
+
+ fmrx r2, fpexc
+ orr r2, r2, #0x40000000
+ fmxr fpexc, r2
+#endif
+
+@-------------------------------------------------------------------------------
+@ Initialize Stack Pointers
+ ldr r0, =stack_top
+
+ @ Set the startup stack for svc
+ mov sp, r0
+
+ @ Enter Undefined Instruction Mode and set its Stack Pointer
+ msr cpsr_c, #Mode_UND|I_Bit|F_Bit
+ mov sp, r0
+ sub r0, r0, #UND_Stack_Size
+
+ @ Enter Abort Mode and set its Stack Pointer
+ msr cpsr_c, #Mode_ABT|I_Bit|F_Bit
+ mov sp, r0
+ sub r0, r0, #ABT_Stack_Size
+
+ @ Enter FIQ Mode and set its Stack Pointer
+ msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit
+ mov sp, r0
+ sub r0, r0, #FIQ_Stack_Size
+
+ @ Enter IRQ Mode and set its Stack Pointer
+ msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit
+ mov sp, r0
+ sub r0, r0, #IRQ_Stack_Size
+
+ @ Switch back to SVC
+ msr cpsr_c, #Mode_SVC|I_Bit|F_Bit
+
+ bl next1
+next1:
+ bl next2
+next2:
+ bl next3
+next3:
+ bl next4
+next4:
+ ldr lr, =_c_int00
+ bx lr
+
+.globl data_init
+data_init:
+ /* copy .data to SRAM */
+ ldr r1, =_mdata /* .data start in image */
+ ldr r2, =_data_end /* .data end in image */
+ ldr r3, =_data_start /* 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-r3, ip, lr}
+ mov lr, pc
+ bx r2
+ ldmfd sp!, {r0-r3, ip, lr}
+ b ctor_loop
+ctor_end:
+ bx lr
+
+@-------------------------------------------------------------------------------
+@ Enable RAM ECC Support
+
+ .globl _coreEnableRamEcc_
+_coreEnableRamEcc_:
+
+ stmfd sp!, {r0}
+ mrc p15, #0x00, r0, c1, c0, #0x01
+ orr r0, r0, #0x0C000000
+ mcr p15, #0x00, r0, c1, c0, #0x01
+ ldmfd sp!, {r0}
+ bx lr
+
+@-------------------------------------------------------------------------------
+@ Disable RAM ECC Support
+
+ .globl _coreDisableRamEcc_
+_coreDisableRamEcc_:
+
+ stmfd sp!, {r0}
+ mrc p15, #0x00, r0, c1, c0, #0x01
+ bic r0, r0, #0x0C000000
+ mcr p15, #0x00, r0, c1, c0, #0x01
+ ldmfd sp!, {r0}
+ bx lr
+
+
+@-------------------------------------------------------------------------------
+@ Enable Flash ECC Support
+
+ .globl _coreEnableFlashEcc_
+_coreEnableFlashEcc_:
+
+ stmfd sp!, {r0}
+ mrc p15, #0x00, r0, c1, c0, #0x01
+ orr r0, r0, #0x02000000
+ dmb
+ mcr p15, #0x00, r0, c1, c0, #0x01
+ ldmfd sp!, {r0}
+ bx lr
+
+@-------------------------------------------------------------------------------
+@ Disable Flash ECC Support
+
+ .globl _coreDisableFlashEcc_
+_coreDisableFlashEcc_:
+
+ stmfd sp!, {r0}
+ mrc p15, #0x00, r0, c1, c0, #0x01
+ bic r0, r0, #0x02000000
+ mcr p15, #0x00, r0, c1, c0, #0x01
+ ldmfd sp!, {r0}
+ bx lr
+
+
+@-------------------------------------------------------------------------------
+@ Get data fault status register
+
+ .globl _coreGetDataFault_
+_coreGetDataFault_:
+
+ mrc p15, #0, r0, c5, c0, #0
+ bx lr
+
+
+
+@-------------------------------------------------------------------------------
+@ Clear data fault status register
+
+ .globl _coreClearDataFault_
+_coreClearDataFault_:
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c5, c0, #0
+ ldmfd sp!, {r0}
+ bx lr
+
+
+
+@-------------------------------------------------------------------------------
+@ Get instruction fault status register
+
+ .globl _coreGetInstructionFault_
+_coreGetInstructionFault_:
+
+ mrc p15, #0, r0, c5, c0, #1
+ bx lr
+
+
+
+@-------------------------------------------------------------------------------
+@ Clear instruction fault status register
+
+ .globl _coreClearInstructionFault_
+_coreClearInstructionFault_:
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c5, c0, #1
+ ldmfd sp!, {r0}
+ bx lr
+
+
+
+@-------------------------------------------------------------------------------
+@ Get data fault address register
+
+ .globl _coreGetDataFaultAddress_
+_coreGetDataFaultAddress_:
+
+ mrc p15, #0, r0, c6, c0, #0
+ bx lr
+
+
+
+@-------------------------------------------------------------------------------
+@ Clear data fault address register
+
+ .globl _coreClearDataFaultAddress_
+_coreClearDataFaultAddress_:
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c6, c0, #0
+ ldmfd sp!, {r0}
+ bx lr
+
+
+
+@-------------------------------------------------------------------------------
+@ Get instruction fault address register
+
+ .globl _coreGetInstructionFaultAddress_
+_coreGetInstructionFaultAddress_:
+
+ mrc p15, #0, r0, c6, c0, #2
+ bx lr
+
+
+
+@-------------------------------------------------------------------------------
+@ Clear instruction fault address register
+
+ .globl _coreClearInstructionFaultAddress_
+_coreClearInstructionFaultAddress_:
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c6, c0, #2
+ ldmfd sp!, {r0}
+ bx lr
+
+
+
+@-------------------------------------------------------------------------------
+@ Get auxiliary data fault status register
+
+ .globl _coreGetAuxiliaryDataFault_
+_coreGetAuxiliaryDataFault_:
+
+ mrc p15, #0, r0, c5, c1, #0
+ bx lr
+
+
+
+@-------------------------------------------------------------------------------
+@ Clear auxiliary data fault status register
+
+ .globl _coreClearAuxiliaryDataFault_
+_coreClearAuxiliaryDataFault_:
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c5, c1, #0
+ ldmfd sp!, {r0}
+ bx lr
+
+
+
+@-------------------------------------------------------------------------------
+@ Get auxiliary instruction fault status register
+
+ .globl _coreGetAuxiliaryInstructionFault_
+_coreGetAuxiliaryInstructionFault_:
+
+ mrc p15, #0, r0, c5, c1, #1
+ bx lr
+
+
+@-------------------------------------------------------------------------------
+@ Clear auxiliary instruction fault status register
+
+ .globl _coreClearAuxiliaryInstructionFault_
+_coreClearAuxiliaryInstructionFault_:
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mrc p15, #0, r0, c5, c1, #1
+ ldmfd sp!, {r0}
+ bx lr
+
+
+@-------------------------------------------------------------------------------
+@ Clear ESM CCM errorss
+
+ .globl _esmCcmErrorsClear_
+_esmCcmErrorsClear_:
+
+ stmfd sp!, {r0-r2}
+ ldr r0, ESMSR1_REG @ load the ESMSR1 status register address
+ ldr r2, ESMSR1_ERR_CLR
+ str r2, [r0] @ clear the ESMSR1 register
+
+ ldr r0, ESMSR2_REG @ load the ESMSR2 status register address
+ ldr r2, ESMSR2_ERR_CLR
+ str r2, [r0] @ clear the ESMSR2 register
+
+ ldr r0, ESMSSR2_REG @ load the ESMSSR2 status register address
+ ldr r2, ESMSSR2_ERR_CLR
+ str r2, [r0] @ clear the ESMSSR2 register
+
+ ldr r0, ESMKEY_REG @ load the ESMKEY register address
+ mov r2, #0x5 @ load R2 with 0x5
+ str r2, [r0] @ clear the ESMKEY register
+
+ ldr r0, VIM_INTREQ @ load the INTREQ register address
+ ldr r2, VIM_INT_CLR
+ str r2, [r0] @ clear the INTREQ register
+ ldr r0, CCMR4_STAT_REG @ load the CCMR4 status register address
+ ldr r2, CCMR4_ERR_CLR
+ str r2, [r0] @ clear the CCMR4 status register
+ ldmfd sp!, {r0-r2}
+ bx lr
+
+ESMSR1_REG: .word 0xFFFFF518
+ESMSR2_REG: .word 0xFFFFF51C
+ESMSR3_REG: .word 0xFFFFF520
+ESMKEY_REG: .word 0xFFFFF538
+ESMSSR2_REG: .word 0xFFFFF53C
+CCMR4_STAT_REG: .word 0xFFFFF600
+ERR_CLR_WRD: .word 0xFFFFFFFF
+CCMR4_ERR_CLR: .word 0x00010000
+ESMSR1_ERR_CLR: .word 0x80000000
+ESMSR2_ERR_CLR: .word 0x00000004
+ESMSSR2_ERR_CLR: .word 0x00000004
+VIM_INT_CLR: .word 0x00000001
+VIM_INTREQ: .word 0xFFFFFE20
+
+
+@-------------------------------------------------------------------------------
+@ Work Around for Errata CORTEX-R4#57:
+@
+@ Errata Description:
+@ Conditional VMRS APSR_Nzcv, FPSCR May Evaluate With Incorrect Flags
+@ Workaround:
+@ Disable out-of-order single-precision floating point
+@ multiply-accumulate instruction completion
+
+ .globl _errata_CORTEXR4_57_
+_errata_CORTEXR4_57_:
+
+ push {r0}
+ mrc p15, #0, r0, c15, c0, #0 @ Read Secondary Auxiliary Control Register
+ orr r0, r0, #0x10000 @ Set BIT 16 (Set DOOFMACS)
+ mcr p15, #0, r0, c15, c0, #0 @ Write Secondary Auxiliary Control Register
+ pop {r0}
+ bx lr
+
+@-------------------------------------------------------------------------------
+@ Work Around for Errata CORTEX-R4#66:
+@
+@ Errata Description:
+@ Register Corruption During A Load-Multiple Instruction At
+@ an Exception Vector
+@ Workaround:
+@ Disable out-of-order completion for divide instructions in
+@ Auxiliary Control register
+
+ .globl _errata_CORTEXR4_66_
+_errata_CORTEXR4_66_:
+
+ push {r0}
+ mrc p15, #0, r0, c1, c0, #1 @ Read Auxiliary Control register
+ orr r0, r0, #0x80 @ Set BIT 7 (Disable out-of-order completion
+ @ for divide instructions.)
+ mcr p15, #0, r0, c1, c0, #1 @ Write Auxiliary Control register
+ pop {r0}
+ bx lr
+
+ .globl turnon_VFP
+turnon_VFP:
+ @ Enable FPV
+ STMDB sp!, {r0}
+ fmrx r0, fpexc
+ orr r0, r0, #0x40000000
+ fmxr fpexc, r0
+ LDMIA sp!, {r0}
+ subs pc, lr, #4
+
+ .macro push_svc_reg
+ sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */
+ stmia sp, {r0 - r12} @/* Calling r0-r12 */
+ mov r0, sp
+ mrs r6, spsr @/* Save CPSR */
+ str lr, [r0, #15*4] @/* Push PC */
+ str r6, [r0, #16*4] @/* Push CPSR */
+ cps #Mode_SVC
+ str sp, [r0, #13*4] @/* Save calling SP */
+ str lr, [r0, #14*4] @/* Save calling PC */
+ .endm
+
+ .globl vector_svc
+vector_svc:
+ push_svc_reg
+ bl rt_hw_trap_svc
+ b .
+
+ .globl vector_pabort
+vector_pabort:
+ push_svc_reg
+ bl rt_hw_trap_pabt
+ b .
+
+ .globl vector_dabort
+vector_dabort:
+ push_svc_reg
+ bl rt_hw_trap_dabt
+ b .
+
+ .globl vector_resv
+vector_resv:
+ push_svc_reg
+ bl rt_hw_trap_resv
+ b .
diff --git a/libcpu/arm/cortex-r52/start_iar.S b/libcpu/arm/cortex-r52/start_iar.S
new file mode 100644
index 0000000000..9e110dd152
--- /dev/null
+++ b/libcpu/arm/cortex-r52/start_iar.S
@@ -0,0 +1,334 @@
+;/*
+; * Copyright (c) 2006-2022, RT-Thread Development Team
+; *
+; * SPDX-License-Identifier: Apache-2.0
+; *
+; * Change Logs:
+; * Date Author Notes
+; * 2024-03-11 Wangyuqiang first version
+; */
+;@-------------------------------------------------------------------------------
+;@ sys_core.asm
+;@
+;@ (c) Texas Instruments 2009-2013, All rights reserved.
+;@
+
+; Constants
+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
+F_Bit EQU 0x40
+
+UND_Stack_Size EQU 0x00000000
+SVC_Stack_Size EQU 0x00000000
+ABT_Stack_Size EQU 0x00000000
+FIQ_Stack_Size EQU 0x00001000
+IRQ_Stack_Size EQU 0x00001000
+
+ IMPORT _c_int00
+ IMPORT rt_hw_trap_svc
+ IMPORT rt_hw_trap_pabt
+ IMPORT rt_hw_trap_dabt
+ IMPORT rt_hw_trap_resv
+ IMPORT system_init
+ IMPORT __iar_program_start
+
+; Define sections
+ SECTION .text:CODE:REORDER:NOROOT(2)
+
+ ; Define stack start and top
+ EXPORT stack_start
+ EXPORT stack_top
+
+ ; Align stack start to a 4-byte boundary (32-bit word)
+ ALIGNRAM 5
+stack_start:
+ ; Reserve stack memory
+ REPT (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + FIQ_Stack_Size + IRQ_Stack_Size)
+ DCB 0 ; Define a byte of data and clear it to zero
+ ENDR
+
+ ; Define stack top label
+stack_top:
+
+; Define code section
+ SECTION .text:CODE:REORDER:NOROOT(2)
+
+ ; Specify ARM mode
+ THUMB
+
+;@-------------------------------------------------------------------------------
+;@ Enable RAM ECC Support
+
+ EXPORT _coreEnableRamEcc_
+_coreEnableRamEcc_:
+
+ stmfd sp!, {r0}
+ mrc p15, #0x00, r0, c1, c0, #0x01
+ orr r0, r0, #0x0C000000
+ mcr p15, #0x00, r0, c1, c0, #0x01
+ ldmfd sp!, {r0}
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Disable RAM ECC Support
+
+ EXPORT _coreDisableRamEcc_
+_coreDisableRamEcc_:
+
+ stmfd sp!, {r0}
+ mrc p15, #0x00, r0, c1, c0, #0x01
+ bic r0, r0, #0x0C000000
+ mcr p15, #0x00, r0, c1, c0, #0x01
+ ldmfd sp!, {r0}
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Enable Flash ECC Support
+
+ EXPORT _coreEnableFlashEcc_
+_coreEnableFlashEcc_:
+
+ stmfd sp!, {r0}
+ mrc p15, #0x00, r0, c1, c0, #0x01
+ orr r0, r0, #0x02000000
+ dmb
+ mcr p15, #0x00, r0, c1, c0, #0x01
+ ldmfd sp!, {r0}
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Disable Flash ECC Support
+
+ EXPORT _coreDisableFlashEcc_
+_coreDisableFlashEcc_:
+
+ stmfd sp!, {r0}
+ mrc p15, #0x00, r0, c1, c0, #0x01
+ bic r0, r0, #0x02000000
+ mcr p15, #0x00, r0, c1, c0, #0x01
+ ldmfd sp!, {r0}
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Get data fault status register
+
+ EXPORT _coreGetDataFault_
+_coreGetDataFault_:
+
+ mrc p15, #0, r0, c5, c0, #0
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Clear data fault status register
+
+ EXPORT _coreClearDataFault_
+_coreClearDataFault_:
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c5, c0, #0
+ ldmfd sp!, {r0}
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Get instruction fault status register
+
+ EXPORT _coreGetInstructionFault_
+_coreGetInstructionFault_:
+
+ mrc p15, #0, r0, c5, c0, #1
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Clear instruction fault status register
+
+ EXPORT _coreClearInstructionFault_
+_coreClearInstructionFault_:
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c5, c0, #1
+ ldmfd sp!, {r0}
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Get data fault address register
+
+ EXPORT _coreGetDataFaultAddress_
+_coreGetDataFaultAddress_:
+
+ mrc p15, #0, r0, c6, c0, #0
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Clear data fault address register
+
+ EXPORT _coreClearDataFaultAddress_
+_coreClearDataFaultAddress_:
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c6, c0, #0
+ ldmfd sp!, {r0}
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Get instruction fault address register
+
+ EXPORT _coreGetInstructionFaultAddress_
+_coreGetInstructionFaultAddress_:
+
+ mrc p15, #0, r0, c6, c0, #2
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Clear instruction fault address register
+
+ EXPORT _coreClearInstructionFaultAddress_
+_coreClearInstructionFaultAddress_:
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c6, c0, #2
+ ldmfd sp!, {r0}
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Get auxiliary data fault status register
+
+ EXPORT _coreGetAuxiliaryDataFault_
+_coreGetAuxiliaryDataFault_:
+
+ mrc p15, #0, r0, c5, c1, #0
+ bx lr
+
+
+
+;@-------------------------------------------------------------------------------
+;@ Clear auxiliary data fault status register
+
+ EXPORT _coreClearAuxiliaryDataFault_
+_coreClearAuxiliaryDataFault_:
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mcr p15, #0, r0, c5, c1, #0
+ ldmfd sp!, {r0}
+ bx lr
+
+
+
+;@-------------------------------------------------------------------------------
+;@ Get auxiliary instruction fault status register
+
+ EXPORT _coreGetAuxiliaryInstructionFault_
+_coreGetAuxiliaryInstructionFault_:
+
+ mrc p15, #0, r0, c5, c1, #1
+ bx lr
+
+
+;@-------------------------------------------------------------------------------
+;@ Clear auxiliary instruction fault status register
+
+ EXPORT _coreClearAuxiliaryInstructionFault_
+_coreClearAuxiliaryInstructionFault_:
+
+ stmfd sp!, {r0}
+ mov r0, #0
+ mrc p15, #0, r0, c5, c1, #1
+ ldmfd sp!, {r0}
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Work Around for Errata CORTEX-R4#57:
+;@
+;@ Errata Description:
+;@ Conditional VMRS APSR_Nzcv, FPSCR May Evaluate With Incorrect Flags
+;@ Workaround:
+;@ Disable out-of-order single-precision floating point
+;@ multiply-accumulate instruction completion
+
+ EXPORT _errata_CORTEXR4_57_
+_errata_CORTEXR4_57_:
+
+ push {r0}
+ mrc p15, #0, r0, c15, c0, #0 ;@ Read Secondary Auxiliary Control Register
+ orr r0, r0, #0x10000 ;@ Set BIT 16 (Set DOOFMACS)
+ mcr p15, #0, r0, c15, c0, #0 ;@ Write Secondary Auxiliary Control Register
+ pop {r0}
+ bx lr
+
+;@-------------------------------------------------------------------------------
+;@ Work Around for Errata CORTEX-R4#66:
+;@
+;@ Errata Description:
+;@ Register Corruption During A Load-Multiple Instruction At
+;@ an Exception Vector
+;@ Workaround:
+;@ Disable out-of-order completion for divide instructions in
+;@ Auxiliary Control register
+
+ EXPORT _errata_CORTEXR4_66_
+_errata_CORTEXR4_66_:
+
+ push {r0}
+ mrc p15, #0, r0, c1, c0, #1 ;@ Read Auxiliary Control register
+ orr r0, r0, #0x80 ;@ Set BIT 7 (Disable out-of-order completion
+ ;@ for divide instructions.)
+ mcr p15, #0, r0, c1, c0, #1 ;@ Write Auxiliary Control register
+ pop {r0}
+ bx lr
+ EXPORT turnon_VFP
+turnon_VFP:
+ ;@ Enable FPV
+ stmdb sp!, {r0}
+ fmrx r0, fpexc
+ orr r0, r0, #0x40000000
+ fmxr fpexc, r0
+ ldmia sp!, {r0}
+ subs pc, lr, #4
+
+ macro push_svc_reg
+ sub sp, sp, #17 * 4 ;@/* Sizeof(struct rt_hw_exp_stack) */
+ stmia sp, {r0 - r12} ;@/* Calling r0-r12 */
+ mov r0, sp
+ mrs r6, spsr ;@/* Save CPSR */
+ str lr, [r0, #15*4] ;@/* Push PC */
+ str r6, [r0, #16*4] ;@/* Push CPSR */
+ cps #Mode_SVC
+ str sp, [r0, #13*4] ;@/* Save calling SP */
+ str lr, [r0, #14*4] ;@/* Save calling PC */
+ endm
+
+ EXPORT SVC_Handler
+SVC_Handler:
+ push_svc_reg
+ bl rt_hw_trap_svc
+ b .
+
+ EXPORT Prefetch_Handler
+Prefetch_Handler:
+ push_svc_reg
+ bl rt_hw_trap_pabt
+ b .
+
+ EXPORT Abort_Handler
+Abort_Handler:
+ push_svc_reg
+ bl rt_hw_trap_dabt
+ b .
+
+ EXPORT Reserved_Handler
+Reserved_Handler:
+ push_svc_reg
+ bl rt_hw_trap_resv
+ b .
+ END
diff --git a/libcpu/arm/cortex-r52/trap.c b/libcpu/arm/cortex-r52/trap.c
new file mode 100644
index 0000000000..e5c217cb73
--- /dev/null
+++ b/libcpu/arm/cortex-r52/trap.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2013-07-20 Bernard first version
+ */
+
+#include <armv8.h>
+#include <gicv3.h>
+#include <rtthread.h>
+#include <rthw.h>
+//#include <board.h>
+
+#include "interrupt.h"
+
+#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
+extern long list_thread(void);
+#endif
+
+/**
+ * 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_svc(struct rt_hw_exp_stack *regs)
+{
+ rt_kprintf("software interrupt\n");
+ rt_hw_show_register(regs);
+#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
+ list_thread();
+#endif
+ rt_hw_cpu_shutdown();
+}
+
+static rt_err_t (*rt_exception_hook)(void *context) = RT_NULL;
+
+/**
+ * This function set the hook, which is invoked on fault exception handling.
+ *
+ * @param exception_handle the exception handling hook function.
+ */
+void rt_hw_exception_install(rt_err_t (*exception_handle)(void *context))
+{
+ rt_exception_hook = exception_handle;
+}
+
+/**
+ * this function will show registers of CPU
+ *
+ * @param regs the registers point
+ */
+void rt_hw_show_register(struct rt_hw_exp_stack *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);
+ if (rt_exception_hook != RT_NULL)
+ {
+ rt_err_t result;
+
+ result = rt_exception_hook(regs);
+ if (result == RT_EOK) return;
+ }
+}
+
+void (*rt_trap_hook)(struct rt_hw_exp_stack *regs, const char *ex, unsigned int exception_type);
+
+/**
+ * This function will set a hook function to trap handler.
+ *
+ * @param hook the hook function
+ */
+void rt_hw_trap_set_hook(void (*hook)(struct rt_hw_exp_stack *regs, const char *ex, unsigned int exception_type))
+{
+ rt_trap_hook = hook;
+}
+
+/**
+ * When 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_undef(struct rt_hw_exp_stack *regs)
+{
+#ifdef RT_USING_FPU
+ {
+ uint32_t val;
+ uint32_t addr;
+
+ if (regs->cpsr & (1 << 5))
+ {
+ /* thumb mode */
+ addr = regs->pc - 2;
+ }
+ else
+ {
+ addr = regs->pc - 4;
+ }
+ asm volatile ("vmrs %0, fpexc" : "=r"(val)::"memory");
+
+ if (!(val & 0x40000000))
+ {
+ /* float ins */
+ val = (1U << 30);
+
+ asm volatile ("vmsr fpexc, %0"::"r"(val):"memory");
+ regs->pc = addr;
+ return;
+ }
+ }
+#endif
+
+ if (rt_trap_hook == RT_NULL)
+ {
+ rt_kprintf("undefined instruction:\n");
+ rt_hw_show_register(regs);
+#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
+ list_thread();
+#endif
+ rt_hw_cpu_shutdown();
+ }
+ else
+ {
+ rt_trap_hook(regs, "undefined instruction", UND_EXCEPTION);
+ }
+}
+
+/**
+ * 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_exp_stack *regs)
+{
+ if (rt_trap_hook == RT_NULL)
+ {
+ rt_kprintf("software interrupt:\n");
+ rt_hw_show_register(regs);
+#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
+ list_thread();
+#endif
+ rt_hw_cpu_shutdown();
+ }
+ else
+ {
+ rt_trap_hook(regs, "software instruction", SWI_EXCEPTION);
+ }
+}
+
+/**
+ * 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_exp_stack *regs)
+{
+ if (rt_trap_hook == RT_NULL)
+ {
+ rt_kprintf("prefetch abort:\n");
+ rt_hw_show_register(regs);
+#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
+ list_thread();
+#endif
+ rt_hw_cpu_shutdown();
+ }
+ else
+ {
+ rt_trap_hook(regs, "prefetch abort", PABT_EXCEPTION);
+ }
+}
+
+/**
+ * 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_exp_stack *regs)
+{
+ if (rt_trap_hook == RT_NULL)
+ {
+ rt_kprintf("data abort:");
+ rt_hw_show_register(regs);
+#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
+ list_thread();
+#endif
+ rt_hw_cpu_shutdown();
+ }
+ else
+ {
+ rt_trap_hook(regs, "data abort", DABT_EXCEPTION);
+ }
+}
+
+/**
+ * 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_exp_stack *regs)
+{
+ if (rt_trap_hook == RT_NULL)
+ {
+ rt_kprintf("reserved trap:\n");
+ rt_hw_show_register(regs);
+#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
+ list_thread();
+#endif
+ rt_hw_cpu_shutdown();
+ }
+ else
+ {
+ rt_trap_hook(regs, "reserved trap", RESV_EXCEPTION);
+ }
+}
+
+void rt_hw_trap_irq(void)
+{
+ void *param;
+ int int_ack;
+ int ir;
+ volatile rt_isr_handler_t isr_func;
+ extern struct rt_irq_desc isr_table[];
+
+ int_ack = rt_hw_interrupt_get_irq();
+
+ ir = int_ack & GIC_ACK_INTID_MASK;
+ if (ir == 1023)
+ {
+ /* Spurious interrupt */
+ return;
+ }
+
+#ifdef SOC_SERIES_R9A07G0
+ extern fsp_vector_t g_vector_table[BSP_ICU_VECTOR_MAX_ENTRIES];
+
+ bsp_common_interrupt_handler((uint32_t)ir);
+ if (ir < MAX_HANDLERS)
+ {
+ /* get interrupt service routine */
+ isr_table[ir].handler = (rt_isr_handler_t)g_vector_table[ir];
+ isr_table[ir].param = RT_NULL;
+ }
+#endif
+ /* get interrupt service routine */
+ isr_func = isr_table[ir].handler;
+
+#ifdef RT_USING_INTERRUPT_INFO
+ isr_table[ir].counter++;
+#endif
+ if (isr_func)
+ {
+ /* Interrupt for myself. */
+ param = isr_table[ir].param;
+ /* turn to interrupt service routine */
+ isr_func(ir, param);
+ }
+
+ /* end of interrupt */
+ rt_hw_interrupt_ack(int_ack);
+}
+
+void rt_hw_trap_fiq(void)
+{
+ void *param;
+ int ir;
+ rt_isr_handler_t isr_func;
+ extern struct rt_irq_desc isr_table[];
+
+ ir = rt_hw_interrupt_get_irq();
+
+#ifdef SOC_SERIES_R9A07G0
+ extern fsp_vector_t g_vector_table[BSP_ICU_VECTOR_MAX_ENTRIES];
+
+ bsp_common_interrupt_handler((uint32_t)ir);
+ if (ir < MAX_HANDLERS)
+ {
+ /* get interrupt service routine */
+ isr_table[ir].handler = (rt_isr_handler_t)g_vector_table[ir];
+ isr_table[ir].param = RT_NULL;
+ }
+#endif
+ /* get interrupt service routine */
+ isr_func = isr_table[ir].handler;
+ param = isr_table[ir].param;
+
+ /* turn to interrupt service routine */
+ isr_func(ir, param);
+
+ /* end of interrupt */
+ rt_hw_interrupt_ack(ir);
+}
+
diff --git a/libcpu/arm/cortex-r52/vector_ccs.asm b/libcpu/arm/cortex-r52/vector_ccs.asm
new file mode 100644
index 0000000000..df2bcec925
--- /dev/null
+++ b/libcpu/arm/cortex-r52/vector_ccs.asm
@@ -0,0 +1,34 @@
+;-------------------------------------------------------------------------------
+; sys_intvecs.asm
+;
+; (c) Texas Instruments 2009-2013, All rights reserved.
+;
+
+ .sect ".intvecs"
+ .arm
+
+;-------------------------------------------------------------------------------
+; import reference for interrupt routines
+
+ .ref _reset
+ .ref turnon_VFP
+ .ref vector_svc
+ .ref vector_pabort
+ .ref vector_dabort
+ .ref vector_resv
+ .ref IRQ_Handler
+
+;-------------------------------------------------------------------------------
+; interrupt vectors
+ .def resetEntry
+resetEntry
+ b _reset
+ b turnon_VFP
+ b vector_svc
+ b vector_pabort
+ b vector_dabort
+ b vector_resv
+ b IRQ_Handler
+ ldr pc,[pc,#-0x1b0]
+
+;-------------------------------------------------------------------------------
diff --git a/libcpu/arm/cortex-r52/vector_gcc.S b/libcpu/arm/cortex-r52/vector_gcc.S
new file mode 100644
index 0000000000..8cd38196b5
--- /dev/null
+++ b/libcpu/arm/cortex-r52/vector_gcc.S
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ */
+@-------------------------------------------------------------------------------
+@ sys_intvecs.asm
+@
+@ (c) Texas Instruments 2009-2013, All rights reserved.
+@
+
+.section .vectors, "ax"
+.code 32
+
+@-------------------------------------------------------------------------------
+@ import reference for interrupt routines
+
+ .globl Reset_Handler
+ .globl turnon_VFP
+ .globl SVC_Handler
+ .globl Prefetch_Handler
+ .globl Abort_Handler
+ .globl Reserved_Handler
+ .globl IRQ_Handler
+ .globl FIQ_Handler
+
+
+.globl system_vectors
+system_vectors:
+ b Reset_Handler
+ b turnon_VFP
+ b SVC_Handler
+ b Prefetch_Handler
+ b Abort_Handler
+ b Reserved_Handler
+ b IRQ_Handler
+ b FIQ_Handler
+ ldr pc,[pc,#-0x1b0]
diff --git a/libcpu/arm/cortex-r52/vector_iar.S b/libcpu/arm/cortex-r52/vector_iar.S
new file mode 100644
index 0000000000..453f41f3fe
--- /dev/null
+++ b/libcpu/arm/cortex-r52/vector_iar.S
@@ -0,0 +1,45 @@
+;/*
+; * Copyright (c) 2006-2018, RT-Thread Development Team
+; *
+; * SPDX-License-Identifier: Apache-2.0
+; *
+; * Change Logs:
+; * Date Author Notes
+; * 2024-03-11 Wangyuqiang first version
+; */
+;@-------------------------------------------------------------------------------
+;@ sys_intvecs.asm
+;@
+;@ (c) Texas Instruments 2009-2013, All rights reserved.
+;@
+
+ ;SECTION .vectors:"ax"
+
+;@-------------------------------------------------------------------------------
+;@ import reference for interrupt routines
+
+ IMPORT Reset_Handler
+ IMPORT Undefined_Handler
+ IMPORT SVC_Handler
+ IMPORT Prefetch_Handler
+ IMPORT Abort_Handler
+ IMPORT Reserved_Handler
+ IMPORT IRQ_Handler
+ IMPORT FIQ_Handler
+
+;/*
+; * int system_vectors(void);
+; */
+ EXPORT system_vectors
+ SECTION .intvec:CODE:NOROOT(2)
+system_vectors:
+ b Reset_Handler
+ b Undefined_Handler
+ b SVC_Handler
+ b Prefetch_Handler
+ b Abort_Handler
+ b Reserved_Handler
+ b IRQ_Handler
+ b FIQ_Handler
+ ldr pc,[pc,#-0x1b0]
+ END \ No newline at end of file