418 lines
11 KiB
C
418 lines
11 KiB
C
/****************************************************************************
|
||
|
||
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 "iot_bitops.h"
|
||
#include "dtest_printf.h"
|
||
#include "cpu.h"
|
||
#include "ahb.h"
|
||
|
||
#if HW_PLATFORM > HW_PLATFORM_SIMU
|
||
#include "dbg_io.h"
|
||
#endif
|
||
|
||
#include "watchdog.h"
|
||
#include "chip_reg_base.h"
|
||
#include "ahb_rf_s.h"
|
||
|
||
#include "uart.h"
|
||
#include "strformat.h"
|
||
#include "uart_e.h"
|
||
|
||
extern iot_wdg_info g_wdg_info[3];
|
||
extern iot_wdg_info g_wdg_timeout;
|
||
extern int g_feed_dog[3];
|
||
|
||
extern void _core_start(void);
|
||
extern void _start(void);
|
||
|
||
typedef struct _wdg_typedef
|
||
{
|
||
uint32_t RVER1;
|
||
struct
|
||
{
|
||
uint32_t rver1 : 7;
|
||
uint32_t fullrst_cnt_en : 1;
|
||
uint32_t rver2 : 7;
|
||
uint32_t cpurst_cnt_en : 1;
|
||
uint32_t rver3 : 7;
|
||
uint32_t timeout_cnt_en : 1;
|
||
uint32_t rver4 : 7;
|
||
uint32_t cnt_en : 1;
|
||
}CTL0;
|
||
struct
|
||
{
|
||
uint32_t rver1 : 7;
|
||
uint32_t fullrst_inter_en : 1;
|
||
uint32_t rver2 : 7;
|
||
uint32_t cpurst_inter_en : 1;
|
||
uint32_t rver3 : 7;
|
||
uint32_t timeout_inter_en : 1;
|
||
uint32_t rver4 : 7;
|
||
uint32_t inter_en : 1;
|
||
}CTL1;
|
||
uint32_t CTL2;
|
||
uint32_t CNT;
|
||
uint32_t CMP;
|
||
|
||
struct
|
||
{
|
||
uint32_t rver1 : 8;
|
||
uint32_t fullrst_cnt : 8;
|
||
uint32_t cputrst_cnt : 8;
|
||
uint32_t timeout_cnt : 8;
|
||
}CNTS;
|
||
struct
|
||
{
|
||
uint32_t rver1 : 8;
|
||
uint32_t fullrst_cmp : 8;
|
||
uint32_t cputrst_cmp : 8;
|
||
uint32_t timeout_cmp : 8;
|
||
}CMPS;
|
||
struct
|
||
{
|
||
uint32_t rver1 : 24;
|
||
uint32_t cpurst_width : 8;
|
||
}CPURST_WIDTH;
|
||
|
||
uint32_t RVER2[0x60];
|
||
uint32_t PROTECT_CODE;
|
||
|
||
|
||
}wdg_typdef;
|
||
|
||
typedef enum
|
||
{
|
||
TEST_MODE_CPURST = 0,
|
||
TEST_MODE_FULLRST,
|
||
}TEST_MODE;
|
||
|
||
|
||
|
||
//wdg_typdef *WDG
|
||
|
||
static volatile ahb_lite_reg_t *ahb_base =
|
||
(volatile ahb_lite_reg_t *)AHB_REG_LITE_BASEADDR;
|
||
|
||
extern struct uart_ctrl uart_e_ctrl;
|
||
#define my_g_uart_ctrl uart_e_ctrl
|
||
|
||
void delay_sometime(void) {
|
||
uint32_t loop;
|
||
loop = 0;
|
||
while(loop++ < 1000000) __asm volatile ("nop\n");
|
||
}
|
||
|
||
void core_print_regs(UART_PORT port, char *buf, int len, uint32_t cur_cpu) {
|
||
|
||
uint32_t pc;
|
||
uint32_t rst_flag;
|
||
int str_len;
|
||
uint32_t *reg = (uint32_t *)WDG0_REG_BASEADDR ;
|
||
|
||
switch(cur_cpu) {
|
||
case 0:
|
||
pc = ahb_base->cpu0_start_pc.w;
|
||
reg = (uint32_t *)WDG0_REG_BASEADDR ;
|
||
break;
|
||
case 1:
|
||
pc = ahb_base->cpu1_start_pc.w;
|
||
reg = (uint32_t *)WDG1_REG_BASEADDR ;
|
||
break;
|
||
case 2:
|
||
pc = ahb_base->cpu2_start_pc.w;
|
||
reg = (uint32_t *)WDG2_REG_BASEADDR ;
|
||
break;
|
||
|
||
}
|
||
|
||
rst_flag = *( (uint32_t *)(0x40000000 + 0x008C) );
|
||
|
||
str_len = iot_snprintf(buf, len, "cpu:%d,ctl0:%08x,ctl1:%08x,cnt:%08x,\
|
||
cmp:%08x,cnts:%08x,cmps:%08x,width:%08x,pc=%08x,rst_flag=%08x\r\n",
|
||
cur_cpu, *(reg + 1),*(reg + 2), *(reg + 4), *(reg + 5), *(reg+6), *(reg+7),
|
||
*(reg+8), pc , rst_flag);
|
||
|
||
my_g_uart_ctrl.puts(port, (uint8_t*)buf, str_len);
|
||
}
|
||
|
||
/*
|
||
port:输出日志的串口编号
|
||
pin_num:对应串口的txd引脚编号
|
||
buf:输出日志时用的缓存地址
|
||
buf_len:缓存大小
|
||
mode :测试cpurst还是fullrst
|
||
*/
|
||
void core_wdg_test_loop(UART_PORT port, int pin_num, char *buf, int buf_len,
|
||
TEST_MODE mode) {
|
||
uint32_t cnt = 0;
|
||
uint32_t cur_cpu = cpu_get_mhartid();
|
||
|
||
// UART0 init
|
||
my_g_uart_ctrl.init(port);
|
||
my_g_uart_ctrl.config(port, 115200, UART_DATA_8_BITS, UART_STOP_BITS_1,
|
||
UART_PARITY_DISABLE);
|
||
iot_uart_set_pin(port, 0xff, pin_num);
|
||
|
||
my_g_uart_ctrl.puts(port, (uint8_t*)"00000\r\n", 7);
|
||
|
||
int str_len ;
|
||
|
||
// print start
|
||
str_len = iot_snprintf(buf, buf_len, "CPU %d : Start 0000!!!\r\n", cur_cpu);
|
||
my_g_uart_ctrl.puts(port, (uint8_t*)buf, str_len);
|
||
|
||
delay_sometime();
|
||
|
||
//wdg init
|
||
core_print_regs(port, buf, buf_len, cur_cpu);
|
||
|
||
wdg_deinit(cur_cpu);
|
||
|
||
wdg_init(cur_cpu);
|
||
|
||
if (TEST_MODE_CPURST == mode) {
|
||
wdg_set_cmp(cur_cpu, 50000);//SET_WDG_INTC_CMP);
|
||
wdg_set_timeout_cmp(cur_cpu, 15);//SET_WDG_TIMEOUT_CMP);
|
||
wdg_set_cpurst_cmp(cur_cpu, 5);//SET_WDG_CPURST_CMP );
|
||
wdg_set_fullrst_cmp(cur_cpu, 10);//SET_WDG_FULLRST_CMP);
|
||
} else if (TEST_MODE_FULLRST == mode) {
|
||
wdg_set_cmp(cur_cpu, 50000);//SET_WDG_INTC_CMP);
|
||
wdg_set_timeout_cmp(cur_cpu, 15);//SET_WDG_TIMEOUT_CMP);
|
||
wdg_set_cpurst_cmp(cur_cpu, 10);//SET_WDG_CPURST_CMP );
|
||
wdg_set_fullrst_cmp(cur_cpu, 5);//SET_WDG_FULLRST_CMP);
|
||
} else {
|
||
|
||
}
|
||
|
||
while(1) {
|
||
//delay_sometime();
|
||
//core_print_regs(port, buf, buf_len, cur_cpu);
|
||
|
||
if (g_feed_dog[cur_cpu] == 1 && cnt < 5) {
|
||
|
||
str_len = iot_snprintf(buf, buf_len,
|
||
"cnt %d, feed dog cpu%d\r\n", cnt, cur_cpu);
|
||
|
||
my_g_uart_ctrl.puts(port, (uint8_t*)buf, str_len);
|
||
|
||
wdg_feed_dog(cur_cpu);
|
||
|
||
iot_interrupt_unmask(g_wdg_info[cur_cpu].handle);
|
||
g_feed_dog[cur_cpu] = 0;
|
||
cnt++;
|
||
}
|
||
}
|
||
}
|
||
|
||
void core_working_loop(UART_PORT port, int pin_num, char *buf, int buf_len) {
|
||
|
||
uint32_t cur_cpu = cpu_get_mhartid();
|
||
|
||
// UART init
|
||
my_g_uart_ctrl.init(port);
|
||
my_g_uart_ctrl.config(port, 115200, UART_DATA_8_BITS, UART_STOP_BITS_1,
|
||
UART_PARITY_DISABLE);
|
||
|
||
iot_uart_set_pin(port, 0xff, pin_num);
|
||
|
||
int str_len ;
|
||
int inc = 0;
|
||
|
||
while(1) {
|
||
str_len = iot_snprintf(buf, buf_len, "CPU %d : %d\r\n", cur_cpu, inc);
|
||
my_g_uart_ctrl.puts(port, (uint8_t*)buf, str_len);
|
||
inc ++;
|
||
if(inc > 10000)
|
||
inc = 0;
|
||
delay_sometime();
|
||
}
|
||
}
|
||
|
||
/*
|
||
WDG_TEST_FUNC 可定义如下些值
|
||
0:仅core0 看门狗cpurst
|
||
1:core0 rst core1 core2 正常运行
|
||
2:core1 rst core0 core2 正常运行
|
||
3:core2 rst core0 core1 正常运行
|
||
4:core0 rst core1 rst core2 rst
|
||
*/
|
||
#define WDG_TEST_FUNC 1
|
||
/*
|
||
TEST_MODE_CPURST
|
||
TEST_MODE_FULLRST
|
||
*/
|
||
|
||
/*
|
||
由于当前时在FPGA上跑的,fullrst 后会对start pc复位成 20000
|
||
而当前这个地方没有东西,复位过去没法执行,也就是当前没法测
|
||
fullrst
|
||
|
||
由于core_start.S中调用了_init 函数,它会重新初始化中断
|
||
导致core2 的cpurst不再响应,若要测试它请将core_start.s中
|
||
的
|
||
li t0, 2
|
||
改成
|
||
li t0, 1
|
||
|
||
*/
|
||
|
||
|
||
#define CUR_TEST_MODE TEST_MODE_CPURST
|
||
|
||
#define UART0_GPIO 6
|
||
#define UART1_GPIO 8
|
||
#define UART2_GPIO 36
|
||
|
||
|
||
int main(void) {
|
||
uint32_t cur_cpu = cpu_get_mhartid();
|
||
dbg_uart_init();
|
||
// 26 27 28
|
||
#if (WDG_TEST_FUNC == 0)
|
||
|
||
static char buf[500];
|
||
if (0 == cur_cpu) {
|
||
ahb_core0_set_start((uint32_t) _start);
|
||
} else if (1 == cur_cpu) {
|
||
ahb_core1_set_start((uint32_t) _start);
|
||
} else {
|
||
ahb_core2_set_start((uint32_t) _start);
|
||
}
|
||
core_wdg_test_loop(UART_PT1, UART1_GPIO, buf, sizeof(buf), CUR_TEST_MODE);
|
||
|
||
#elif (WDG_TEST_FUNC == 1) //
|
||
|
||
if (0 == cur_cpu) {
|
||
static char buf0[500];
|
||
|
||
//core1没有启动时才启动,否则core1就相当于重启了,等同于被复位
|
||
if ((ahb_base->ahb_reg0.w & (1 << AHB_RV5_CORE1_RST))) {
|
||
ahb_core1_set_start((uint32_t) _core_start);
|
||
ahb_core1_enable();
|
||
ahb_core1_reset();
|
||
}
|
||
ahb_core0_set_start((uint32_t) _start);
|
||
core_wdg_test_loop(UART_PT1, UART1_GPIO, buf0, sizeof(buf0), CUR_TEST_MODE);
|
||
} else if(1 == cur_cpu) {
|
||
static char buf[500];
|
||
|
||
ahb_core2_set_start((uint32_t) _core_start);
|
||
ahb_core2_enable();
|
||
ahb_core2_reset();
|
||
|
||
while(1) {
|
||
core_working_loop(UART_PT0, UART0_GPIO, buf, sizeof(buf));
|
||
}
|
||
} else {
|
||
static char buf2[500];
|
||
while(1) {
|
||
core_working_loop(UART_PT2, UART2_GPIO, buf2, sizeof(buf2) );
|
||
}
|
||
}
|
||
|
||
#elif (WDG_TEST_FUNC == 2)
|
||
if (0 == cur_cpu) {
|
||
static char buf0[500];
|
||
ahb_core1_set_start((uint32_t) _core_start);
|
||
ahb_core1_enable();
|
||
ahb_core1_reset();
|
||
|
||
while(1) {
|
||
core_working_loop(UART_PT0, UART0_GPIO, buf0, sizeof(buf0));
|
||
}
|
||
} else if(1 == cur_cpu) {
|
||
static char buf[500];
|
||
|
||
if ((ahb_base->ahb_reg0.w & (1 << AHB_RV5_CORE2_RST))) {
|
||
ahb_core2_set_start((uint32_t) _core_start);
|
||
ahb_core2_enable();
|
||
ahb_core2_reset();
|
||
}
|
||
core_wdg_test_loop(UART_PT1, UART1_GPIO, buf, sizeof(buf), CUR_TEST_MODE);
|
||
}else {
|
||
static char buf2[500];
|
||
while(1) {
|
||
core_working_loop(UART_PT2, UART2_GPIO, buf2, sizeof(buf2) );
|
||
}
|
||
}
|
||
#elif (WDG_TEST_FUNC == 3)
|
||
if (0 == cur_cpu) {
|
||
static char buf0[500];
|
||
ahb_core1_set_start((uint32_t) _core_start);
|
||
ahb_core1_enable();
|
||
ahb_core1_reset();
|
||
|
||
while(1) {
|
||
core_working_loop(UART_PT0, UART0_GPIO, buf0, sizeof(buf0));
|
||
}
|
||
} else if(1 == cur_cpu) {
|
||
static char buf[500];
|
||
|
||
ahb_core2_set_start((uint32_t) _core_start);
|
||
|
||
ahb_core2_enable();
|
||
ahb_core2_reset();
|
||
|
||
while(1) {
|
||
core_working_loop(UART_PT2, UART2_GPIO, buf, sizeof(buf));
|
||
}
|
||
} else {
|
||
static char buf2[500];
|
||
core_wdg_test_loop(UART_PT1, UART1_GPIO, buf2, sizeof(buf2), CUR_TEST_MODE);
|
||
}
|
||
#elif (WDG_TEST_FUNC == 4)
|
||
iot_interrupt_init();
|
||
if (0 == cur_cpu) {
|
||
static char buf0[500];
|
||
ahb_core0_set_start((uint32_t) _start);
|
||
if ((ahb_base->ahb_reg0.w & (1 << AHB_RV5_CORE1_RST))) {
|
||
ahb_core1_set_start((uint32_t) _core_start);
|
||
ahb_core1_enable();
|
||
ahb_core1_reset();
|
||
}
|
||
while(1) {
|
||
|
||
core_wdg_test_loop(UART_PT0, UART0_GPIO, buf0, sizeof(buf0), CUR_TEST_MODE);
|
||
}
|
||
} else if(1 == cur_cpu) {
|
||
static char buf[500];
|
||
if((ahb_base->ahb_reg0.w & (1 << AHB_RV5_CORE2_RST))) {
|
||
ahb_core2_set_start((uint32_t) _core_start);
|
||
ahb_core2_enable();
|
||
ahb_core2_reset();
|
||
}
|
||
while(1) {
|
||
core_wdg_test_loop(UART_PT2, UART2_GPIO, buf, sizeof(buf), CUR_TEST_MODE);
|
||
}
|
||
}
|
||
else {
|
||
static char buf2[500];
|
||
core_wdg_test_loop(UART_PT1, UART1_GPIO, buf2, sizeof(buf2), CUR_TEST_MODE);
|
||
}
|
||
|
||
#else
|
||
|
||
|
||
|
||
|
||
#endif
|
||
while(1) {
|
||
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|