mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-10-02 14:23:19 +08:00
Merge remote-tracking branch 'remotes/gitee/master'
This commit is contained in:
@@ -57,6 +57,25 @@ config ARCH_ARM_ARM11
|
||||
config ARCH_ARM_CORTEX_A
|
||||
bool
|
||||
select ARCH_ARM
|
||||
select RT_USING_CPU_FFS
|
||||
|
||||
if ARCH_ARM_CORTEX_A
|
||||
config RT_SMP_AUTO_BOOT
|
||||
bool
|
||||
default n
|
||||
|
||||
config RT_USING_GIC_V2
|
||||
bool
|
||||
default n
|
||||
|
||||
config RT_USING_GIC_V3
|
||||
bool
|
||||
default n
|
||||
|
||||
config RT_NO_USING_GIC
|
||||
bool
|
||||
default y if !RT_USING_GIC_V2 && !RT_USING_GIC_V3
|
||||
endif
|
||||
|
||||
config ARCH_ARM_CORTEX_A5
|
||||
bool
|
||||
|
||||
@@ -5,9 +5,24 @@ from building import *
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp')
|
||||
src = Split('''
|
||||
cache.c
|
||||
cpu.c
|
||||
mmu.c
|
||||
stack.c
|
||||
''')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
if GetDepend('RT_USING_GIC_V2'):
|
||||
src += ['interrupt.c']
|
||||
src += ['gic.c']
|
||||
src += ['trap.c']
|
||||
|
||||
if GetDepend('RT_USING_GIC_V3'):
|
||||
src += ['interrupt.c']
|
||||
src += ['gicv3.c']
|
||||
src += ['trap.c']
|
||||
|
||||
if rtconfig.PLATFORM == 'armcc':
|
||||
src += Glob('*_rvds.S')
|
||||
|
||||
@@ -18,6 +33,9 @@ if rtconfig.PLATFORM == 'gcc':
|
||||
if rtconfig.PLATFORM == 'iar':
|
||||
src += Glob('*_iar.S')
|
||||
|
||||
if rtconfig.PLATFORM == 'iar':
|
||||
src += Glob('*_iar.S')
|
||||
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
|
||||
@@ -69,4 +69,10 @@ struct rt_hw_stack
|
||||
#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
|
||||
|
||||
#endif
|
||||
|
||||
@@ -58,6 +58,37 @@ void rt_hw_cpu_dcache_invalidate(void *addr, int size)
|
||||
asm volatile ("dsb":::"memory");
|
||||
}
|
||||
|
||||
void rt_hw_cpu_dcache_inv_range(void *addr, int size)
|
||||
{
|
||||
rt_uint32_t line_size = rt_cpu_dcache_line_size();
|
||||
rt_uint32_t start_addr = (rt_uint32_t)addr;
|
||||
rt_uint32_t end_addr = (rt_uint32_t)addr + size;
|
||||
|
||||
asm volatile ("dmb":::"memory");
|
||||
|
||||
if ((start_addr & (line_size - 1)) != 0)
|
||||
{
|
||||
start_addr &= ~(line_size - 1);
|
||||
asm volatile ("mcr p15, 0, %0, c7, c14, 1" :: "r"(start_addr));
|
||||
start_addr += line_size;
|
||||
asm volatile ("dsb":::"memory");
|
||||
}
|
||||
|
||||
if ((end_addr & (line_size - 1)) != 0)
|
||||
{
|
||||
end_addr &= ~(line_size - 1);
|
||||
asm volatile ("mcr p15, 0, %0, c7, c14, 1" :: "r"(end_addr));
|
||||
asm volatile ("dsb":::"memory");
|
||||
}
|
||||
|
||||
while (start_addr < end_addr)
|
||||
{
|
||||
asm volatile ("mcr p15, 0, %0, c7, c6, 1" :: "r"(start_addr)); /* dcimvac */
|
||||
start_addr += line_size;
|
||||
}
|
||||
asm volatile ("dsb":::"memory");
|
||||
}
|
||||
|
||||
void rt_hw_cpu_dcache_clean(void *addr, int size)
|
||||
{
|
||||
rt_uint32_t line_size = rt_cpu_dcache_line_size();
|
||||
@@ -75,6 +106,23 @@ void rt_hw_cpu_dcache_clean(void *addr, int size)
|
||||
asm volatile ("dsb":::"memory");
|
||||
}
|
||||
|
||||
void rt_hw_cpu_dcache_clean_inv(void *addr, int size)
|
||||
{
|
||||
rt_uint32_t line_size = rt_cpu_dcache_line_size();
|
||||
rt_uint32_t start_addr = (rt_uint32_t)addr;
|
||||
rt_uint32_t end_addr = (rt_uint32_t) addr + size + line_size - 1;
|
||||
|
||||
asm volatile ("dmb":::"memory");
|
||||
start_addr &= ~(line_size-1);
|
||||
end_addr &= ~(line_size-1);
|
||||
while (start_addr < end_addr)
|
||||
{
|
||||
asm volatile ("mcr p15, 0, %0, c7, c14, 1" :: "r"(start_addr));
|
||||
start_addr += line_size;
|
||||
}
|
||||
asm volatile ("dsb":::"memory");
|
||||
}
|
||||
|
||||
void rt_hw_cpu_icache_ops(int ops, void *addr, int size)
|
||||
{
|
||||
if (ops == RT_HW_CACHE_INVALIDATE)
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
#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" )
|
||||
|
||||
unsigned long rt_cpu_get_smp_id(void);
|
||||
|
||||
int rt_hw_cpu_id(void);
|
||||
void rt_cpu_mmu_disable(void);
|
||||
void rt_cpu_mmu_enable(void);
|
||||
void rt_cpu_tlb_set(volatile unsigned long*);
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
* 2013-07-05 Bernard the first version
|
||||
*/
|
||||
|
||||
.globl rt_cpu_get_smp_id
|
||||
rt_cpu_get_smp_id:
|
||||
mrc p15, #0, r0, c0, c0, #5
|
||||
.weak rt_hw_cpu_id
|
||||
rt_hw_cpu_id:
|
||||
mrc p15, #0, r0, c0, c0, #5 @ read multiprocessor affinity register
|
||||
ldr r1, =0xFFFF03 @ Affinity mask off, leaving CPU ID field, [0:1]CPU ID, [8:15]Cluster ID Aff1, [16:23]Cluster ID Aff2
|
||||
and r0, r0, r1
|
||||
bx lr
|
||||
|
||||
.globl rt_cpu_vector_set_base
|
||||
|
||||
+17
-11
@@ -15,17 +15,6 @@
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock)
|
||||
{
|
||||
lock->slock = 0;
|
||||
@@ -86,4 +75,21 @@ RT_WEAK void rt_hw_cpu_shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RT_USING_CPU_FFS
|
||||
/**
|
||||
* This function finds the first bit set (beginning with the least significant bit)
|
||||
* in value and return the index of that bit.
|
||||
*
|
||||
* Bits are numbered starting at 1 (the least significant bit). A return value of
|
||||
* zero from any of these functions means that the argument was zero.
|
||||
*
|
||||
* @return return the index of the first bit set. If value is 0, then this function
|
||||
* shall return 0.
|
||||
*/
|
||||
int __rt_ffs(int value)
|
||||
{
|
||||
return __builtin_ffs(value);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*@}*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, 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 (1<<31)
|
||||
#define GICD_CTLR_E1NWF (1<<7)
|
||||
#define GICD_CTLR_DS (1<<6)
|
||||
#define GICD_CTLR_ARE_NS (1<<5)
|
||||
#define GICD_CTLR_ARE_S (1<<4)
|
||||
#define GICD_CTLR_ENGRP1S (1<<2)
|
||||
#define GICD_CTLR_ENGRP1NS (1<<1)
|
||||
#define GICD_CTLR_ENGRP0 (1<<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, 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);
|
||||
|
||||
void arm_gic_send_affinity_sgi(rt_uint32_t index, int irq, rt_uint32_t cpu_mask, rt_uint32_t routing_mode);
|
||||
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);
|
||||
#endif
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-03-30 huijie.feng first version
|
||||
*/
|
||||
|
||||
#include "cp15.h"
|
||||
#include <rtdef.h>
|
||||
|
||||
/** Set CNTFRQ
|
||||
* This function assigns the given value to PL1 Physical Timer Counter Frequency Register (CNTFRQ).
|
||||
* @param value: CNTFRQ Register value to set
|
||||
*/
|
||||
static inline void __set_cntfrq(rt_uint32_t value)
|
||||
{
|
||||
__set_cp(15, 0, value, 14, 0, 0);
|
||||
}
|
||||
|
||||
/** Get CNTFRQ
|
||||
* This function returns the value of the PL1 Physical Timer Counter Frequency Register (CNTFRQ).
|
||||
* return CNTFRQ Register value
|
||||
*/
|
||||
static inline rt_uint32_t __get_cntfrq(void)
|
||||
{
|
||||
rt_uint32_t result;
|
||||
__get_cp(15, 0, result, 14, 0 , 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Set CNTP_TVAL
|
||||
* This function assigns the given value to PL1 Physical Timer Value Register (CNTP_TVAL).
|
||||
* param value: CNTP_TVAL Register value to set
|
||||
*/
|
||||
static inline void __set_cntp_tval(rt_uint32_t value)
|
||||
{
|
||||
__set_cp(15, 0, value, 14, 2, 0);
|
||||
}
|
||||
|
||||
/** Get CNTP_TVAL
|
||||
* This function returns the value of the PL1 Physical Timer Value Register (CNTP_TVAL).
|
||||
* return CNTP_TVAL Register value
|
||||
*/
|
||||
static inline rt_uint32_t __get_cntp_tval(void)
|
||||
{
|
||||
rt_uint32_t result;
|
||||
__get_cp(15, 0, result, 14, 2, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Get CNTPCT
|
||||
* This function returns the value of the 64 bits PL1 Physical Count Register (CNTPCT).
|
||||
* return CNTPCT Register value
|
||||
*/
|
||||
static inline rt_uint64_t __get_cntpct(void)
|
||||
{
|
||||
rt_uint64_t result;
|
||||
__get_cp64(15, 0, result, 14);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Set CNTP_CVAL
|
||||
* This function assigns the given value to 64bits PL1 Physical Timer CompareValue Register (CNTP_CVAL).
|
||||
* param value: CNTP_CVAL Register value to set
|
||||
*/
|
||||
static inline void __set_cntp_cval(rt_uint64_t value)
|
||||
{
|
||||
__set_cp64(15, 2, value, 14);
|
||||
}
|
||||
|
||||
/** Get CNTP_CVAL
|
||||
* This function returns the value of the 64 bits PL1 Physical Timer CompareValue Register (CNTP_CVAL).
|
||||
* return CNTP_CVAL Register value
|
||||
*/
|
||||
static inline rt_uint64_t __get_cntp_cval(void)
|
||||
{
|
||||
rt_uint64_t result;
|
||||
__get_cp64(15, 2, result, 14);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Set CNTP_CTL
|
||||
* This function assigns the given value to PL1 Physical Timer Control Register (CNTP_CTL).
|
||||
* param value: CNTP_CTL Register value to set
|
||||
*/
|
||||
static inline void __set_cntp_ctl(uint32_t value)
|
||||
{
|
||||
__set_cp(15, 0, value, 14, 2, 1);
|
||||
}
|
||||
|
||||
/** Get CNTP_CTL register
|
||||
* return CNTP_CTL Register value
|
||||
*/
|
||||
static inline rt_uint32_t __get_cntp_ctl(void)
|
||||
{
|
||||
rt_uint32_t result;
|
||||
__get_cp(15, 0, result, 14, 2, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Configures the frequency the timer shall run at.
|
||||
* param value The timer frequency in Hz.
|
||||
*/
|
||||
void gtimer_set_counter_frequency(rt_uint32_t value)
|
||||
{
|
||||
__set_cntfrq(value);
|
||||
__asm__ volatile ("isb 0xF":::"memory");
|
||||
}
|
||||
|
||||
/** Sets the reset value of the timer.
|
||||
* param value: The value the timer is loaded with.
|
||||
*/
|
||||
void gtimer_set_load_value(rt_uint32_t value)
|
||||
{
|
||||
__set_cntp_tval(value);
|
||||
__asm__ volatile ("isb 0xF":::"memory");
|
||||
}
|
||||
|
||||
/** Get the current counter value.
|
||||
* return Current counter value.
|
||||
*/
|
||||
rt_uint32_t gtimer_get_current_value(void)
|
||||
{
|
||||
return(__get_cntp_tval());
|
||||
}
|
||||
|
||||
/** Get the current physical counter value.
|
||||
* return Current physical counter value.
|
||||
*/
|
||||
rt_uint64_t gtimer_get_current_physical_value(void)
|
||||
{
|
||||
return(__get_cntpct());
|
||||
}
|
||||
|
||||
/** Set the physical compare value.
|
||||
* param value: New physical timer compare value.
|
||||
*/
|
||||
void gtimer_set_physical_compare_value(rt_uint64_t value)
|
||||
{
|
||||
__set_cntp_cval(value);
|
||||
__asm__ volatile ("isb 0xF":::"memory");
|
||||
}
|
||||
|
||||
/** Get the physical compare value.
|
||||
* return Physical compare value.
|
||||
*/
|
||||
rt_uint64_t gtimer_get_physical_compare_value(void)
|
||||
{
|
||||
return(__get_cntp_cval());
|
||||
}
|
||||
|
||||
/** Configure the timer by setting the control value.
|
||||
* param value: New timer control value.
|
||||
*/
|
||||
void gtimer_set_control(rt_uint32_t value)
|
||||
{
|
||||
__set_cntp_ctl(value);
|
||||
__asm__ volatile ("isb 0xF":::"memory");
|
||||
}
|
||||
|
||||
/** Get the control value.
|
||||
* return Control value.
|
||||
*/
|
||||
rt_uint32_t gtimer_get_control(void)
|
||||
{
|
||||
return(__get_cntp_ctl());
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-03-30 huijie.feng first version
|
||||
*/
|
||||
|
||||
#ifndef __GTIMER_H__
|
||||
#define __GTIMER_H__
|
||||
|
||||
#include <rtdef.h>
|
||||
|
||||
void gtimer_set_counter_frequency(rt_uint32_t value);
|
||||
void gtimer_set_load_value(rt_uint32_t value);
|
||||
rt_uint32_t gtimer_get_current_value(void);
|
||||
rt_uint64_t gtimer_get_current_physical_value(void);
|
||||
void gtimer_set_physical_compare_value(rt_uint64_t value);
|
||||
rt_uint64_t gtimer_get_physical_compare_value(void);
|
||||
void gtimer_set_control(rt_uint32_t value);
|
||||
rt_uint32_t gtimer_get_control(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,8 +12,12 @@
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include "interrupt.h"
|
||||
#include "gic.h"
|
||||
|
||||
#ifdef RT_USING_GIC_V2
|
||||
#include "gic.h"
|
||||
#else
|
||||
#include "gicv3.h"
|
||||
#endif
|
||||
|
||||
/* exception and interrupt handler table */
|
||||
struct rt_irq_desc isr_table[MAX_HANDLERS];
|
||||
@@ -23,6 +27,20 @@ struct rt_irq_desc isr_table[MAX_HANDLERS];
|
||||
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;
|
||||
@@ -34,6 +52,7 @@ void rt_hw_vector_init(void)
|
||||
rt_cpu_vector_set_base((unsigned int)&system_vectors);
|
||||
}
|
||||
|
||||
#ifdef RT_USING_GIC_V2
|
||||
/**
|
||||
* This function will initialize hardware interrupt
|
||||
*/
|
||||
@@ -58,6 +77,33 @@ void rt_hw_interrupt_init(void)
|
||||
arm_gic_dist_init(0, gic_dist_base, gic_irq_start);
|
||||
arm_gic_cpu_init(0, gic_cpu_base);
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This function will mask a interrupt.
|
||||
@@ -245,7 +291,7 @@ unsigned int rt_hw_interrupt_get_prior_group_bits(void)
|
||||
* @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)
|
||||
void *param, const char *name)
|
||||
{
|
||||
rt_isr_handler_t old_handler = RT_NULL;
|
||||
|
||||
@@ -269,7 +315,11 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
||||
#ifdef RT_USING_SMP
|
||||
void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
|
||||
{
|
||||
#ifdef RT_USING_GIC_V2
|
||||
arm_gic_send_sgi(0, ipi_vector, cpu_mask, 0);
|
||||
#else
|
||||
arm_gic_send_affinity_sgi(0, ipi_vector, cpu_mask, ROUTED_TO_SPEC);
|
||||
#endif
|
||||
}
|
||||
|
||||
void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler)
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
#include "pmu.h"
|
||||
|
||||
void rt_hw_pmu_dump_feature(void)
|
||||
{
|
||||
unsigned long reg;
|
||||
|
||||
reg = rt_hw_pmu_get_control();
|
||||
rt_kprintf("ARM PMU Implementor: %c, ID code: %02x, %d counters\n",
|
||||
reg >> 24, (reg >> 16) & 0xff, (reg >> 11) & 0x1f);
|
||||
RT_ASSERT(ARM_PMU_CNTER_NR == ((reg >> 11) & 0x1f));
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
#ifndef __PMU_H__
|
||||
#define __PMU_H__
|
||||
|
||||
#include "board.h"
|
||||
|
||||
/* Number of counters */
|
||||
#define ARM_PMU_CNTER_NR 4
|
||||
|
||||
enum rt_hw_pmu_event_type {
|
||||
ARM_PMU_EVENT_PMNC_SW_INCR = 0x00,
|
||||
ARM_PMU_EVENT_L1_ICACHE_REFILL = 0x01,
|
||||
ARM_PMU_EVENT_ITLB_REFILL = 0x02,
|
||||
ARM_PMU_EVENT_L1_DCACHE_REFILL = 0x03,
|
||||
ARM_PMU_EVENT_L1_DCACHE_ACCESS = 0x04,
|
||||
ARM_PMU_EVENT_DTLB_REFILL = 0x05,
|
||||
ARM_PMU_EVENT_MEM_READ = 0x06,
|
||||
ARM_PMU_EVENT_MEM_WRITE = 0x07,
|
||||
ARM_PMU_EVENT_INSTR_EXECUTED = 0x08,
|
||||
ARM_PMU_EVENT_EXC_TAKEN = 0x09,
|
||||
ARM_PMU_EVENT_EXC_EXECUTED = 0x0A,
|
||||
ARM_PMU_EVENT_CID_WRITE = 0x0B,
|
||||
};
|
||||
|
||||
/* Enable bit */
|
||||
#define ARM_PMU_PMCR_E (0x01 << 0)
|
||||
/* Event counter reset */
|
||||
#define ARM_PMU_PMCR_P (0x01 << 1)
|
||||
/* Cycle counter reset */
|
||||
#define ARM_PMU_PMCR_C (0x01 << 2)
|
||||
/* Cycle counter divider */
|
||||
#define ARM_PMU_PMCR_D (0x01 << 3)
|
||||
|
||||
#ifdef __GNUC__
|
||||
rt_inline void rt_hw_pmu_enable_cnt(int divide64)
|
||||
{
|
||||
unsigned long pmcr;
|
||||
unsigned long pmcntenset;
|
||||
|
||||
asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
|
||||
pmcr |= ARM_PMU_PMCR_E | ARM_PMU_PMCR_P | ARM_PMU_PMCR_C;
|
||||
if (divide64)
|
||||
pmcr |= ARM_PMU_PMCR_D;
|
||||
else
|
||||
pmcr &= ~ARM_PMU_PMCR_D;
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
|
||||
|
||||
/* enable all the counters */
|
||||
pmcntenset = ~0;
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 1" :: "r"(pmcntenset));
|
||||
/* clear overflows(just in case) */
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 3" :: "r"(pmcntenset));
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_control(void)
|
||||
{
|
||||
unsigned long pmcr;
|
||||
asm ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
|
||||
return pmcr;
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_ceid(void)
|
||||
{
|
||||
unsigned long reg;
|
||||
/* only PMCEID0 is supported, PMCEID1 is RAZ. */
|
||||
asm ("mrc p15, 0, %0, c9, c12, 6" : "=r"(reg));
|
||||
return reg;
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_cnten(void)
|
||||
{
|
||||
unsigned long pmcnt;
|
||||
asm ("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcnt));
|
||||
return pmcnt;
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_reset_cycle(void)
|
||||
{
|
||||
unsigned long pmcr;
|
||||
|
||||
asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
|
||||
pmcr |= ARM_PMU_PMCR_C;
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
|
||||
asm volatile ("isb");
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_reset_event(void)
|
||||
{
|
||||
unsigned long pmcr;
|
||||
|
||||
asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
|
||||
pmcr |= ARM_PMU_PMCR_P;
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
|
||||
asm volatile ("isb");
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_cycle(void)
|
||||
{
|
||||
unsigned long cyc;
|
||||
asm volatile ("isb");
|
||||
asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r"(cyc));
|
||||
return cyc;
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_select_counter(int idx)
|
||||
{
|
||||
RT_ASSERT(idx < ARM_PMU_CNTER_NR);
|
||||
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 5" : : "r"(idx));
|
||||
/* Linux add an isb here, don't know why here. */
|
||||
asm volatile ("isb");
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_select_event(int idx,
|
||||
enum rt_hw_pmu_event_type eve)
|
||||
{
|
||||
RT_ASSERT(idx < ARM_PMU_CNTER_NR);
|
||||
|
||||
rt_hw_pmu_select_counter(idx);
|
||||
asm volatile ("mcr p15, 0, %0, c9, c13, 1" : : "r"(eve));
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_read_counter(int idx)
|
||||
{
|
||||
unsigned long reg;
|
||||
|
||||
rt_hw_pmu_select_counter(idx);
|
||||
asm volatile ("isb");
|
||||
asm volatile ("mrc p15, 0, %0, c9, c13, 2" : "=r"(reg));
|
||||
return reg;
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_ovsr(void)
|
||||
{
|
||||
unsigned long reg;
|
||||
asm volatile ("isb");
|
||||
asm ("mrc p15, 0, %0, c9, c12, 3" : "=r"(reg));
|
||||
return reg;
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_clear_ovsr(unsigned long reg)
|
||||
{
|
||||
asm ("mcr p15, 0, %0, c9, c12, 3" : : "r"(reg));
|
||||
asm volatile ("isb");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void rt_hw_pmu_dump_feature(void);
|
||||
|
||||
#endif /* end of include guard: __PMU_H__ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+72
-22
@@ -35,6 +35,18 @@ void rt_hw_show_register(struct rt_hw_exp_stack *regs)
|
||||
rt_kprintf("cpsr:0x%08x\n", regs->cpsr);
|
||||
}
|
||||
|
||||
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.
|
||||
@@ -72,12 +84,20 @@ void rt_hw_trap_undef(struct rt_hw_exp_stack *regs)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
rt_kprintf("undefined instruction:\n");
|
||||
rt_hw_show_register(regs);
|
||||
|
||||
if (rt_trap_hook == RT_NULL)
|
||||
{
|
||||
rt_kprintf("undefined instruction:\n");
|
||||
rt_hw_show_register(regs);
|
||||
#ifdef RT_USING_FINSH
|
||||
list_thread();
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_trap_hook(regs, "undefined instruction", UND_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,12 +111,19 @@ void rt_hw_trap_undef(struct rt_hw_exp_stack *regs)
|
||||
*/
|
||||
void rt_hw_trap_swi(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("software interrupt:\n");
|
||||
rt_hw_show_register(regs);
|
||||
if (rt_trap_hook == RT_NULL)
|
||||
{
|
||||
rt_kprintf("software interrupt:\n");
|
||||
rt_hw_show_register(regs);
|
||||
#ifdef RT_USING_FINSH
|
||||
list_thread();
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_trap_hook(regs, "software instruction", SWI_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,12 +136,19 @@ void rt_hw_trap_swi(struct rt_hw_exp_stack *regs)
|
||||
*/
|
||||
void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("prefetch abort:\n");
|
||||
rt_hw_show_register(regs);
|
||||
if (rt_trap_hook == RT_NULL)
|
||||
{
|
||||
rt_kprintf("prefetch abort:\n");
|
||||
rt_hw_show_register(regs);
|
||||
#ifdef RT_USING_FINSH
|
||||
list_thread();
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_trap_hook(regs, "prefetch abort", PABT_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,12 +161,19 @@ void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs)
|
||||
*/
|
||||
void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("data abort:");
|
||||
rt_hw_show_register(regs);
|
||||
if (rt_trap_hook == RT_NULL)
|
||||
{
|
||||
rt_kprintf("data abort:");
|
||||
rt_hw_show_register(regs);
|
||||
#ifdef RT_USING_FINSH
|
||||
list_thread();
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_trap_hook(regs, "data abort", DABT_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,23 +185,32 @@ void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs)
|
||||
*/
|
||||
void rt_hw_trap_resv(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("reserved trap:\n");
|
||||
rt_hw_show_register(regs);
|
||||
if (rt_trap_hook == RT_NULL)
|
||||
{
|
||||
rt_kprintf("reserved trap:\n");
|
||||
rt_hw_show_register(regs);
|
||||
#ifdef RT_USING_FINSH
|
||||
list_thread();
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
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;
|
||||
rt_isr_handler_t isr_func;
|
||||
extern struct rt_irq_desc isr_table[];
|
||||
|
||||
ir = rt_hw_interrupt_get_irq();
|
||||
int_ack = rt_hw_interrupt_get_irq();
|
||||
|
||||
ir = int_ack & GIC_ACK_INTID_MASK;
|
||||
if (ir == 1023)
|
||||
{
|
||||
/* Spurious interrupt */
|
||||
@@ -181,7 +231,7 @@ void rt_hw_trap_irq(void)
|
||||
}
|
||||
|
||||
/* end of interrupt */
|
||||
rt_hw_interrupt_ack(ir);
|
||||
rt_hw_interrupt_ack(int_ack);
|
||||
}
|
||||
|
||||
void rt_hw_trap_fiq(void)
|
||||
|
||||
@@ -10,6 +10,8 @@ CPPPATH = [cwd]
|
||||
|
||||
if rtconfig.PLATFORM == 'armcc':
|
||||
src += Glob('*_rvds.S')
|
||||
elif rtconfig.PLATFORM == 'armclang':
|
||||
src += Glob('*_rvds.S')
|
||||
|
||||
if rtconfig.PLATFORM == 'gcc':
|
||||
src += Glob('*_init.S')
|
||||
|
||||
@@ -8,7 +8,7 @@ cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
if rtconfig.PLATFORM == 'armcc':
|
||||
if rtconfig.PLATFORM == 'armcc' or rtconfig.PLATFORM == 'armclang':
|
||||
src += Glob('*_rvds.S')
|
||||
|
||||
if rtconfig.PLATFORM == 'gcc':
|
||||
|
||||
+266
-31
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,9 @@
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020-03-19 WangHuachen first version
|
||||
* 2021-05-11 WangHuachen Added call to Xil_InitializeExistingMPURegConfig to
|
||||
* initialize the MPU configuration table with the MPU
|
||||
* configurations already set in Init_Mpu function.
|
||||
*/
|
||||
|
||||
.equ Mode_USR, 0x10
|
||||
@@ -234,6 +237,7 @@ ctor_loop:
|
||||
b ctor_loop
|
||||
ctor_end:
|
||||
|
||||
bl Xil_InitializeExistingMPURegConfig /* Initialize MPU config */
|
||||
/* start RT-Thread Kernel */
|
||||
ldr pc, _entry
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2015 - 2020 Xilinx, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
******************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file xil_mmu.h
|
||||
* This file only includes xil_mpu.h which contains Xil_SetTlbAttributes API
|
||||
* defined for MPU in R5. R5 does not have mmu and for usage of similar API
|
||||
* the file has been created.
|
||||
*
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- ---------------------------------------------------
|
||||
* 5.0 pkp 2/12/15 Initial version
|
||||
* </pre>
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef XIL_MMU_H
|
||||
#define XIL_MMU_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xil_mpu.h"
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* XIL_MMU_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,129 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2014 - 2017 Xilinx, Inc. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file xil_mmu.h
|
||||
*
|
||||
* @addtogroup r5_mpu_apis Cortex R5 Processor MPU specific APIs
|
||||
*
|
||||
* MPU functions provides access to MPU operations such as enable MPU, disable
|
||||
* MPU and set attribute for section of memory.
|
||||
* Boot code invokes Init_MPU function to configure the MPU. A total of 10 MPU
|
||||
* regions are allocated with another 6 being free for users. Overview of the
|
||||
* memory attributes for different MPU regions is as given below,
|
||||
*
|
||||
*| | Memory Range | Attributes of MPURegion |
|
||||
*|-----------------------|-------------------------|-----------------------------|
|
||||
*| DDR | 0x00000000 - 0x7FFFFFFF | Normal write-back Cacheable |
|
||||
*| PL | 0x80000000 - 0xBFFFFFFF | Strongly Ordered |
|
||||
*| QSPI | 0xC0000000 - 0xDFFFFFFF | Device Memory |
|
||||
*| PCIe | 0xE0000000 - 0xEFFFFFFF | Device Memory |
|
||||
*| STM_CORESIGHT | 0xF8000000 - 0xF8FFFFFF | Device Memory |
|
||||
*| RPU_R5_GIC | 0xF9000000 - 0xF90FFFFF | Device memory |
|
||||
*| FPS | 0xFD000000 - 0xFDFFFFFF | Device Memory |
|
||||
*| LPS | 0xFE000000 - 0xFFFFFFFF | Device Memory |
|
||||
*| OCM | 0xFFFC0000 - 0xFFFFFFFF | Normal write-back Cacheable |
|
||||
*
|
||||
*
|
||||
* @note
|
||||
* For a system where DDR is less than 2GB, region after DDR and before PL is
|
||||
* marked as undefined in translation table. Memory range 0xFE000000-0xFEFFFFFF is
|
||||
* allocated for upper LPS slaves, where as memory region 0xFF000000-0xFFFFFFFF is
|
||||
* allocated for lower LPS slaves.
|
||||
*
|
||||
* @{
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- ---------------------------------------------------
|
||||
* 5.00 pkp 02/10/14 Initial version
|
||||
* 6.4 asa 08/16/17 Added many APIs for MPU access to make MPU usage
|
||||
* user-friendly. The APIs added are: Xil_UpdateMPUConfig,
|
||||
* Xil_GetMPUConfig, Xil_GetNumOfFreeRegions,
|
||||
* Xil_GetNextMPURegion, Xil_DisableMPURegionByRegNum,
|
||||
* Xil_GetMPUFreeRegMask, Xil_SetMPURegionByRegNum, and
|
||||
* Xil_InitializeExistingMPURegConfig.
|
||||
* Added a new array of structure of type XMpuConfig to
|
||||
* represent the MPU configuration table.
|
||||
* </pre>
|
||||
*
|
||||
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef XIL_MPU_H
|
||||
#define XIL_MPU_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
#include "xil_types.h"
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
#define MPU_REG_DISABLED 0U
|
||||
#define MPU_REG_ENABLED 1U
|
||||
#define MAX_POSSIBLE_MPU_REGS 16U
|
||||
/**************************** Type Definitions *******************************/
|
||||
struct XMpuConfig{
|
||||
u32 RegionStatus; /* Enabled or disabled */
|
||||
INTPTR BaseAddress;/* MPU region base address */
|
||||
u64 Size; /* MPU region size address */
|
||||
u32 Attribute; /* MPU region size attribute */
|
||||
};
|
||||
|
||||
typedef struct XMpuConfig XMpu_Config[MAX_POSSIBLE_MPU_REGS];
|
||||
|
||||
extern XMpu_Config Mpu_Config;
|
||||
/************************** Constant Definitions *****************************/
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
void Xil_SetTlbAttributes(INTPTR Addr, u32 attrib);
|
||||
void Xil_EnableMPU(void);
|
||||
void Xil_DisableMPU(void);
|
||||
u32 Xil_SetMPURegion(INTPTR addr, u64 size, u32 attrib);
|
||||
u32 Xil_UpdateMPUConfig(u32 reg_num, INTPTR address, u32 size, u32 attrib);
|
||||
void Xil_GetMPUConfig (XMpu_Config mpuconfig);
|
||||
u32 Xil_GetNumOfFreeRegions (void);
|
||||
u32 Xil_GetNextMPURegion(void);
|
||||
u32 Xil_DisableMPURegionByRegNum (u32 reg_num);
|
||||
u16 Xil_GetMPUFreeRegMask (void);
|
||||
u32 Xil_SetMPURegionByRegNum (u32 reg_num, INTPTR addr, u64 size, u32 attrib);
|
||||
void* Xil_MemMap(UINTPTR Physaddr, size_t size, u32 flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* XIL_MPU_H */
|
||||
/**
|
||||
* @} End of "addtogroup r5_mpu_apis".
|
||||
*/
|
||||
@@ -14,6 +14,8 @@ if rtconfig.CPU == "e906" :
|
||||
group = group
|
||||
elif rtconfig.CPU == "nuclei" :
|
||||
group = group
|
||||
elif rtconfig.CPU == "virt64" :
|
||||
group = group
|
||||
else :
|
||||
group = group + SConscript(os.path.join(cwd, 'common', 'SConscript'))
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
ASFLAGS = ''
|
||||
|
||||
group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS)
|
||||
|
||||
Return('group')
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/28 Bernard The unify RISC-V porting code.
|
||||
* 2021-02-11 lizhirui add gp support
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "cpuport.h"
|
||||
#include "stack.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief from thread used interrupt context switch
|
||||
*
|
||||
*/
|
||||
volatile rt_ubase_t rt_interrupt_from_thread = 0;
|
||||
/**
|
||||
* @brief to thread used interrupt context switch
|
||||
*
|
||||
*/
|
||||
volatile rt_ubase_t rt_interrupt_to_thread = 0;
|
||||
/**
|
||||
* @brief flag to indicate context switch in interrupt or not
|
||||
*
|
||||
*/
|
||||
volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0;
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
struct rt_hw_stack_frame *frame;
|
||||
rt_uint8_t *stk;
|
||||
int i;
|
||||
extern int __global_pointer$;
|
||||
|
||||
stk = stack_addr + sizeof(rt_ubase_t);
|
||||
stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES);
|
||||
stk -= sizeof(struct rt_hw_stack_frame);
|
||||
|
||||
frame = (struct rt_hw_stack_frame *)stk;
|
||||
|
||||
for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++)
|
||||
{
|
||||
((rt_ubase_t *)frame)[i] = 0xdeadbeef;
|
||||
}
|
||||
|
||||
frame->ra = (rt_ubase_t)texit;
|
||||
frame->gp = (rt_ubase_t)&__global_pointer$;
|
||||
frame->a0 = (rt_ubase_t)parameter;
|
||||
frame->epc = (rt_ubase_t)tentry;
|
||||
frame->user_sp_exc_stack = (rt_ubase_t)(((rt_ubase_t)stk) + sizeof(struct rt_hw_stack_frame));
|
||||
|
||||
#ifndef RISCV_S_MODE
|
||||
frame->xstatus = 0x00007880;
|
||||
#else
|
||||
frame->xstatus = 0x00040120;
|
||||
#endif
|
||||
|
||||
return stk;
|
||||
}
|
||||
|
||||
/*
|
||||
* #ifdef RT_USING_SMP
|
||||
* void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
|
||||
* #else
|
||||
* void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
|
||||
* #endif
|
||||
*/
|
||||
#ifndef RT_USING_SMP
|
||||
void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
|
||||
{
|
||||
if (rt_thread_switch_interrupt_flag == 0)
|
||||
rt_interrupt_from_thread = from;
|
||||
|
||||
rt_interrupt_to_thread = to;
|
||||
rt_thread_switch_interrupt_flag = 1;
|
||||
|
||||
return ;
|
||||
}
|
||||
#endif /* end of RT_USING_SMP */
|
||||
|
||||
/** 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);
|
||||
}
|
||||
}
|
||||
|
||||
rt_thread_t rt_thread_sp_to_thread(void *spmember_addr)
|
||||
{
|
||||
return (rt_thread_t)(((rt_ubase_t)spmember_addr) - (offsetof(struct rt_thread,sp)));
|
||||
}
|
||||
|
||||
void *get_thread_kernel_stack_top(rt_thread_t thread)
|
||||
{
|
||||
return (void *)(((rt_size_t)thread -> stack_addr) + ((rt_size_t)thread -> stack_size));
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-10-03 Bernard The first version
|
||||
*/
|
||||
|
||||
#ifndef CPUPORT_H__
|
||||
#define CPUPORT_H__
|
||||
|
||||
#include <rtconfig.h>
|
||||
|
||||
/* bytes of register width */
|
||||
#ifdef ARCH_CPU_64BIT
|
||||
#define STORE sd
|
||||
#define LOAD ld
|
||||
#define REGBYTES 8
|
||||
#else
|
||||
// error here, not portable
|
||||
#endif
|
||||
|
||||
#ifdef RISCV_U_MODE
|
||||
#define RISCV_USER_ENTRY 0xFFFFFFE000000000ULL
|
||||
#endif
|
||||
|
||||
#ifdef RISCV_S_MODE
|
||||
//csr in s-mode
|
||||
// M/U/S Interrupt Registers
|
||||
#define SRC_XIE sie
|
||||
#define SRC_XIP sip
|
||||
#define SRC_XTVEC stvec
|
||||
#define SRC_XSTATUS sstatus
|
||||
#define SRC_XSCRATCH sscratch
|
||||
#define SRC_XEPC sepc
|
||||
#define SRC_XCAUSE scause
|
||||
#define SRC_XTVAL stval
|
||||
#define XRET sret
|
||||
#else
|
||||
//csr in m-mode
|
||||
// M/U/S Interrupt Registers
|
||||
#define SRC_XIE mie
|
||||
#define SRC_XIP mip
|
||||
#define SRC_XTVEC mtvec
|
||||
#define SRC_XSTATUS mstatus
|
||||
#define SRC_XSCRATCH mscratch
|
||||
#define SRC_XEPC mepc
|
||||
#define SRC_XCAUSE mcause
|
||||
#define SRC_XTVAL mtval
|
||||
#define XRET mret
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-05-20 bigmagic The first version
|
||||
*/
|
||||
|
||||
#ifndef INTERRUPT_H__
|
||||
#define INTERRUPT_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include "stack.h"
|
||||
|
||||
int rt_hw_clint_ipi_enable(void);
|
||||
int rt_hw_clint_ipi_disable(void);
|
||||
int rt_hw_plic_irq_enable(int irq_number);
|
||||
int rt_hw_plic_irq_disable(int irq_number);
|
||||
void rt_hw_interrupt_init(void);
|
||||
void rt_hw_interrupt_mask(int vector);
|
||||
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
||||
void *param, const char *name);
|
||||
void handle_trap(rt_size_t xcause,rt_size_t xtval,rt_size_t xepc,struct rt_hw_stack_frame *sp);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/02 Bernard The first version
|
||||
* 2018/12/27 Jesven Add SMP schedule
|
||||
* 2021/02/02 lizhirui Add userspace support
|
||||
*/
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
.section .text.entry
|
||||
.align 2
|
||||
.global trap_entry
|
||||
trap_entry:
|
||||
#ifdef ARCH_RISCV_FPU
|
||||
addi sp, sp, -32 * FREGBYTES
|
||||
|
||||
FSTORE f0, 0 * FREGBYTES(sp)
|
||||
FSTORE f1, 1 * FREGBYTES(sp)
|
||||
FSTORE f2, 2 * FREGBYTES(sp)
|
||||
FSTORE f3, 3 * FREGBYTES(sp)
|
||||
FSTORE f4, 4 * FREGBYTES(sp)
|
||||
FSTORE f5, 5 * FREGBYTES(sp)
|
||||
FSTORE f6, 6 * FREGBYTES(sp)
|
||||
FSTORE f7, 7 * FREGBYTES(sp)
|
||||
FSTORE f8, 8 * FREGBYTES(sp)
|
||||
FSTORE f9, 9 * FREGBYTES(sp)
|
||||
FSTORE f10, 10 * FREGBYTES(sp)
|
||||
FSTORE f11, 11 * FREGBYTES(sp)
|
||||
FSTORE f12, 12 * FREGBYTES(sp)
|
||||
FSTORE f13, 13 * FREGBYTES(sp)
|
||||
FSTORE f14, 14 * FREGBYTES(sp)
|
||||
FSTORE f15, 15 * FREGBYTES(sp)
|
||||
FSTORE f16, 16 * FREGBYTES(sp)
|
||||
FSTORE f17, 17 * FREGBYTES(sp)
|
||||
FSTORE f18, 18 * FREGBYTES(sp)
|
||||
FSTORE f19, 19 * FREGBYTES(sp)
|
||||
FSTORE f20, 20 * FREGBYTES(sp)
|
||||
FSTORE f21, 21 * FREGBYTES(sp)
|
||||
FSTORE f22, 22 * FREGBYTES(sp)
|
||||
FSTORE f23, 23 * FREGBYTES(sp)
|
||||
FSTORE f24, 24 * FREGBYTES(sp)
|
||||
FSTORE f25, 25 * FREGBYTES(sp)
|
||||
FSTORE f26, 26 * FREGBYTES(sp)
|
||||
FSTORE f27, 27 * FREGBYTES(sp)
|
||||
FSTORE f28, 28 * FREGBYTES(sp)
|
||||
FSTORE f29, 29 * FREGBYTES(sp)
|
||||
FSTORE f30, 30 * FREGBYTES(sp)
|
||||
FSTORE f31, 31 * FREGBYTES(sp)
|
||||
|
||||
#endif
|
||||
|
||||
/* save thread context to thread stack */
|
||||
addi sp, sp, -32 * REGBYTES
|
||||
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
|
||||
csrr x1, SRC_XSTATUS
|
||||
STORE x1, 2 * REGBYTES(sp)
|
||||
|
||||
csrr x1, SRC_XEPC
|
||||
STORE x1, 0 * REGBYTES(sp)
|
||||
|
||||
STORE x4, 4 * REGBYTES(sp)
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
STORE x6, 6 * REGBYTES(sp)
|
||||
STORE x7, 7 * REGBYTES(sp)
|
||||
STORE x8, 8 * REGBYTES(sp)
|
||||
STORE x9, 9 * REGBYTES(sp)
|
||||
STORE x10, 10 * REGBYTES(sp)
|
||||
STORE x11, 11 * REGBYTES(sp)
|
||||
STORE x12, 12 * REGBYTES(sp)
|
||||
STORE x13, 13 * REGBYTES(sp)
|
||||
STORE x14, 14 * REGBYTES(sp)
|
||||
STORE x15, 15 * REGBYTES(sp)
|
||||
STORE x16, 16 * REGBYTES(sp)
|
||||
STORE x17, 17 * REGBYTES(sp)
|
||||
STORE x18, 18 * REGBYTES(sp)
|
||||
STORE x19, 19 * REGBYTES(sp)
|
||||
STORE x20, 20 * REGBYTES(sp)
|
||||
STORE x21, 21 * REGBYTES(sp)
|
||||
STORE x22, 22 * REGBYTES(sp)
|
||||
STORE x23, 23 * REGBYTES(sp)
|
||||
STORE x24, 24 * REGBYTES(sp)
|
||||
STORE x25, 25 * REGBYTES(sp)
|
||||
STORE x26, 26 * REGBYTES(sp)
|
||||
STORE x27, 27 * REGBYTES(sp)
|
||||
STORE x28, 28 * REGBYTES(sp)
|
||||
STORE x29, 29 * REGBYTES(sp)
|
||||
STORE x30, 30 * REGBYTES(sp)
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
|
||||
/* switch to interrupt stack */
|
||||
move s0, sp
|
||||
|
||||
#ifndef RISCV_S_MODE
|
||||
/* get cpu id */
|
||||
csrr t0, mhartid
|
||||
#else
|
||||
li t0, 0
|
||||
#endif
|
||||
|
||||
/* switch interrupt stack of current cpu */
|
||||
la sp, __stack_start__
|
||||
addi t1, t0, 1
|
||||
li t2, __STACKSIZE__
|
||||
mul t1, t1, t2
|
||||
add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */
|
||||
|
||||
/* handle interrupt */
|
||||
call rt_interrupt_enter
|
||||
csrr a0, SRC_XCAUSE
|
||||
csrr a1, SRC_XEPC
|
||||
mv a2, s0
|
||||
call handle_trap
|
||||
call rt_interrupt_leave
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
/* s0 --> sp */
|
||||
mv sp, s0
|
||||
mv a0, s0
|
||||
call rt_scheduler_do_irq_switch
|
||||
tail rt_hw_context_switch_exit
|
||||
|
||||
#else
|
||||
|
||||
/* switch to from_thread stack */
|
||||
move sp, s0
|
||||
|
||||
/* need to switch new thread */
|
||||
la s0, rt_thread_switch_interrupt_flag
|
||||
lw s2, 0(s0)
|
||||
beqz s2, spurious_interrupt
|
||||
sw zero, 0(s0)
|
||||
|
||||
la s0, rt_interrupt_from_thread
|
||||
LOAD s1, 0(s0)
|
||||
STORE sp, 0(s1)
|
||||
|
||||
la s0, rt_interrupt_to_thread
|
||||
LOAD s1, 0(s0)
|
||||
LOAD sp, 0(s1)
|
||||
|
||||
#endif
|
||||
|
||||
spurious_interrupt:
|
||||
tail rt_hw_context_switch_exit
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-01-30 lizhirui first version
|
||||
*/
|
||||
|
||||
#ifndef __RISCV_H__
|
||||
#define __RISCV_H__
|
||||
|
||||
#include <encoding.h>
|
||||
|
||||
#define __SIZE(bit) (1UL << (bit))
|
||||
#define __MASK(bit) (__SIZE(bit) - 1UL)
|
||||
#define __UMASK(bit) (~(__MASK(bit)))
|
||||
#define __MASKVALUE(value,maskvalue) ((value) & (maskvalue))
|
||||
#define __UMASKVALUE(value,maskvalue) ((value) & (~(maskvalue)))
|
||||
#define __CHECKUPBOUND(value,bit_count) (!(((rt_size_t)value) & (~__MASK(bit_count))))
|
||||
#define __CHECKALIGN(value,start_bit) (!(((rt_size_t)value) & (__MASK(start_bit))))
|
||||
|
||||
#define __PARTBIT(value,start_bit,length) (((value) >> (start_bit)) & __MASK(length))
|
||||
|
||||
#define __ALIGNUP(value,bit) (((value) + __MASK(bit)) & __UMASK(bit))
|
||||
#define __ALIGNDOWN(value,bit) ((value) & __UMASK(bit))
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* Authors:
|
||||
* Anup Patel <anup.patel@wdc.com>
|
||||
*/
|
||||
|
||||
#ifndef __RISCV_IO_H__
|
||||
#define __RISCV_IO_H__
|
||||
|
||||
// which hart (core) is this?
|
||||
static inline uint32_t r_mhartid()
|
||||
{
|
||||
#ifndef RISCV_S_MODE
|
||||
uint32_t x;
|
||||
asm volatile("csrr %0, mhartid" : "=r" (x) );
|
||||
return x;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void __raw_writeb(rt_uint8_t val, volatile void *addr)
|
||||
{
|
||||
asm volatile("sb %0, 0(%1)"
|
||||
:
|
||||
: "r"(val), "r"(addr));
|
||||
}
|
||||
|
||||
static inline void __raw_writew(rt_uint16_t val, volatile void *addr)
|
||||
{
|
||||
asm volatile("sh %0, 0(%1)"
|
||||
:
|
||||
: "r"(val), "r"(addr));
|
||||
}
|
||||
|
||||
static inline void __raw_writel(rt_uint32_t val, volatile void *addr)
|
||||
{
|
||||
asm volatile("sw %0, 0(%1)"
|
||||
:
|
||||
: "r"(val), "r"(addr));
|
||||
}
|
||||
|
||||
#if __riscv_xlen != 32
|
||||
static inline void __raw_writeq(rt_uint64_t val, volatile void *addr)
|
||||
{
|
||||
asm volatile("sd %0, 0(%1)"
|
||||
:
|
||||
: "r"(val), "r"(addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline rt_uint8_t __raw_readb(const volatile void *addr)
|
||||
{
|
||||
rt_uint8_t val;
|
||||
|
||||
asm volatile("lb %0, 0(%1)"
|
||||
: "=r"(val)
|
||||
: "r"(addr));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline rt_uint16_t __raw_readw(const volatile void *addr)
|
||||
{
|
||||
rt_uint16_t val;
|
||||
|
||||
asm volatile("lh %0, 0(%1)"
|
||||
: "=r"(val)
|
||||
: "r"(addr));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline rt_uint32_t __raw_readl(const volatile void *addr)
|
||||
{
|
||||
rt_uint32_t val;
|
||||
|
||||
asm volatile("lw %0, 0(%1)"
|
||||
: "=r"(val)
|
||||
: "r"(addr));
|
||||
return val;
|
||||
}
|
||||
|
||||
#if __riscv_xlen != 32
|
||||
static inline rt_uint64_t __raw_readq(const volatile void *addr)
|
||||
{
|
||||
rt_uint64_t val;
|
||||
|
||||
asm volatile("ld %0, 0(%1)"
|
||||
: "=r"(val)
|
||||
: "r"(addr));
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* FIXME: These are now the same as asm-generic */
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#define __io_rbr() do {} while (0)
|
||||
#define __io_rar() do {} while (0)
|
||||
#define __io_rbw() do {} while (0)
|
||||
#define __io_raw() do {} while (0)
|
||||
|
||||
#define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; })
|
||||
#define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; })
|
||||
#define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; })
|
||||
|
||||
#define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); })
|
||||
#define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); })
|
||||
#define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); })
|
||||
|
||||
#if __riscv_xlen != 32
|
||||
#define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; })
|
||||
#define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); })
|
||||
#endif
|
||||
|
||||
#define __io_br() do {} while (0)
|
||||
#define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory");
|
||||
#define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory");
|
||||
#define __io_aw() do {} while (0)
|
||||
|
||||
#define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; })
|
||||
#define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; })
|
||||
#define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; })
|
||||
|
||||
#define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); })
|
||||
#define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); })
|
||||
#define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); })
|
||||
|
||||
#if __riscv_xlen != 32
|
||||
#define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; })
|
||||
#define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); })
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-01-30 lizhirui first version
|
||||
*/
|
||||
|
||||
#ifndef __STACK_H__
|
||||
#define __STACK_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
struct rt_hw_stack_frame
|
||||
{
|
||||
rt_ubase_t epc; /* epc - epc - program counter */
|
||||
rt_ubase_t ra; /* x1 - ra - return address for jumps */
|
||||
rt_ubase_t xstatus; /* - supervisor/machine/user status register */
|
||||
rt_ubase_t gp; /* x3 - gp - global pointer */
|
||||
rt_ubase_t tp; /* x4 - tp - thread pointer */
|
||||
rt_ubase_t t0; /* x5 - t0 - temporary register 0 */
|
||||
rt_ubase_t t1; /* x6 - t1 - temporary register 1 */
|
||||
rt_ubase_t t2; /* x7 - t2 - temporary register 2 */
|
||||
rt_ubase_t s0_fp; /* x8 - s0/fp - saved register 0 or frame pointer */
|
||||
rt_ubase_t s1; /* x9 - s1 - saved register 1 */
|
||||
rt_ubase_t a0; /* x10 - a0 - return value or function argument 0 */
|
||||
rt_ubase_t a1; /* x11 - a1 - return value or function argument 1 */
|
||||
rt_ubase_t a2; /* x12 - a2 - function argument 2 */
|
||||
rt_ubase_t a3; /* x13 - a3 - function argument 3 */
|
||||
rt_ubase_t a4; /* x14 - a4 - function argument 4 */
|
||||
rt_ubase_t a5; /* x15 - a5 - function argument 5 */
|
||||
rt_ubase_t a6; /* x16 - a6 - function argument 6 */
|
||||
rt_ubase_t a7; /* x17 - s7 - function argument 7 */
|
||||
rt_ubase_t s2; /* x18 - s2 - saved register 2 */
|
||||
rt_ubase_t s3; /* x19 - s3 - saved register 3 */
|
||||
rt_ubase_t s4; /* x20 - s4 - saved register 4 */
|
||||
rt_ubase_t s5; /* x21 - s5 - saved register 5 */
|
||||
rt_ubase_t s6; /* x22 - s6 - saved register 6 */
|
||||
rt_ubase_t s7; /* x23 - s7 - saved register 7 */
|
||||
rt_ubase_t s8; /* x24 - s8 - saved register 8 */
|
||||
rt_ubase_t s9; /* x25 - s9 - saved register 9 */
|
||||
rt_ubase_t s10; /* x26 - s10 - saved register 10 */
|
||||
rt_ubase_t s11; /* x27 - s11 - saved register 11 */
|
||||
rt_ubase_t t3; /* x28 - t3 - temporary register 3 */
|
||||
rt_ubase_t t4; /* x29 - t4 - temporary register 4 */
|
||||
rt_ubase_t t5; /* x30 - t5 - temporary register 5 */
|
||||
rt_ubase_t t6; /* x31 - t6 - temporary register 6 */
|
||||
rt_ubase_t user_sp_exc_stack; /* sscratch - user mode sp/exception stack */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-02-02 lizhirui first version
|
||||
* 2021-02-11 lizhirui fixed gp save/store bug
|
||||
*/
|
||||
|
||||
#ifndef __STACKFRAME_H__
|
||||
#define __STACKFRAME_H__
|
||||
|
||||
#include "cpuport.h"
|
||||
|
||||
.macro SAVE_ALL
|
||||
addi sp, sp, -33 * REGBYTES
|
||||
|
||||
STORE x1, 1 * REGBYTES(sp)
|
||||
|
||||
csrr x1, SRC_XSTATUS
|
||||
STORE x1, 2 * REGBYTES(sp)
|
||||
|
||||
csrr x1, SRC_XEPC
|
||||
STORE x1, 0 * REGBYTES(sp)
|
||||
|
||||
STORE x3, 3 * REGBYTES(sp)
|
||||
STORE x4, 4 * REGBYTES(sp)
|
||||
STORE x5, 5 * REGBYTES(sp)
|
||||
STORE x6, 6 * REGBYTES(sp)
|
||||
STORE x7, 7 * REGBYTES(sp)
|
||||
STORE x8, 8 * REGBYTES(sp)
|
||||
STORE x9, 9 * REGBYTES(sp)
|
||||
STORE x10, 10 * REGBYTES(sp)
|
||||
STORE x11, 11 * REGBYTES(sp)
|
||||
STORE x12, 12 * REGBYTES(sp)
|
||||
STORE x13, 13 * REGBYTES(sp)
|
||||
STORE x14, 14 * REGBYTES(sp)
|
||||
STORE x15, 15 * REGBYTES(sp)
|
||||
STORE x16, 16 * REGBYTES(sp)
|
||||
STORE x17, 17 * REGBYTES(sp)
|
||||
STORE x18, 18 * REGBYTES(sp)
|
||||
STORE x19, 19 * REGBYTES(sp)
|
||||
STORE x20, 20 * REGBYTES(sp)
|
||||
STORE x21, 21 * REGBYTES(sp)
|
||||
STORE x22, 22 * REGBYTES(sp)
|
||||
STORE x23, 23 * REGBYTES(sp)
|
||||
STORE x24, 24 * REGBYTES(sp)
|
||||
STORE x25, 25 * REGBYTES(sp)
|
||||
STORE x26, 26 * REGBYTES(sp)
|
||||
STORE x27, 27 * REGBYTES(sp)
|
||||
STORE x28, 28 * REGBYTES(sp)
|
||||
STORE x29, 29 * REGBYTES(sp)
|
||||
STORE x30, 30 * REGBYTES(sp)
|
||||
STORE x31, 31 * REGBYTES(sp)
|
||||
csrr t0, SRC_XSCRATCH
|
||||
STORE t0, 32 * REGBYTES(sp)
|
||||
.endm
|
||||
|
||||
.macro RESTORE_ALL_ONLY
|
||||
/* resw ra to sepc */
|
||||
LOAD x1, 0 * REGBYTES(sp)
|
||||
csrw SRC_XEPC, x1
|
||||
|
||||
LOAD x1, 2 * REGBYTES(sp)
|
||||
csrw SRC_XSTATUS, x1
|
||||
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
LOAD x3, 3 * REGBYTES(sp)
|
||||
LOAD x4, 4 * REGBYTES(sp)
|
||||
LOAD x5, 5 * REGBYTES(sp)
|
||||
LOAD x6, 6 * REGBYTES(sp)
|
||||
LOAD x7, 7 * REGBYTES(sp)
|
||||
LOAD x8, 8 * REGBYTES(sp)
|
||||
LOAD x9, 9 * REGBYTES(sp)
|
||||
LOAD x10, 10 * REGBYTES(sp)
|
||||
LOAD x11, 11 * REGBYTES(sp)
|
||||
LOAD x12, 12 * REGBYTES(sp)
|
||||
LOAD x13, 13 * REGBYTES(sp)
|
||||
LOAD x14, 14 * REGBYTES(sp)
|
||||
LOAD x15, 15 * REGBYTES(sp)
|
||||
LOAD x16, 16 * REGBYTES(sp)
|
||||
LOAD x17, 17 * REGBYTES(sp)
|
||||
LOAD x18, 18 * REGBYTES(sp)
|
||||
LOAD x19, 19 * REGBYTES(sp)
|
||||
LOAD x20, 20 * REGBYTES(sp)
|
||||
LOAD x21, 21 * REGBYTES(sp)
|
||||
LOAD x22, 22 * REGBYTES(sp)
|
||||
LOAD x23, 23 * REGBYTES(sp)
|
||||
LOAD x24, 24 * REGBYTES(sp)
|
||||
LOAD x25, 25 * REGBYTES(sp)
|
||||
LOAD x26, 26 * REGBYTES(sp)
|
||||
LOAD x27, 27 * REGBYTES(sp)
|
||||
LOAD x28, 28 * REGBYTES(sp)
|
||||
LOAD x29, 29 * REGBYTES(sp)
|
||||
LOAD x30, 30 * REGBYTES(sp)
|
||||
LOAD x31, 31 * REGBYTES(sp)
|
||||
|
||||
addi sp, sp, 33 * REGBYTES
|
||||
.endm
|
||||
|
||||
.macro RESTORE_ALL
|
||||
/* resw ra to sepc */
|
||||
LOAD x1, 0 * REGBYTES(sp)
|
||||
csrw SRC_XEPC, x1
|
||||
|
||||
LOAD x1, 2 * REGBYTES(sp)
|
||||
csrw SRC_XSTATUS, x1
|
||||
|
||||
LOAD x1, 1 * REGBYTES(sp)
|
||||
|
||||
LOAD x3, 3 * REGBYTES(sp)
|
||||
LOAD x4, 4 * REGBYTES(sp)
|
||||
LOAD x5, 5 * REGBYTES(sp)
|
||||
LOAD x6, 6 * REGBYTES(sp)
|
||||
LOAD x7, 7 * REGBYTES(sp)
|
||||
LOAD x8, 8 * REGBYTES(sp)
|
||||
LOAD x9, 9 * REGBYTES(sp)
|
||||
LOAD x10, 10 * REGBYTES(sp)
|
||||
LOAD x11, 11 * REGBYTES(sp)
|
||||
LOAD x12, 12 * REGBYTES(sp)
|
||||
LOAD x13, 13 * REGBYTES(sp)
|
||||
LOAD x14, 14 * REGBYTES(sp)
|
||||
LOAD x15, 15 * REGBYTES(sp)
|
||||
LOAD x16, 16 * REGBYTES(sp)
|
||||
LOAD x17, 17 * REGBYTES(sp)
|
||||
LOAD x18, 18 * REGBYTES(sp)
|
||||
LOAD x19, 19 * REGBYTES(sp)
|
||||
LOAD x20, 20 * REGBYTES(sp)
|
||||
LOAD x21, 21 * REGBYTES(sp)
|
||||
LOAD x22, 22 * REGBYTES(sp)
|
||||
LOAD x23, 23 * REGBYTES(sp)
|
||||
LOAD x24, 24 * REGBYTES(sp)
|
||||
LOAD x25, 25 * REGBYTES(sp)
|
||||
LOAD x26, 26 * REGBYTES(sp)
|
||||
LOAD x27, 27 * REGBYTES(sp)
|
||||
LOAD x28, 28 * REGBYTES(sp)
|
||||
LOAD x29, 29 * REGBYTES(sp)
|
||||
LOAD x30, 30 * REGBYTES(sp)
|
||||
LOAD x31, 31 * REGBYTES(sp)
|
||||
|
||||
//restore user sp
|
||||
LOAD sp, 32 * REGBYTES(sp)
|
||||
.endm
|
||||
|
||||
.macro RESTORE_SYS_GP
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
.endm
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/01 Bernard The first version
|
||||
* 2018/12/27 Jesven Add SMP support
|
||||
* 2020/6/12 Xim Port to QEMU and remove SMP support
|
||||
*/
|
||||
|
||||
#define XSTATUS_FS (3 << 13) /* initial state of FPU, clear to disable */
|
||||
#define XSTATUS_PUM (1 << 18)
|
||||
#include <cpuport.h>
|
||||
|
||||
.global _start
|
||||
.section ".start", "ax"
|
||||
_start:
|
||||
#ifndef RISCV_S_MODE
|
||||
# setup stacks per hart
|
||||
csrr t0, mhartid # read current hart id
|
||||
slli t0, t0, 10 # shift left the hart id by 1024
|
||||
|
||||
# park harts with id != 0
|
||||
csrr a0, mhartid # read current hart id
|
||||
bnez a0, park # if we're not on the hart 0
|
||||
#endif
|
||||
|
||||
csrw SRC_XIE, 0 # clear Interrupt Registers
|
||||
csrw SRC_XIP, 0
|
||||
|
||||
la t0, trap_entry
|
||||
csrw SRC_XTVEC, t0 # set Trap Vector Base Address Register
|
||||
|
||||
/* set to disable FPU */
|
||||
li t0, XSTATUS_FS # close fpu
|
||||
csrc SRC_XSTATUS, t0
|
||||
#ifdef RISCV_S_MODE
|
||||
li t0, XSTATUS_PUM # PUM has no effect
|
||||
csrs SRC_XSTATUS, t0
|
||||
#endif
|
||||
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
la sp, __stack_start__
|
||||
li t0, __STACKSIZE__
|
||||
add sp, sp, t0
|
||||
csrw SRC_XSCRATCH, sp
|
||||
j primary_cpu_entry
|
||||
|
||||
park:
|
||||
wfi
|
||||
j park
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/28 Bernard The unify RISC-V porting code.
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "sbi.h"
|
||||
#include "tick.h"
|
||||
#include <riscv_io.h>
|
||||
#include <encoding.h>
|
||||
|
||||
#define VIRT_CLINT_TIMEBASE_FREQ (10000000)
|
||||
|
||||
static volatile uint64_t time_elapsed = 0;
|
||||
static volatile unsigned long tick_cycles = 0;
|
||||
|
||||
static uint64_t get_ticks()
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"rdtime %0"
|
||||
: "=r"(time_elapsed));
|
||||
return time_elapsed;
|
||||
}
|
||||
|
||||
int tick_isr(void)
|
||||
{
|
||||
int tick_cycles = VIRT_CLINT_TIMEBASE_FREQ / RT_TICK_PER_SECOND;
|
||||
rt_tick_increase();
|
||||
#ifdef RISCV_S_MODE
|
||||
sbi_set_timer(get_ticks() + tick_cycles);
|
||||
#else
|
||||
*(uint64_t*)CLINT_MTIMECMP(r_mhartid()) = *(uint64_t*)CLINT_MTIME + tick_cycles;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sets and enable the timer interrupt */
|
||||
int rt_hw_tick_init(void)
|
||||
{
|
||||
unsigned long interval = VIRT_CLINT_TIMEBASE_FREQ / RT_TICK_PER_SECOND;
|
||||
|
||||
#ifdef RISCV_S_MODE
|
||||
/* Clear the Supervisor-Timer bit in SIE */
|
||||
clear_csr(sie, SIP_STIP);
|
||||
|
||||
/* calculate the tick cycles */
|
||||
// tick_cycles = interval * sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / CLINT_CLOCK_DIV / 1000ULL - 1;
|
||||
tick_cycles = 40000;
|
||||
/* Set timer */
|
||||
sbi_set_timer(get_ticks() + tick_cycles);
|
||||
|
||||
/* Enable the Supervisor-Timer bit in SIE */
|
||||
set_csr(sie, SIP_STIP);
|
||||
#else
|
||||
clear_csr(mie, MIP_MTIP);
|
||||
clear_csr(mip, MIP_MTIP);
|
||||
*(uint64_t*)CLINT_MTIMECMP(r_mhartid()) = *(uint64_t*)CLINT_MTIME + interval;
|
||||
set_csr(mie, MIP_MTIP);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018/10/28 Bernard The unify RISC-V porting code.
|
||||
*/
|
||||
|
||||
#ifndef TICK_H__
|
||||
#define TICK_H__
|
||||
|
||||
//ask the CLINT for a timer interrupt.
|
||||
#define CLINT (0x2000000L)
|
||||
#define CLINT_MTIMECMP(hartid) (CLINT + 0x4000 + 4*(hartid))
|
||||
#define CLINT_MTIME (CLINT + 0xBFF8) // cycles since boot.
|
||||
|
||||
int tick_isr(void);
|
||||
int rt_hw_tick_init(void);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user