初始提交

This commit is contained in:
2024-09-28 14:24:04 +08:00
commit c756587541
5564 changed files with 2413077 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
# OUTPUT type
# 1 - .out
# 2 - .a
# 3 - .so
OUTPUT_TYPE = 1
OUTPUT_NAME = spinlock_test
SUB_DIRS = $(TOPDIR)/common/os_shim/dtestos
EXT_SRC += ../common/dtest_printf.c
# .h files dir
ADD_INCLUDE += $(TOPDIR)/inc/io_lib $(TOPDIR)/inc/driver $(TOPDIR)/driver/inc ../common
# predefined macro
PRE_MARCO += _MODULE_NAME_=\"SPINLOCK\"
PRE_MARCO += _MODULE_VERSION_=\"V1.0.0\"
LD_SCRIPT = link_soc.lds
ADD_LIB = riscv
ADD_LIBDIR = $(TOPDIR)/startup/riscv3
ADD_INCLUDE += $(TOPDIR)/driver/src/hw3/inc
# lib need to ld together
ADD_LIB += driver io_lib
# lib dir
ADD_LIBDIR += $(TOPDIR)/driver $(TOPDIR)/common/io_lib
#####################################################
ifdef TOPDIR
include $(TOPDIR)/build/makefile.cfg
else
include $(CURDIR)/build/makefile.cfg
TOPDIR = $(CURDIR)
export TOPDIR
endif
dump:
$(OBJDUMP) -D -S -l $(OUTPUT_FULL_NAME) > $(OUTPUT_FULL_NAME).dump
# display the obj files and output name
debug:
@echo TOPDIR=$(TOPDIR)
@echo OUTPUT_LIB=$(OUTPUT_FULL_NAME)
@echo DEPS=$(DEPS)
@echo OBJECTS=$(OBJECTS)
@echo SRCS=$(SRCS)
@echo OBJECTS folder=$(foreach dirname, $(SUB_DIRS), $(addprefix $(BIN_DIR)/, $(dirname)))
@echo output_name=$(OUTPUT_FULL_NAME)

View File

@@ -0,0 +1,49 @@
// See LICENSE for license details.
#include "encoding.h"
.section .init
.globl _core_start
.type _core_start,@function
_core_start:
li t0, MSTATUS_MIE
csrc mstatus, t0
li t0, MIP_MTIP
csrc mie, t0
li t0, MIP_MEIP
csrc mie, t0
li t0, 0
csrc mcause, t0
la gp, _gp
la sp, _sp
addi sp, sp, 1024
csrr t1, mhartid
li t0, 2
beq t1, t0, 1f
addi sp, sp, 1024
/* Call global constructors */
//la a0, __libc_fini_array
//call __libc_init_array
/* init function*/
call _init
1:
#ifndef __riscv_float_abi_soft
/* Enable FPU */
li t0, MSTATUS_FS
csrs mstatus, t0
csrr t1, mstatus
and t1, t1, t0
beqz t1, 1f
fssr x0
1:
#endif
/* argc = argv = 0 */
li a0, 0
li a1, 0
call dtest_spinlock_core12_main
#tail exit
1: j 1b

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
# spinlock测试说明文档
## spinlock简介
自旋锁spinlock是为了实现保护共享资源而设计的一个IP实现了在任何时刻某个共享资源只能被一个master访问。
在自旋锁机制中某个master要访问某个共享资源时首先查询该共享资源是否被其他的master访问即是否已经被其他的master锁住如果没有则该master先对该共享资源上锁然后在执行对共享资源的操作在访问结束之后主动释放锁。如果已经被其他的master锁住则一直查询该贡献资源是否已经被其他master释放。
在kl3中自旋锁的本质是一个32bit的寄存器一共16个自旋锁即最多定义16个共享资源每个自旋锁的每个bit对应一个master这些寄存器具有如下特性
* 存在保护寄存器通过写入magic number到指定的寄存器来解除保护仅在解除保护的情况下才能写自旋锁对应的寄存器。
* 在自旋锁寄存器已经有bit被置1的情况下无法再对其他的bit进行置1操作此时必须将所有已经置1的bit清除之后才能重新置位其他的bit。
## spinlock测试例程说明
spinlock测试例程使用到的外设包含spinlock、uart、gp_timer。
* spinlock测试对象用于测试spinlock对贡献资源的保护功能。
* uart使用uart0实现调试信息打印接收case配置信息等与PC的交互功能。
* gp_timer用于定时。
spinlock测试例程遵循自动化测试框架在例程执行之后初始化串口0通过串口发送“start”字段到PC并等待PC发送“config”字段来获取本次需要执行的测试case。
在获取到case组合之后初始化spinlock并根据case组合开始执行测试case。
### case0共享资源保护测试
spinlock功能比较单一因此测试例程比较简单仅以ram中的一个地址作为共享资源事实上这里的串口也是共享资源3个核同时对该地址进行读写操作观察数据是否正确以及core是否一直等待spinlock。具体步骤如下
1. 上电后初始化外设并将ram指定地址的数据清零。
2. 引导core1、core2运行测试代码并记录此时gp_timer的计数值
core1、core2测试代码一致都是运行之后马上申请spinlock在拿到锁之后对ram地址进行读写操作每次在原有数据的基础上加1每次读写操作延时100ms在执行100次读写后释放spinlock并将core挂起。
*为了保证core0最后执行core0在启动core1、core2之后延时一段时间这段时间比core1、core2执行的总时长要更短*
3. core0申请spinlock在拿到锁之后读取gp_timer的时间并判断执行时间与core1、core2延时总时长差距是否过大同时判断ram中的数据是否为其他core累加的值。如果任意条件不满足则判定失败。
测试结果符合预期。core1、core2顺序执行先后顺序不一定core会一直等待spinlock并能正确的保护资源。

View File

@@ -0,0 +1,180 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "chip_reg_base.h"
#include "hw_reg_api.h"
#include "sfc_rf.h"
#include "apb_cache_reg.h"
#include "ahb.h"
#include "cpu.h"
#include "gp_timer.h"
#include "iot_spinlock.h"
#include "iot_clock.h"
#include "dbg_io.h"
#include "iot_errno_api.h"
#include "dtest_printf.h"
#define DTEST_SPINLOCK_CORE0_USE_SPINLOCK 1
#define DTEST_SPINLOCK_RAM_ADDR_CNT AHB_RAM0_BASEADDR
#define DTEST_SPINLOCK_RAM_ADDR_DATA (AHB_RAM0_BASEADDR + 3 * 4)
#define DTEST_SPINLOCK_TEST_NUM SPINLOCK_INDEX_0
#define DTEST_SPINLOCK_TEST_CNT 10000
#define DTEST_SPINLOCK_TIME_DELAY 100
#define DTEST_SPINLOCK_CASE_MUTEX (1 << 0)
extern void _core_start(void);
void dtest_spinlock_core12_main()
{
uint8_t cpu = cpu_get_mhartid();
gp_timer_init();
gp_timer_set(0, 0xffffffff, 0);
gp_timer_start(0);
while (1) {
iot_spinlock_lock(DTEST_SPINLOCK_TEST_NUM, cpu);
// iot_printf("cpu:%d get spinlock\n", cpu);
*(uint32_t*)(DTEST_SPINLOCK_RAM_ADDR_DATA) = (1 << cpu);
*(uint32_t*)(DTEST_SPINLOCK_RAM_ADDR_CNT + cpu * 4) += 1;
iot_delay_us(DTEST_SPINLOCK_TIME_DELAY);
iot_spinlock_unlock(DTEST_SPINLOCK_TEST_NUM, cpu);
}
}
static uint32_t dtest_spinlock_multicore_mutex_test()
{
uint8_t i;
uint32_t data, cnt_0 = 0, cnt_1 = 0, cnt_2 = 0;
uint8_t cpu = cpu_get_mhartid();
uint32_t time_start, time_end, time_delta;
dcase_start("spinlock multicore access test\n");
dprintf("set ram data to 0\n");
for (i = 0; i < 3; i++) {
*(uint32_t *)(DTEST_SPINLOCK_RAM_ADDR_CNT + i * 4) = 0;
}
dprintf("enable core1 and core2\n");
time_start = gp_timer_get_current_val(0);
ahb_core1_set_start((uint32_t)_core_start);
ahb_core1_enable();
ahb_core1_reset();
ahb_core2_set_start((uint32_t)_core_start);
ahb_core2_enable();
ahb_core2_reset();
/* core0 delay sometime to make sure get spinlock last */
iot_delay_us(DTEST_SPINLOCK_TIME_DELAY);
while (1) {
#if DTEST_SPINLOCK_CORE0_USE_SPINLOCK
iot_spinlock_lock(DTEST_SPINLOCK_TEST_NUM, cpu);
// iot_printf("cpu:%d get spinlock\n", cpu);
*(uint32_t*)(DTEST_SPINLOCK_RAM_ADDR_DATA) = (1 << cpu);
*(uint32_t*)(DTEST_SPINLOCK_RAM_ADDR_CNT) += 1;
iot_delay_us(DTEST_SPINLOCK_TIME_DELAY);
#endif
data = *(uint32_t*)(DTEST_SPINLOCK_RAM_ADDR_DATA);
cnt_0 = *(uint32_t*)(DTEST_SPINLOCK_RAM_ADDR_CNT);
cnt_1 = *(uint32_t*)(DTEST_SPINLOCK_RAM_ADDR_CNT + 4);
cnt_2 = *(uint32_t*)(DTEST_SPINLOCK_RAM_ADDR_CNT + 8);
if (data != 0x1 && data != 0x2 && data != 0x4) {
dprintf("ram access conflict, err data:0x%08x\n", data);
i = 0;
break;
}
if (cnt_0 + cnt_1 + cnt_2 >= DTEST_SPINLOCK_TEST_CNT) {
dprintf("execution complete cnt:%d, cpu0:%d, cpu1:%d, cpu2:%d\n",
DTEST_SPINLOCK_TEST_CNT, cnt_0, cnt_1, cnt_2);
break;
}
#if DTEST_SPINLOCK_CORE0_USE_SPINLOCK
iot_spinlock_unlock(DTEST_SPINLOCK_TEST_NUM, cpu);
#endif
}
ahb_core1_disable();
ahb_core1_reset();
ahb_core2_disable();
ahb_core2_reset();
time_end = gp_timer_get_current_val(0);
time_delta = (time_end >= time_start) ? (time_end - time_start) :
(0xffffffff - time_start + time_start);
dprintf("time start:%d, end:%d, delta:%d\n", time_start, time_end, time_delta);
if (i == 0) {
dcase_failed();
return ERR_FAIL;
}
dcase_success();
return ERR_OK;
}
static void dtest_spinlock_main()
{
uint32_t case_group = 0, failed_cnt = 0;
dbg_uart_init();
gp_timer_init();
gp_timer_set(0, 0xffffffff, 0);
gp_timer_start(0);
dconfig();
dstart();
dversion();
if (dtest_get_case_group(&case_group) < 0) {
case_group = 0xffffffff;
}
dprintf("get case group:0x%08X\n", case_group);
iot_spinlock_init();
if (case_group & DTEST_SPINLOCK_CASE_MUTEX) {
if (dtest_spinlock_multicore_mutex_test()) {
failed_cnt++;
}
}
if (failed_cnt) {
dprintf("spinlock dtest failed\n");
} else {
dprintf("spinlock dtest succeed\n");
}
dend();
return;
}
int main(void)
{
dtest_spinlock_main();
return 0;
}