1293 lines
43 KiB
C
1293 lines
43 KiB
C
/**
|
||
* @file debug.c
|
||
* @brief DebugModule
|
||
* @author chenrixin@zh-jieli.net
|
||
* @version 0.1.00
|
||
* @date 2016-10-27
|
||
*/
|
||
#include "system/includes.h"
|
||
#include "asm/debug.h"
|
||
#include "asm/p33.h"
|
||
#include "asm/clock.h"
|
||
#include "asm/crc16.h"
|
||
#include "asm/power_interface.h"
|
||
#include "asm/sfc_norflash_api.h"
|
||
#include "asm/system_reset_reason.h"
|
||
#include "system/boot.h"
|
||
#include "app_config.h"
|
||
#include "fs/fs.h"
|
||
|
||
#define EXPCPTION_IN_SRAM 0 //如果出现死机不复位的情况务必需要打开,防止flash挂了,进入异常函数失败复位不了
|
||
#define DEBUG_UART JL_UART2 //debug串口
|
||
|
||
extern const char *os_current_task_rom();
|
||
extern void log_output_release_deadlock(void);
|
||
extern void exception_irq_handler();
|
||
extern void sdtap_init(u32 ch);
|
||
extern void __wdt_clear(void);
|
||
extern void __cpu_reset(void);
|
||
static u8 debug_index;
|
||
|
||
static const char *const debug_msg[32] = {
|
||
/*0---7*/
|
||
"wdt_timout_err",
|
||
"prp_rd_mmu_err",
|
||
"prp_wr_limit_err",
|
||
"prp_wr_mmu_err",
|
||
"axi_rd_inv",
|
||
"axi_wr_inv",
|
||
"c1_rd_mmu_expt",
|
||
"c0_rd_mmu_expt",
|
||
/*8---15*/
|
||
"c1_wr_mmu_expt",
|
||
"c0_wr_mmu_expt",
|
||
"c1_pc_limit_err_r",
|
||
"c1_wr_limit_err_r",
|
||
"c0_pc_limit_err_r",
|
||
"c0_wr_limit_err_r",
|
||
"dmc_pnd",
|
||
"dbg_pnd",
|
||
/*16---23*/
|
||
"c1_if_bus_inv",
|
||
"c1_rd_bus_inv",
|
||
"c1_wr_bus_inv",
|
||
"c0_if_bus_inv",
|
||
"c0_rd_bus_inv",
|
||
"c0_wr_bus_inv",
|
||
"reserved",
|
||
"reserved",
|
||
/*24---31*/
|
||
"reserved",
|
||
"reserved",
|
||
"reserved",
|
||
"reserved",
|
||
"reserved",
|
||
"reserved",
|
||
"reserved",
|
||
"reserved",
|
||
};
|
||
|
||
static const char *const emu_msg[32] = {
|
||
"reserved", //31
|
||
"reserved", //30
|
||
"reserved", //29
|
||
"reserved", //28
|
||
|
||
"reserved", //27
|
||
"reserved", //26
|
||
"reserved", //25
|
||
"reserved", //24
|
||
|
||
"reserved", //23
|
||
"reserved", //22
|
||
"reserved", //21
|
||
"fpu_ine_err", //20
|
||
|
||
"fpu_huge_err", //19
|
||
"fpu_tiny", //18
|
||
"fpu_inf_err", //17
|
||
"fpu_inv_err", //16
|
||
|
||
"reserved", //15
|
||
"reserved", //14
|
||
"reserved", //13
|
||
"reserved", //12
|
||
|
||
"reserved", //11
|
||
"reserved", //10
|
||
"reserved", //9
|
||
"etm_wp0_err", //8
|
||
|
||
"reserved", //7
|
||
"reserved", //6
|
||
"reserved", //5
|
||
"reserved", //4
|
||
|
||
"stackoverflow", //3
|
||
"div0_err", //2
|
||
"illeg_err", //1
|
||
"misalign_err", //0
|
||
};
|
||
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
|
||
static u32 exception_log_flash_addr sec(.volatile_ram);
|
||
static char exception_log_buf[640];
|
||
|
||
#define LOG_PATH "mnt/sdfile/EXT_RESERVED/log"
|
||
|
||
static int get_exception_log_flash_addr(void)
|
||
{
|
||
struct vfs_attr file_attr;
|
||
|
||
FILE *fp = fopen(LOG_PATH, "r");
|
||
if (fp == NULL) {
|
||
return -1;
|
||
}
|
||
fget_attrs(fp, &file_attr);
|
||
fclose(fp);
|
||
exception_log_flash_addr = file_attr.sclust;
|
||
exception_log_buf[0] = -1;
|
||
sdfile_reserve_zone_read(exception_log_buf, exception_log_flash_addr, sizeof(exception_log_buf), 0);
|
||
if (exception_log_buf[0] != -1) {
|
||
printf("last exception log : \n%s\n", exception_log_buf);
|
||
sdfile_reserve_zone_erase(exception_log_flash_addr, SDFILE_SECTOR_SIZE, 0);
|
||
}
|
||
memset(exception_log_buf, 0, sizeof(exception_log_buf));
|
||
return 0;
|
||
}
|
||
platform_initcall(get_exception_log_flash_addr);
|
||
|
||
static void write_exception_log_to_flash(void *data, u32 len)
|
||
{
|
||
extern void set_os_init_flag(u8 value);
|
||
set_os_init_flag(0);
|
||
extern void norflash_set_write_cpu_hold(u8 hold_en);
|
||
norflash_set_write_cpu_hold(0);
|
||
/* sdfile_reserve_zone_erase(exception_log_flash_addr, SDFILE_SECTOR_SIZE, 0); */
|
||
sdfile_reserve_zone_write(data, exception_log_flash_addr, len, 0);
|
||
}
|
||
#endif
|
||
|
||
//使用此功能必须确保软件上没有出现异常的可能性,电源供电必须足够稳定
|
||
#ifdef CONFIG_EXCEPTION_AUTO_FIX_ENABLE
|
||
|
||
#define FIX_PATH "mnt/sdfile/EXT_RESERVED/fix"
|
||
#define EXCEPTION_FIX_MAGIC 0x3CE8A924
|
||
#define EXCEPTION_FIX_INFO_OFFSET 1024
|
||
#define EXCEPTION_FIX_CRC_OFFSET 512
|
||
#define EXCEPTION_FIX_MAX_STEP 2 //取以下MAX STEP的最大值
|
||
#define EXCEPTION_FIX_VDDIOM_MAX_STEP 2
|
||
#define EXCEPTION_FIX_VDDIOW_MAX_STEP 0
|
||
#define EXCEPTION_FIX_VDC14_MAX_STEP 0
|
||
#define EXCEPTION_FIX_SYSVDD_MAX_STEP 1
|
||
#define EXCEPTION_FIX_SDRAM_CLK_MAX_STEP 1
|
||
|
||
struct exception_fix_info_t {
|
||
u32 sdram_clock;
|
||
u32 sys_clock;
|
||
u8 sdram_clock_fix_step;
|
||
u8 sys_clock_fix_step;
|
||
u8 vddiom;
|
||
u8 vddiom_fix_step;
|
||
u8 vddiow;
|
||
u8 vddiow_fix_step;
|
||
u8 vdc14;
|
||
u8 vdc14_fix_step;
|
||
u8 sysvdd;
|
||
u8 sysvdd_fix_step;
|
||
};
|
||
|
||
static u32 exception_fix_flash_addr sec(.volatile_ram);
|
||
|
||
int exception_auto_fix_config(void)
|
||
{
|
||
struct vfs_attr file_attr;
|
||
struct exception_fix_info_t *info;
|
||
u16 crc;
|
||
|
||
FILE *fp = fopen(FIX_PATH, "r");
|
||
if (fp == NULL) {
|
||
return -1;
|
||
}
|
||
fget_attrs(fp, &file_attr);
|
||
fclose(fp);
|
||
|
||
exception_fix_flash_addr = file_attr.sclust;
|
||
|
||
u32 *buf = zalloc(1024 * 4);
|
||
if (!buf) {
|
||
return -1;
|
||
}
|
||
|
||
if (sdfile_reserve_zone_read(buf, exception_fix_flash_addr, 1024 * 4, 0) != 1024 * 4) {
|
||
goto __exit;
|
||
}
|
||
|
||
info = (struct exception_fix_info_t *)&buf[EXCEPTION_FIX_INFO_OFFSET / sizeof(u32)];
|
||
|
||
crc = CRC16(info, sizeof(struct exception_fix_info_t));
|
||
if (crc != (buf[EXCEPTION_FIX_CRC_OFFSET / sizeof(u32)] & 0xffff) ||
|
||
info->sdram_clock > clk_get("sdram") || info->sdram_clock < 120 * 1000000 ||
|
||
info->vddiom < TCFG_LOWPOWER_VDDIOM_LEVEL || info->vddiom > VDDIOM_VOL_MAX ||
|
||
info->vddiow < TCFG_LOWPOWER_VDDIOW_LEVEL || info->vddiow > VDDIOW_VOL_MAX ||
|
||
info->vdc14 < VDC14_VOL_SEL_LEVEL || info->vdc14 > VDC14_VOL_SEL_MAX ||
|
||
info->sysvdd < SYSVDD_VOL_SEL_LEVEL || info->sysvdd > SYSVDD_VOL_SEL_MAX) {
|
||
memset(info, 0, sizeof(struct exception_fix_info_t));
|
||
info->sdram_clock = clk_get("sdram");
|
||
info->vddiom = TCFG_LOWPOWER_VDDIOM_LEVEL;
|
||
info->vddiow = TCFG_LOWPOWER_VDDIOW_LEVEL;
|
||
info->vdc14 = VDC14_VOL_SEL_LEVEL;
|
||
info->sysvdd = SYSVDD_VOL_SEL_LEVEL;
|
||
}
|
||
|
||
if (buf[0] != 0xffffffff) {
|
||
printf("find exception fix flag");
|
||
|
||
sdfile_reserve_zone_erase(exception_fix_flash_addr, SDFILE_SECTOR_SIZE, 0);
|
||
|
||
#if 0 //此等待延时是为了避免插拔上电不稳定导致的异常从而误触发
|
||
if (crc == (buf[EXCEPTION_FIX_CRC_OFFSET / sizeof(u32)] & 0xffff)) {
|
||
sdfile_reserve_zone_write(&crc, exception_fix_flash_addr + EXCEPTION_FIX_CRC_OFFSET, sizeof(crc), 0);
|
||
sdfile_reserve_zone_write(info, exception_fix_flash_addr + EXCEPTION_FIX_INFO_OFFSET, sizeof(struct exception_fix_info_t), 0);
|
||
os_time_dly(100);
|
||
sdfile_reserve_zone_erase(exception_fix_flash_addr, SDFILE_SECTOR_SIZE, 0);
|
||
}
|
||
#endif
|
||
|
||
if (buf[0] == EXCEPTION_FIX_MAGIC && system_reset_reason_get() == SYS_RST_SOFT) {
|
||
for (int i = 0; i <= EXCEPTION_FIX_MAX_STEP; ++i) {
|
||
if (info->vddiom_fix_step < i && info->vddiom_fix_step < EXCEPTION_FIX_VDDIOM_MAX_STEP) {
|
||
info->vddiom_fix_step++;
|
||
info->vddiom++;
|
||
break;
|
||
}
|
||
if (info->sysvdd_fix_step < i && info->sysvdd_fix_step < EXCEPTION_FIX_SYSVDD_MAX_STEP) {
|
||
info->sysvdd_fix_step++;
|
||
info->sysvdd++;
|
||
break;
|
||
}
|
||
if (info->vddiow_fix_step < i && info->vddiow_fix_step < EXCEPTION_FIX_VDDIOW_MAX_STEP) {
|
||
info->vddiow_fix_step++;
|
||
info->vddiow++;
|
||
break;
|
||
}
|
||
if (info->vdc14_fix_step < i && info->vdc14_fix_step < EXCEPTION_FIX_VDC14_MAX_STEP) {
|
||
info->vdc14_fix_step++;
|
||
info->vdc14++;
|
||
break;
|
||
}
|
||
//最后才降sdram时钟
|
||
if (i == EXCEPTION_FIX_MAX_STEP) {
|
||
if (info->sdram_clock_fix_step < i && info->sdram_clock_fix_step < EXCEPTION_FIX_SDRAM_CLK_MAX_STEP) {
|
||
u32 sdram_clk_tab[4] = {120 * 1000000, 160 * 1000000, 192 * 1000000, 240 * 1000000};
|
||
for (int k = ARRAY_SIZE(sdram_clk_tab) - 1; k >= 0; --k) {
|
||
if (sdram_clk_tab[k] == clk_get("sdram") && info->sdram_clock_fix_step < k) {
|
||
info->sdram_clock_fix_step++;
|
||
info->sdram_clock = sdram_clk_tab[k - info->sdram_clock_fix_step];
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
crc = CRC16(info, sizeof(struct exception_fix_info_t));
|
||
buf[EXCEPTION_FIX_CRC_OFFSET / sizeof(u32)] = crc;
|
||
}
|
||
|
||
if (crc == (buf[EXCEPTION_FIX_CRC_OFFSET / sizeof(u32)] & 0xffff)) {
|
||
sdfile_reserve_zone_write(&crc, exception_fix_flash_addr + EXCEPTION_FIX_CRC_OFFSET, sizeof(crc), 0);
|
||
sdfile_reserve_zone_write(info, exception_fix_flash_addr + EXCEPTION_FIX_INFO_OFFSET, sizeof(struct exception_fix_info_t), 0);
|
||
}
|
||
}
|
||
|
||
if (info->vddiom > TCFG_LOWPOWER_VDDIOM_LEVEL && info->vddiom < VDDIOM_VOL_MAX) {
|
||
printf("exception fix vddiom : %d", info->vddiom);
|
||
VDDIOM_VOL_SEL(info->vddiom);
|
||
}
|
||
if (info->vddiow > TCFG_LOWPOWER_VDDIOW_LEVEL && info->vddiow < VDDIOW_VOL_MAX) {
|
||
printf("exception fix vddiow : %d", info->vddiow);
|
||
VDDIOW_VOL_SEL(info->vddiow);
|
||
}
|
||
if (info->vdc14 > VDC14_VOL_SEL_LEVEL && info->vdc14 < VDC14_VOL_SEL_MAX) {
|
||
printf("exception fix vdc14 : %d", info->vdc14);
|
||
VDC14_VOL_SEL(info->vdc14);
|
||
}
|
||
if (info->sysvdd > SYSVDD_VOL_SEL_LEVEL && info->vdc14 < SYSVDD_VOL_SEL_MAX) {
|
||
printf("exception fix sysvdd : %d", info->sysvdd);
|
||
SYSVDD_VOL_SEL(info->sysvdd);
|
||
}
|
||
if (info->sdram_clock < clk_get("sdram")) {
|
||
printf("exception fix sdram clock : %d", info->sdram_clock);
|
||
sdram_clock_set(info->sdram_clock);
|
||
}
|
||
|
||
__exit:
|
||
free(buf);
|
||
|
||
return 0;
|
||
}
|
||
|
||
static void write_exception_fix_to_flash(void)
|
||
{
|
||
extern void set_os_init_flag(u8 value);
|
||
set_os_init_flag(0);
|
||
|
||
struct vm_info vm = {0};
|
||
norflash_ioctl(NULL, IOCTL_GET_VM_INFO, (u32)&vm);
|
||
|
||
if (!exception_fix_flash_addr || exception_fix_flash_addr < vm.vm_saddr + vm.vm_size) {
|
||
return;
|
||
}
|
||
|
||
u32 magic = EXCEPTION_FIX_MAGIC;
|
||
extern void norflash_set_write_cpu_hold(u8 hold_en);
|
||
norflash_set_write_cpu_hold(0);
|
||
sdfile_reserve_zone_write(&magic, exception_fix_flash_addr, sizeof(magic), 0);
|
||
}
|
||
#endif
|
||
|
||
static void trace_call_stack(int *len)
|
||
{
|
||
for (int c = 0; c < CPU_CORE_NUM; c++) {
|
||
printf("CPU%d %x --> %x --> %x --> %x\n", c,
|
||
q32DSP(c)->ETM_PC3, q32DSP(c)->ETM_PC2,
|
||
q32DSP(c)->ETM_PC1, q32DSP(c)->ETM_PC0);
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
*len += snprintf(exception_log_buf + *len, sizeof(exception_log_buf) - *len, "CPU%d %x --> %x --> %x --> %x\r\n", c,
|
||
q32DSP(c)->ETM_PC3, q32DSP(c)->ETM_PC2,
|
||
q32DSP(c)->ETM_PC1, q32DSP(c)->ETM_PC0);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
#if EXPCPTION_IN_SRAM
|
||
|
||
AT(.volatile_ram_code)
|
||
static char excep_str[] = "\n\n---------------------exception error ------------------------\n";
|
||
AT(.volatile_ram_code)
|
||
static char debug_msg_str[32][32] = {
|
||
/*0---7*/
|
||
"wdt_timout_err",
|
||
"prp_rd_mmu_err",
|
||
"prp_wr_limit_err",
|
||
"prp_wr_mmu_err",
|
||
"axi_rd_inv",
|
||
"axi_wr_inv",
|
||
"c1_rd_mmu_expt",
|
||
"c0_rd_mmu_expt",
|
||
/*8---15*/
|
||
"c1_wr_mmu_expt",
|
||
"c0_wr_mmu_expt",
|
||
"c1_pc_limit_err_r",
|
||
"c1_wr_limit_err_r",
|
||
"c0_pc_limit_err_r",
|
||
"c0_wr_limit_err_r",
|
||
"dmc_pnd",
|
||
"dbg_pnd",
|
||
/*16---23*/
|
||
"c1_if_bus_inv",
|
||
"c1_rd_bus_inv",
|
||
"c1_wr_bus_inv",
|
||
"c0_if_bus_inv",
|
||
"c0_rd_bus_inv",
|
||
"c0_wr_bus_inv",
|
||
"reserved",
|
||
"reserved",
|
||
/*24---31*/
|
||
"reserved",
|
||
"reserved",
|
||
"reserved",
|
||
"reserved",
|
||
"reserved",
|
||
"reserved",
|
||
"reserved",
|
||
"reserved",
|
||
};
|
||
extern void putbyte(char a);
|
||
AT(.volatile_ram_code)
|
||
static void uart_putchar(char a)
|
||
{
|
||
if (DEBUG_UART->CON0 & BIT(0)) {
|
||
if (a == '\n') {
|
||
DEBUG_UART->CON0 |= BIT(13);
|
||
DEBUG_UART->BUF = '\r';
|
||
__asm_csync();
|
||
while ((DEBUG_UART->CON0 & BIT(15)) == 0);
|
||
}
|
||
DEBUG_UART->CON0 |= BIT(13);
|
||
DEBUG_UART->BUF = a;
|
||
__asm_csync();
|
||
while ((DEBUG_UART->CON0 & BIT(15)) == 0);
|
||
}
|
||
}
|
||
AT(.volatile_ram_code)
|
||
static void putbuffer(char *buf)
|
||
{
|
||
while (*buf != 0) {
|
||
uart_putchar(*buf++);
|
||
}
|
||
}
|
||
AT(.volatile_ram_code)
|
||
static void puthex(int hex)
|
||
{
|
||
uart_putchar(' ');
|
||
uart_putchar('0');
|
||
uart_putchar('x');
|
||
for (char i = 28, p = 0, f = 0; i >= 0; i -= 4) {
|
||
p = (char)(hex >> i) & 0xF;
|
||
if (p || f || i == 0) {
|
||
f = 1;
|
||
uart_putchar(p > 9 ? ('A' + (p - 10)) : ('0' + p));
|
||
}
|
||
}
|
||
}
|
||
AT(.volatile_ram_code)
|
||
static void putretis(unsigned int reti, unsigned int rets)
|
||
{
|
||
uart_putchar('r');
|
||
uart_putchar('e');
|
||
uart_putchar('t');
|
||
uart_putchar('i');
|
||
uart_putchar(':');
|
||
puthex(reti);
|
||
uart_putchar('\n');
|
||
uart_putchar('r');
|
||
uart_putchar('e');
|
||
uart_putchar('t');
|
||
uart_putchar('s');
|
||
uart_putchar(':');
|
||
puthex(rets);
|
||
uart_putchar('\n');
|
||
}
|
||
AT(.volatile_ram_code)
|
||
static void putstrandhex(char c0, char c1, char c2, char c3, char c4, char c5, char c6, char c7, char c8, char c9, int hex, int hex1)
|
||
{
|
||
char bf[10];
|
||
bf[0] = c0, bf[1] = c1, bf[2] = c2, bf[3] = c3, bf[4] = c4, bf[5] = c5, bf[6] = c6, bf[7] = c7, bf[8] = c8, bf[9] = c9;
|
||
for (int i = 0; i < sizeof(bf); i++) {
|
||
if (bf[i]) {
|
||
uart_putchar(bf[i]);
|
||
}
|
||
}
|
||
puthex(hex);
|
||
if (hex1) {
|
||
puthex(hex1);
|
||
}
|
||
uart_putchar('\n');
|
||
}
|
||
AT(.volatile_ram_code)
|
||
static void putpchex(int cpu_id)
|
||
{
|
||
q32DSP(!cpu_id)->CMD_PAUSE = -1;
|
||
if (cpu_id) {
|
||
corex2(0)->C0_CON &= ~BIT(3);
|
||
corex2(0)->C0_CON |= BIT(1);
|
||
} else {
|
||
corex2(0)->C1_CON &= ~BIT(3);
|
||
corex2(0)->C1_CON |= BIT(1);
|
||
}
|
||
putstrandhex('e', 'r', 'r', ' ', 'C', 'P', 'U', '0' + cpu_id, 0, 0, cpu_id, 0);
|
||
for (int c = 0; c < CPU_CORE_NUM; c++) {
|
||
uart_putchar('C');
|
||
uart_putchar('P');
|
||
uart_putchar('U');
|
||
uart_putchar('0' + c);
|
||
uart_putchar(':');
|
||
puthex(q32DSP(c)->ETM_PC3);
|
||
uart_putchar(' ');
|
||
uart_putchar('-');
|
||
uart_putchar('-');
|
||
uart_putchar('>');
|
||
puthex(q32DSP(c)->ETM_PC2);
|
||
uart_putchar(' ');
|
||
uart_putchar('-');
|
||
uart_putchar('-');
|
||
uart_putchar('>');
|
||
puthex(q32DSP(c)->ETM_PC1);
|
||
uart_putchar(' ');
|
||
uart_putchar('-');
|
||
uart_putchar('-');
|
||
uart_putchar('>');
|
||
puthex(q32DSP(c)->ETM_PC0);
|
||
uart_putchar('\n');
|
||
}
|
||
}
|
||
AT(.volatile_ram_code)
|
||
static void putdebugreg(void)
|
||
{
|
||
putstrandhex('D', 'B', 'G', '_', 'M', 'S', 'G', ':', 0, 0, corex2(0)->DBG_MSG, 0);
|
||
for (int i = 0, j = 0, num = 0; i < 32; i++) {
|
||
if (BIT(i) & corex2(0)->DBG_MSG) {
|
||
j = 0;
|
||
if (i == 2 || i == 11 || i == 13) {
|
||
num = j == 2 ? corex2(0)->PRP_WR_LIMIT_ERR_NUM : (j == 11 ? corex2(0)->C1_WR_LIMIT_ERR_NUM : corex2(0)->C0_WR_LIMIT_ERR_NUM);
|
||
while (!(num & BIT(j)) && ++j < 8);
|
||
putstrandhex('W', 'R', '_', 'L', 'I', 'M', 'I', 'T', 'L', ':', ((volatile u32 *)(&corex2(0)->WR_LIMIT0_H))[j], ((volatile u32 *)(&corex2(0)->WR_LIMIT0_L))[j]);
|
||
} else if (i == 10 || i == 12) {
|
||
putstrandhex('P', 'C', '_', 'L', 'M', 'T', '0', 'L', '-', 'H', corex2(0)->PC_LIMIT0_L, corex2(0)->PC_LIMIT0_H);
|
||
putstrandhex('P', 'C', '_', 'L', 'M', 'T', '1', 'L', '-', 'H', corex2(0)->PC_LIMIT1_L, corex2(0)->PC_LIMIT1_H);
|
||
} else if (i == 14) {
|
||
putstrandhex('S', 'D', 'R', ' ', 'D', 'B', 'G', 'I', 'N', 'F', JL_SDR->DBG_INFO, 0);
|
||
putstrandhex('S', 'D', 'R', ' ', 'D', 'B', 'G', 'A', 'D', 'R', JL_SDR->DBG_ADR, 0);
|
||
putstrandhex('S', 'D', 'R', ' ', 'D', 'B', 'G', 'S', 'T', 'A', JL_SDR->DBG_START, 0);
|
||
putstrandhex('S', 'D', 'R', ' ', 'D', 'B', 'G', 'E', 'N', 'D', JL_SDR->DBG_END, 0);
|
||
} else if (i == 15) {
|
||
putstrandhex('A', 'X', 'I', '_', 'L', 'M', 'T', 'L', '_', 'H', JL_DBG->LIMIT_L, JL_DBG->LIMIT_H);
|
||
putstrandhex('W', 'R', '_', 'A', 'L', 'W', ' ', 'I', 'D', '0', JL_DBG->WR_ALLOW_ID0, 0);
|
||
putstrandhex('W', 'R', '_', 'A', 'L', 'W', ' ', 'I', 'D', '1', JL_DBG->WR_ALLOW_ID1, 0);
|
||
putstrandhex('W', 'R', '_', 'L', 'M', 'T', ' ', 'I', 'D', ':', JL_DBG->WR_ALLOW_ID0, 0);
|
||
}
|
||
uart_putchar('R');
|
||
uart_putchar('e');
|
||
uart_putchar('a');
|
||
uart_putchar('s');
|
||
uart_putchar('o');
|
||
uart_putchar('n');
|
||
uart_putchar(':');
|
||
putbuffer((char *)&debug_msg_str[i]);
|
||
}
|
||
}
|
||
uart_putchar('\n');
|
||
uart_putchar('\n');
|
||
}
|
||
AT(.volatile_ram_code)
|
||
___interrupt
|
||
static void exception_analyze_sram(void)
|
||
{
|
||
#if 0
|
||
u32 rets, reti, cpu_id;
|
||
__asm__ volatile("%0 = rets ;" : "=r"(rets));
|
||
__asm__ volatile("%0 = reti ;" : "=r"(reti));
|
||
__asm__ volatile("%0 = cnum" : "=r"(cpu_id) ::);
|
||
putbuffer(excep_str);
|
||
putretis(reti, rets);
|
||
putpchex(cpu_id);
|
||
putdebugreg();
|
||
#endif
|
||
__wdt_clear();
|
||
__cpu_reset();
|
||
}
|
||
#endif
|
||
|
||
void exception_analyze(int *sp)
|
||
{
|
||
int len = 0;
|
||
|
||
log_output_release_deadlock();
|
||
|
||
printf("\r\n\r\n---------------------exception error ------------------------\r\n\r\n");
|
||
|
||
u32 cpu_id = current_cpu_id();
|
||
if (cpu_id == 0) {
|
||
q32DSP(1)->CMD_PAUSE = -1;
|
||
corex2(0)->C1_CON &= ~BIT(3) ;
|
||
corex2(0)->C1_CON |= BIT(1) ;
|
||
printf("CPU1 run addr = 0x%x \n", q32DSP(1)->PCRS);
|
||
printf("cpu 0 %s DEBUG_MSG = 0x%x, EMU_MSG = 0x%x C0_CON=%x\n",
|
||
__func__, corex2(0)->DBG_MSG, q32DSP(0)->EMU_MSG, corex2(0)->C0_CON);
|
||
} else {
|
||
q32DSP(0)->CMD_PAUSE = -1;
|
||
corex2(0)->C0_CON &= ~BIT(3) ;
|
||
corex2(0)->C0_CON |= BIT(1) ;
|
||
printf("CPU0 run addr = 0x%x \n", q32DSP(0)->PCRS);
|
||
printf("cpu 1 %s DEBUG_MSG = 0x%x, EMU_MSG = 0x%x C1_CON=%x\n",
|
||
__func__, corex2(0)->DBG_MSG, q32DSP(1)->EMU_MSG, corex2(0)->C1_CON);
|
||
}
|
||
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "CPU%d run addr = 0x%x\r\ncpu %d DEBUG_MSG = 0x%x, EMU_MSG = 0x%x C%d_CON=%x\r\n",
|
||
!cpu_id, q32DSP(!cpu_id)->PCRS, cpu_id, corex2(0)->DBG_MSG, q32DSP(0)->EMU_MSG, cpu_id, cpu_id ? corex2(0)->C1_CON : corex2(0)->C0_CON);
|
||
#endif
|
||
|
||
trace_call_stack(&len);
|
||
|
||
unsigned int reti = sp[16];
|
||
unsigned int rete = sp[17];
|
||
unsigned int retx = sp[18];
|
||
unsigned int rets = sp[19];
|
||
unsigned int psr = sp[20];
|
||
unsigned int icfg = sp[21];
|
||
unsigned int usp = sp[22];
|
||
unsigned int ssp = sp[23];
|
||
unsigned int _sp = sp[24];
|
||
|
||
for (int r = 0; r < 16; r++) {
|
||
printf("R%d: %x\n", r, sp[r]);
|
||
}
|
||
|
||
printf("icfg: %x \n", icfg);
|
||
printf("psr: %x \n", psr);
|
||
printf("rets: 0x%x \n", rets);
|
||
printf("reti: 0x%x \n", reti);
|
||
printf("usp : %x, ssp : %x sp: %x\r\n\r\n", usp, ssp, _sp);
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "icfg: %x\r\n", icfg);
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "psr : %x\r\n", psr);
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "rets: 0x%x\r\n", rets);
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "reti: 0x%x\r\n", reti);
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "usp : %x, ssp : %x sp: %x\r\n", usp, ssp, _sp);
|
||
#endif
|
||
|
||
for (int i = 0; i < 32; i++) {
|
||
if (q32DSP(cpu_id)->EMU_MSG & BIT(i)) {
|
||
printf("%s\r\n", emu_msg[31 - i]);
|
||
if (i == 3) {
|
||
if (os_current_task_rom()) {
|
||
printf("current_task : %s\r\n", os_current_task_rom());
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "%s\r\ncurrent_task : %s\r\n", emu_msg[31 - i], os_current_task_rom());
|
||
#endif
|
||
}
|
||
printf("usp limit %x %x\r\n",
|
||
q32DSP(cpu_id)->EMU_USP_L, q32DSP(cpu_id)->EMU_USP_H);
|
||
printf("ssp limit %x %x\r\n",
|
||
q32DSP(cpu_id)->EMU_SSP_L, q32DSP(cpu_id)->EMU_SSP_H);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (os_current_task_rom()) {
|
||
printf("current_task : %s\r\n", os_current_task_rom());
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "\r\ncurrent_task : %s\r\n", os_current_task_rom());
|
||
#endif
|
||
}
|
||
|
||
printf("\n %s AXI_WR_INV_ID : 0x%x, AXI_RD_INV_ID : 0x%x, PRP_WR_LIMIT_ID : 0x%x, PRP_MMU_ERR_RID : 0x%x, PRP_MMU_ERR_WID : 0x%x\n",
|
||
corex2(0)->AXI_RD_INV_ID == 0X100 ? "CPU0" : "CPU1",
|
||
corex2(0)->AXI_WR_INV_ID,
|
||
corex2(0)->AXI_RD_INV_ID,
|
||
corex2(0)->PRP_WR_LIMIT_ID,
|
||
corex2(0)->PRP_MMU_ERR_RID,
|
||
corex2(0)->PRP_MMU_ERR_WID);
|
||
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "%s AXI_WR_INV_ID : 0x%x, AXI_RD_INV_ID : 0x%x, PRP_WR_LIMIT_ID : 0x%x, PRP_MMU_ERR_RID : 0x%x, PRP_MMU_ERR_WID : 0x%x\r\n",
|
||
corex2(0)->AXI_RD_INV_ID == 0X100 ? "CPU0" : "CPU1",
|
||
corex2(0)->AXI_WR_INV_ID,
|
||
corex2(0)->AXI_RD_INV_ID,
|
||
corex2(0)->PRP_WR_LIMIT_ID,
|
||
corex2(0)->PRP_MMU_ERR_RID,
|
||
corex2(0)->PRP_MMU_ERR_WID);
|
||
#endif
|
||
|
||
int i = 0;
|
||
int j = 0;
|
||
int num = 0;
|
||
|
||
for (i = 0; i < 32; i++) {
|
||
if (BIT(i) & corex2(0)->DBG_MSG) {
|
||
j = 0;
|
||
if (i == 2) {
|
||
printf("PRP_MMU_ERR_WID %x %x\n",
|
||
corex2(0)->PRP_MMU_ERR_WID, corex2(0)->PRP_WR_LIMIT_ERR_NUM);
|
||
num = corex2(0)->PRP_WR_LIMIT_ERR_NUM;
|
||
while (!(num & BIT(j)) && ++j < 8);
|
||
printf("\nWR_LIMITH : 0x%x, WR_LIMITL : 0x%x\n",
|
||
((volatile u32 *)(&corex2(0)->WR_LIMIT0_H))[j],
|
||
((volatile u32 *)(&corex2(0)->WR_LIMIT0_L))[j]);
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "PRP_MMU_ERR_WID %x %x\r\nWR_LIMITH : 0x%x, WR_LIMITL : 0x%x\r\n",
|
||
corex2(0)->PRP_MMU_ERR_WID, corex2(0)->PRP_WR_LIMIT_ERR_NUM,
|
||
((volatile u32 *)(&corex2(0)->WR_LIMIT0_H))[j],
|
||
((volatile u32 *)(&corex2(0)->WR_LIMIT0_L))[j]);
|
||
#endif
|
||
} else if (i == 11) {
|
||
num = corex2(0)->C1_WR_LIMIT_ERR_NUM;
|
||
while (!(num & BIT(j)) && ++j < 8);
|
||
printf("\nWR_LIMITH : 0x%x, WR_LIMITL : 0x%x\n",
|
||
((volatile u32 *)(&corex2(0)->WR_LIMIT0_H))[j],
|
||
((volatile u32 *)(&corex2(0)->WR_LIMIT0_L))[j]);
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "WR_LIMITH : 0x%x, WR_LIMITL : 0x%x\r\n",
|
||
((volatile u32 *)(&corex2(0)->WR_LIMIT0_H))[j],
|
||
((volatile u32 *)(&corex2(0)->WR_LIMIT0_L))[j]);
|
||
#endif
|
||
} else if (i == 13) {
|
||
num = corex2(0)->C0_WR_LIMIT_ERR_NUM;
|
||
while (!(num & BIT(j)) && ++j < 8);
|
||
printf("\nWR_LIMITH : 0x%x, WR_LIMITL : 0x%x\n",
|
||
((volatile u32 *)(&corex2(0)->WR_LIMIT0_H))[j],
|
||
((volatile u32 *)(&corex2(0)->WR_LIMIT0_L))[j]);
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "WR_LIMITH : 0x%x, WR_LIMITL : 0x%x\r\n",
|
||
((volatile u32 *)(&corex2(0)->WR_LIMIT0_H))[j],
|
||
((volatile u32 *)(&corex2(0)->WR_LIMIT0_L))[j]);
|
||
#endif
|
||
} else if (i == 10) {
|
||
printf("\nPC_LIMIT0_H : 0x%x, PC_LIMIT0_L : 0x%x\n",
|
||
corex2(0)->PC_LIMIT0_H, corex2(0)->PC_LIMIT0_L);
|
||
printf("\nPC_LIMIT1_H : 0x%x, PC_LIMIT1_L : 0x%x\n",
|
||
corex2(0)->PC_LIMIT1_H, corex2(0)->PC_LIMIT1_L);
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "PC_LIMIT0_H : 0x%x, PC_LIMIT0_L : 0x%x\r\nPC_LIMIT1_H : 0x%x, PC_LIMIT1_L : 0x%x\r\n",
|
||
corex2(0)->PC_LIMIT0_H, corex2(0)->PC_LIMIT0_L,
|
||
corex2(0)->PC_LIMIT1_H, corex2(0)->PC_LIMIT1_L);
|
||
#endif
|
||
} else if (i == 12) {
|
||
printf("\nPC_LIMIT0_H : 0x%x, PC_LIMIT0_L : 0x%x\n",
|
||
corex2(0)->PC_LIMIT0_H, corex2(0)->PC_LIMIT0_L);
|
||
printf("\nPC_LIMIT1_H : 0x%x, PC_LIMIT1_L : 0x%x\n",
|
||
corex2(0)->PC_LIMIT1_H, corex2(0)->PC_LIMIT1_L);
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "PC_LIMIT0_H : 0x%x, PC_LIMIT0_L : 0x%x\r\nPC_LIMIT1_H : 0x%x, PC_LIMIT1_L : 0x%x\r\n",
|
||
corex2(0)->PC_LIMIT0_H, corex2(0)->PC_LIMIT0_L,
|
||
corex2(0)->PC_LIMIT1_H, corex2(0)->PC_LIMIT1_L);
|
||
#endif
|
||
} else if (i == 14) {
|
||
printf("JL_SDR->DBG_INFO : 0x%x ,err in JL_SDR->DBG_ADR = 0x%x, JL_SDR->DBG_START : 0x%x JL_SDR->DBG_END : 0x%x\n",
|
||
JL_SDR->DBG_INFO, JL_SDR->DBG_ADR, JL_SDR->DBG_START, JL_SDR->DBG_END);
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "JL_SDR->DBG_INFO : 0x%x ,err in JL_SDR->DBG_ADR = 0x%x, JL_SDR->DBG_START : 0x%x JL_SDR->DBG_END : 0x%x\r\n",
|
||
JL_SDR->DBG_INFO, JL_SDR->DBG_ADR, JL_SDR->DBG_START, JL_SDR->DBG_END);
|
||
#endif
|
||
} else if (i == 15) {
|
||
printf("\nAXI_RAM_LIMIT0_H : 0x%x, AXI_RAM_LIMIT0_L : 0x%x\n",
|
||
JL_DBG->LIMIT_H, JL_DBG->LIMIT_L);
|
||
printf("\nJL_DBG->WR_ALLOW_ID0 : 0x%x, JL_DBG->WR_ALLOW_ID1 : 0x%x, JL_DBG->WR_LIMIT_ID : 0x%x\n",
|
||
JL_DBG->WR_ALLOW_ID0, JL_DBG->WR_ALLOW_ID1, JL_DBG->WR_LIMIT_ID);
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "AXI_RAM_LIMIT0_H : 0x%x, AXI_RAM_LIMIT0_L : 0x%x\r\nJL_DBG->WR_ALLOW_ID0 : 0x%x, JL_DBG->WR_ALLOW_ID1 : 0x%x, JL_DBG->WR_LIMIT_ID : 0x%x\r\n",
|
||
JL_DBG->LIMIT_H, JL_DBG->LIMIT_L,
|
||
JL_DBG->WR_ALLOW_ID0, JL_DBG->WR_ALLOW_ID1, JL_DBG->WR_LIMIT_ID);
|
||
#endif
|
||
}
|
||
printf("exception reason : %s \n", debug_msg[i]);
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
len += snprintf(exception_log_buf + len, sizeof(exception_log_buf) - len, "exception reason : %s \n", debug_msg[i]);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
#ifdef CONFIG_EXCEPTION_AUTO_FIX_ENABLE
|
||
write_exception_fix_to_flash();
|
||
#endif
|
||
#ifdef CONFIG_SAVE_EXCEPTION_LOG_IN_FLASH
|
||
printf("exception log buf len : %d\n", len);
|
||
write_exception_log_to_flash(exception_log_buf, len + 1);
|
||
#endif
|
||
|
||
printf("system_reset...\r\n\r\n\r\n");
|
||
log_flush(); //只能在异常中断里调用
|
||
__wdt_clear();
|
||
#ifdef SDTAP_DEBUG
|
||
sdtap_init(2);//防止IO被占据,重新初始化SDTAP
|
||
while (1);
|
||
#endif
|
||
#ifndef CONFIG_FPGA_ENABLE
|
||
__cpu_reset();
|
||
while (1);
|
||
#endif
|
||
}
|
||
|
||
___interrupt
|
||
static void osa_irq_handler(void)
|
||
{
|
||
JL_OSA->CON |= BIT(6);
|
||
puts("----------lsb clk lost-----------\n");
|
||
}
|
||
|
||
static void debug_enter_critical(void)
|
||
{
|
||
if (corex2(0)->DBG_WR_EN & BIT(0)) {
|
||
return;
|
||
}
|
||
corex2(0)->DBG_WR_EN = 0xe7;//set debug reg write enable
|
||
}
|
||
|
||
static void debug_exit_critical(void)
|
||
{
|
||
if (corex2(0)->DBG_WR_EN & BIT(0)) {
|
||
corex2(0)->DBG_WR_EN = 0xe7;//set debug reg write disable
|
||
}
|
||
}
|
||
|
||
static inline int get_debug_index(void)
|
||
{
|
||
for (u8 i = 0; i < 8 ; i++) {
|
||
if (!(debug_index & BIT(i))) {
|
||
return i;
|
||
}
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
static void pc0_rang_limit(void *low_addr, void *high_addr)
|
||
{
|
||
printf("pc0 :%x---%x\n", (u32)low_addr, (u32)high_addr);
|
||
|
||
corex2(0)->DBG_MSG_CLR = 0xffffffff;
|
||
corex2(0)->PC_LIMIT0_H = (u32)high_addr;
|
||
corex2(0)->PC_LIMIT0_L = (u32)low_addr;
|
||
}
|
||
|
||
static void pc1_rang_limit(void *low_addr, void *high_addr)
|
||
{
|
||
printf("pc1 :%x---%x\n", (u32)low_addr, (u32)high_addr);
|
||
|
||
corex2(0)->DBG_MSG_CLR = 0xffffffff;
|
||
corex2(0)->PC_LIMIT1_H = (u32)high_addr;
|
||
corex2(0)->PC_LIMIT1_L = (u32)low_addr;
|
||
}
|
||
|
||
void pc_rang_limit(void *low_addr0, void *high_addr0, void *low_addr1, void *high_addr1)
|
||
{
|
||
debug_enter_critical();
|
||
|
||
if (low_addr0 && high_addr0) {
|
||
pc0_rang_limit(low_addr0, high_addr0);
|
||
}
|
||
|
||
if (low_addr1 && high_addr1) {
|
||
pc1_rang_limit(low_addr1, high_addr1);
|
||
}
|
||
|
||
debug_exit_critical();
|
||
}
|
||
|
||
#define wr_limit_h ((volatile u32 *)&corex2(0)->WR_LIMIT0_H)
|
||
#define wr_limit_l ((volatile u32 *)&corex2(0)->WR_LIMIT0_L)
|
||
#define wr_allow_num ((volatile u32 *)&corex2(0)->WR_ALLOW_ID0)
|
||
|
||
int dev_write_range_limit(int limit_index, void *low_addr, void *high_addr, u32 is_allow_write_out, int dev_id)
|
||
{
|
||
if (limit_index == -1) {
|
||
limit_index = get_debug_index();
|
||
}
|
||
/*
|
||
else if (debug_index & BIT(limit_index)) {
|
||
return debug_index;
|
||
}
|
||
*/
|
||
|
||
if (limit_index == -1) {
|
||
return -1;
|
||
}
|
||
|
||
debug_enter_critical();
|
||
|
||
debug_index |= BIT(limit_index);
|
||
|
||
#if 1
|
||
printf("dev %x write %s low_addr:%x--high_addr:%x\n",
|
||
dev_id,
|
||
is_allow_write_out ? ("allow") : ("limit"),
|
||
(u32)low_addr,
|
||
(u32)high_addr);
|
||
#endif
|
||
|
||
corex2(0)->DBG_MSG_CLR = 0xffffffff;
|
||
|
||
wr_limit_h[limit_index] = (u32)high_addr;
|
||
wr_limit_l[limit_index] = (u32)low_addr;
|
||
|
||
if (dev_id != -1) {
|
||
corex2(0)->PRP_WR_ALLOW_EN |= BIT(limit_index);
|
||
wr_allow_num[limit_index] = dev_id;
|
||
}
|
||
if (!is_allow_write_out) {
|
||
corex2(0)->PRP_OUTLIM_ERR_EN |= BIT(limit_index);
|
||
}
|
||
corex2(0)->PRP_WR_LIMIT_EN |= BIT(limit_index);
|
||
|
||
debug_exit_critical();
|
||
|
||
#if 1
|
||
printf("WR_LIM%dL:%x--WR_LIM%dH:%x--corex2(0)->DBG_CON:%x--PRP_WR_LIMIT_EN:0x%x\n",
|
||
limit_index,
|
||
wr_limit_l[limit_index],
|
||
limit_index,
|
||
wr_limit_h[limit_index],
|
||
corex2(0)->DBG_CON,
|
||
corex2(0)->PRP_WR_LIMIT_EN);
|
||
#endif
|
||
|
||
return 0;
|
||
}
|
||
void all_dev_range_limit(void *addr, int size)//所有外设写进异常(地址:sram+经过cach的sdram)
|
||
{
|
||
int limit_index = 0;
|
||
debug_enter_critical();
|
||
corex2(0)->PRP_WR_LIMIT_EN &= ~BIT(limit_index);
|
||
corex2(0)->DBG_MSG_CLR = 0xffffffff;
|
||
debug_index |= BIT(limit_index);
|
||
corex2(0)->WR_LIMIT0_L = (u32)((u32)addr);
|
||
corex2(0)->WR_LIMIT0_H = (u32)((u32)addr + size);
|
||
corex2(0)->WR_ALLOW_ID0 = 0;
|
||
corex2(0)->PRP_WR_LIMIT_EN = BIT(limit_index);
|
||
debug_exit_critical();
|
||
}
|
||
void all_dev_range_unlimit(void *addr)
|
||
{
|
||
debug_enter_critical();
|
||
corex2(0)->DBG_MSG_CLR = 0xffffffff;
|
||
corex2(0)->WR_LIMIT0_L = 0;
|
||
corex2(0)->WR_LIMIT0_H = 0;
|
||
corex2(0)->WR_ALLOW_ID0 = 0;
|
||
corex2(0)->PRP_WR_LIMIT_EN = 0;
|
||
debug_exit_critical();
|
||
}
|
||
int cpu_write_range_limit(void *low_addr, u32 win_size)
|
||
{
|
||
void *high_addr = low_addr + win_size - 1;
|
||
|
||
int i = get_debug_index();
|
||
if (i == -1) {
|
||
return -1;
|
||
}
|
||
|
||
debug_enter_critical();
|
||
|
||
debug_index |= BIT(i);
|
||
|
||
corex2(0)->DBG_MSG_CLR = 0xffffffff;
|
||
|
||
wr_limit_h[i] = (u32)high_addr;
|
||
wr_limit_l[i] = (u32)low_addr;
|
||
|
||
corex2(0)->C0_WR_LIMIT_EN |= BIT(i);
|
||
corex2(0)->C1_WR_LIMIT_EN |= BIT(i);
|
||
|
||
debug_exit_critical();
|
||
|
||
return 0;
|
||
}
|
||
|
||
void cpu_write_range_unlimit(void *low_addr)
|
||
{
|
||
int i;
|
||
|
||
debug_enter_critical();
|
||
|
||
corex2(0)->DBG_MSG_CLR = 0xffffffff;
|
||
|
||
for (i = 0; i < 8; i++) {
|
||
if (wr_limit_l[i] == (u32)low_addr) {
|
||
wr_limit_h[i] = 0;
|
||
wr_limit_l[i] = 0;
|
||
debug_index &= ~BIT(i);
|
||
corex2(0)->C0_WR_LIMIT_EN &= ~BIT(i);
|
||
corex2(0)->C1_WR_LIMIT_EN &= ~BIT(i);
|
||
}
|
||
}
|
||
|
||
debug_exit_critical();
|
||
}
|
||
|
||
//使用前一定要先完全flush
|
||
int sdr_read_write_range_limit(u32 low_addr, u32 high_addr,
|
||
int id0, int id1,
|
||
u8 rd0_permit, u8 wr0_permit,
|
||
u8 rd1_permit, u8 wr1_permit,
|
||
u8 wr0_over_area_permit, u8 wr1_over_area_permit)
|
||
{
|
||
if (id0 == -1 && id1 == -1) {
|
||
return -1;
|
||
}
|
||
|
||
JL_SDR->DBG_INFO = 0;
|
||
JL_SDR->DBG_INFO |= BIT(13);
|
||
if (id0 != -1) {
|
||
JL_SDR->DBG_INFO |= ((id0 >> 6) & 0xf);
|
||
JL_SDR->DBG_INFO &= ~BIT(4);
|
||
JL_SDR->DBG_INFO &= ~BIT(5);
|
||
JL_SDR->DBG_INFO &= ~BIT(14);
|
||
if (rd0_permit) {
|
||
JL_SDR->DBG_INFO |= BIT(5);
|
||
}
|
||
if (wr0_permit) {
|
||
JL_SDR->DBG_INFO |= BIT(4);
|
||
}
|
||
if (wr0_over_area_permit) {
|
||
JL_SDR->DBG_INFO |= BIT(14);
|
||
}
|
||
}
|
||
if (id1 != -1) {
|
||
JL_SDR->DBG_INFO |= ((id1 >> 6) & 0xf) << 6;
|
||
JL_SDR->DBG_INFO &= ~BIT(10);
|
||
JL_SDR->DBG_INFO &= ~BIT(11);
|
||
JL_SDR->DBG_INFO &= ~BIT(15);
|
||
if (rd1_permit) {
|
||
JL_SDR->DBG_INFO |= BIT(11);
|
||
}
|
||
if (wr1_permit) {
|
||
JL_SDR->DBG_INFO |= BIT(10);
|
||
}
|
||
if (wr1_over_area_permit) {
|
||
JL_SDR->DBG_INFO |= BIT(15);
|
||
}
|
||
}
|
||
JL_SDR->DBG_START = low_addr;
|
||
JL_SDR->DBG_END = high_addr;
|
||
|
||
JL_SDR->DBG_INFO |= BIT(12);
|
||
/* matrt id
|
||
ISC0:0
|
||
ISC1:1
|
||
LSB:2
|
||
JPG:3
|
||
CPI0:4
|
||
CPU1:5
|
||
CACH:6
|
||
DMA_COPY:7
|
||
EMI:8
|
||
IMD:9
|
||
*/
|
||
return 0;
|
||
}
|
||
|
||
int sdr_read_write_range_unlimit(void)
|
||
{
|
||
JL_SDR->DBG_INFO &= ~BIT(12);
|
||
__asm_csync();
|
||
return 0;
|
||
}
|
||
|
||
int axi_ram_write_range_limit(u32 low_addr, u32 high_addr, u32 is_allow_write_out, int id0, int id1)
|
||
{
|
||
#if 0
|
||
printf("axi_ram id0 %x id1 %x write_out %s low_addr:%x--high_addr:%x\n",
|
||
id0, id1,
|
||
is_allow_write_out ? ("allow") : ("limit"),
|
||
low_addr,
|
||
high_addr);
|
||
#endif
|
||
|
||
if (low_addr < 0x1bfe000 || low_addr >= 0x1c00000) {
|
||
return -1;
|
||
}
|
||
|
||
if (high_addr < 0x1bfe000 || high_addr >= 0x1c00000 || high_addr < low_addr) {
|
||
return -1;
|
||
}
|
||
|
||
JL_DBG->LIMIT_H = high_addr;
|
||
JL_DBG->LIMIT_L = low_addr;
|
||
|
||
if (id0 == -1 && id1 == -1) {
|
||
JL_DBG->CON &= ~BIT(1);
|
||
} else {
|
||
if (id0 != -1) {
|
||
JL_DBG->WR_ALLOW_ID0 = id0;
|
||
JL_DBG->CON |= BIT(1);
|
||
}
|
||
if (id1 != -1) {
|
||
JL_DBG->WR_ALLOW_ID1 = id1;
|
||
JL_DBG->CON |= BIT(1);
|
||
}
|
||
if (!is_allow_write_out) {
|
||
JL_DBG->CON |= BIT(2);
|
||
}
|
||
}
|
||
|
||
JL_DBG->CON |= (BIT(6) | BIT(3) | BIT(0));
|
||
|
||
#if 0
|
||
printf("WR_LIML:0x%x--WR_LIMH:0x%x-- JL_DBG->CON:0x%x \n",
|
||
JL_DBG->LIMIT_L,
|
||
JL_DBG->LIMIT_H,
|
||
JL_DBG->CON);
|
||
#endif
|
||
|
||
return 0;
|
||
}
|
||
|
||
void debug_clear(void)
|
||
{
|
||
debug_enter_critical();
|
||
|
||
JL_SDR->DBG_INFO = 0;
|
||
JL_DBG->CON = 0;
|
||
|
||
corex2(0)->DBG_CON = 0;
|
||
corex2(0)->DBG_EN = 0;
|
||
|
||
corex2(0)->C0_WR_LIMIT_EN = 0;
|
||
corex2(0)->C1_WR_LIMIT_EN = 0;
|
||
|
||
corex2(0)->PRP_WR_LIMIT_EN = 0;
|
||
corex2(0)->PRP_WR_ALLOW_EN = 0;
|
||
corex2(0)->PRP_OUTLIM_ERR_EN = 0;
|
||
|
||
corex2(0)->DBG_MSG_CLR = 0xffffffff;
|
||
|
||
q32DSP(0)->EMU_MSG = -1;
|
||
q32DSP(1)->EMU_MSG = -1;
|
||
|
||
debug_index = 0;
|
||
|
||
debug_exit_critical();
|
||
}
|
||
|
||
__attribute__((noinline))
|
||
void sp_ovf_unen(void)
|
||
{
|
||
q32DSP(OS_CPU_ID)->EMU_CON &= ~ BIT(3);
|
||
}
|
||
|
||
__attribute__((noinline))
|
||
void sp_ovf_en(void)
|
||
{
|
||
#ifndef SDTAP_DEBUG
|
||
q32DSP(OS_CPU_ID)->EMU_CON |= BIT(3); //如果用户使用setjmp longjmp, 或者使用sdtap gdb调试 务必要删掉这句话
|
||
#endif
|
||
}
|
||
|
||
void debug_msg_clear(void)
|
||
{
|
||
debug_enter_critical();
|
||
|
||
JL_DBG->CON |= BIT(6);
|
||
JL_SDR->DBG_INFO |= BIT(11);
|
||
corex2(0)->DBG_CON |= (BIT(17) | BIT(18));
|
||
corex2(0)->DBG_MSG_CLR = 0xffffffff;
|
||
|
||
debug_exit_critical();
|
||
}
|
||
|
||
extern u32 cpu0_sstack_begin[];
|
||
extern u32 cpu0_sstack_end[];
|
||
extern u32 cpu1_sstack_begin[];
|
||
extern u32 cpu1_sstack_end[];
|
||
|
||
void debug_init(void)
|
||
{
|
||
u32 cpu_id = current_cpu_id();
|
||
|
||
#if EXPCPTION_IN_SRAM
|
||
request_irq(IRQ_EXCEPTION_IDX, 7, exception_analyze_sram, 0xff);
|
||
#else
|
||
request_irq(IRQ_EXCEPTION_IDX, 7, exception_irq_handler, 0xff);
|
||
#endif
|
||
|
||
JL_OSA->CON = 0x6D; //监控lsb_clk
|
||
request_irq(IRQ_OSA_IDX, 7, osa_irq_handler, 0);
|
||
|
||
#ifdef SDTAP_DEBUG
|
||
sdtap_init(2);
|
||
#endif
|
||
|
||
q32DSP(cpu_id)->EMU_CON = 0;
|
||
|
||
if (cpu_id == 0) {
|
||
debug_clear();
|
||
|
||
debug_enter_critical();
|
||
corex2(0)->DBG_EN |= (0x3f << 16);
|
||
corex2(0)->DBG_EN |= (0x3 << 4);
|
||
debug_exit_critical();
|
||
|
||
q32DSP(0)->EMU_CON &= ~ BIT(3);
|
||
q32DSP(0)->EMU_SSP_L = (int)cpu0_sstack_begin;
|
||
q32DSP(0)->EMU_SSP_H = (int)cpu0_sstack_end;
|
||
q32DSP(0)->EMU_USP_L = 0;
|
||
q32DSP(0)->EMU_USP_H = -1;
|
||
q32DSP(0)->EMU_CON |= BIT(3);
|
||
|
||
printf("cpu 0 usp limit %x %x\r\n", q32DSP(0)->EMU_USP_L, q32DSP(0)->EMU_USP_H);
|
||
printf("cpu 0 ssp limit %x %x\r\n", q32DSP(0)->EMU_SSP_L, q32DSP(0)->EMU_SSP_H);
|
||
} else {
|
||
#if !defined CONFIG_VIDEO_ENABLE && !defined CONFIG_UI_ENABLE && !defined CONFIG_RTOS_AND_MM_LIB_CODE_SECTION_IN_SDRAM && !defined CONFIG_RF_TRIM_CODE_MOVABLE
|
||
pc_rang_limit(&text_rodata_begin, &text_rodata_end,
|
||
&ram_text_rodata_begin, &ram_text_rodata_end);
|
||
#endif
|
||
|
||
q32DSP(1)->EMU_CON &= ~BIT(3);
|
||
q32DSP(1)->EMU_SSP_L = (int)cpu1_sstack_begin;
|
||
q32DSP(1)->EMU_SSP_H = (int)cpu1_sstack_end;
|
||
q32DSP(1)->EMU_USP_L = 0;
|
||
q32DSP(1)->EMU_USP_H = -1;
|
||
q32DSP(1)->EMU_CON |= BIT(3);
|
||
|
||
printf("cpu 1 usp limit %x %x\r\n", q32DSP(1)->EMU_USP_L, q32DSP(1)->EMU_USP_H);
|
||
printf("cpu 1 ssp limit %x %x\r\n", q32DSP(1)->EMU_SSP_L, q32DSP(1)->EMU_SSP_H);
|
||
}
|
||
|
||
/* q32DSP(cpu_id)->EMU_CON |= (0xf << 0) | (0x1 << 8) | (0x1f << 16); */
|
||
/* q32DSP(cpu_id)->EMU_CON |= (0xf << 0) | (0x1 << 8) | (0x06 << 16); */
|
||
|
||
q32DSP(cpu_id)->EMU_CON |= (BIT(2) | BIT(8));
|
||
q32DSP(cpu_id)->ETM_CON |= BIT(0);
|
||
}
|
||
|
||
#if 0
|
||
static u64 cpu_cnt[CPU_CORE_NUM][4] ;
|
||
|
||
void cpu_effic_init(void)
|
||
{
|
||
debug_enter_critical();
|
||
for (u8 j = 0 ; j < CPU_CORE_NUM ; ++j) {
|
||
if (j == 0) {
|
||
corex2(0)->DBG_CON |= (0x7); ///< enable if_inv_en of_inv_en ex_inv_en
|
||
((u32 *)(&cpu_cnt[0][0]))[0] = corex2(0)->C0_IF_UACNTL ;
|
||
((u32 *)(&cpu_cnt[0][0]))[1] = corex2(0)->C0_IF_UACNTH ;
|
||
((u32 *)(&cpu_cnt[0][1]))[0] = corex2(0)->C0_RD_UACNTL ;
|
||
((u32 *)(&cpu_cnt[0][1]))[1] = corex2(0)->C0_RD_UACNTH ;
|
||
((u32 *)(&cpu_cnt[0][2]))[0] = corex2(0)->C0_WR_UACNTL ;
|
||
((u32 *)(&cpu_cnt[0][2]))[1] = corex2(0)->C0_WR_UACNTH ;
|
||
((u32 *)(&cpu_cnt[0][3]))[0] = corex2(0)->C0_TL_CKCNTL ;
|
||
((u32 *)(&cpu_cnt[0][3]))[1] = corex2(0)->C0_TL_CKCNTH ;
|
||
} else {
|
||
corex2(0)->DBG_CON |= (0x7 << 8); ///< enable if_inv_en of_inv_en ex_inv_en
|
||
((u32 *)(&cpu_cnt[1][0]))[0] = corex2(0)->C1_IF_UACNTL ;
|
||
((u32 *)(&cpu_cnt[1][0]))[1] = corex2(0)->C1_IF_UACNTH ;
|
||
((u32 *)(&cpu_cnt[1][1]))[0] = corex2(0)->C1_RD_UACNTL ;
|
||
((u32 *)(&cpu_cnt[1][1]))[1] = corex2(0)->C1_RD_UACNTH ;
|
||
((u32 *)(&cpu_cnt[1][2]))[0] = corex2(0)->C1_WR_UACNTL ;
|
||
((u32 *)(&cpu_cnt[1][2]))[1] = corex2(0)->C1_WR_UACNTH ;
|
||
((u32 *)(&cpu_cnt[1][3]))[0] = corex2(0)->C1_TL_CKCNTL ;
|
||
((u32 *)(&cpu_cnt[1][3]))[1] = corex2(0)->C1_TL_CKCNTH ;
|
||
}
|
||
}
|
||
debug_exit_critical();
|
||
}
|
||
|
||
void cpu_effic_calc(void)
|
||
{
|
||
u64 cpu_cnt_tmp[CPU_CORE_NUM][4] ;
|
||
u64 all_cnt ;
|
||
u64 effic ;
|
||
int i = 0 ;
|
||
int j ;
|
||
static u8 init_flag = 0;
|
||
|
||
if (!init_flag) {
|
||
cpu_effic_init();
|
||
init_flag = 1;
|
||
return; //初始化后需要隔一段时间
|
||
}
|
||
|
||
for (j = 0 ; j < CPU_CORE_NUM ; j++) {
|
||
if (j == 0) {
|
||
((u32 *)(&cpu_cnt_tmp[0][0]))[0] = corex2(0)->C0_IF_UACNTL ;
|
||
((u32 *)(&cpu_cnt_tmp[0][0]))[1] = corex2(0)->C0_IF_UACNTH ;
|
||
((u32 *)(&cpu_cnt_tmp[0][1]))[0] = corex2(0)->C0_RD_UACNTL ;
|
||
((u32 *)(&cpu_cnt_tmp[0][1]))[1] = corex2(0)->C0_RD_UACNTH ;
|
||
((u32 *)(&cpu_cnt_tmp[0][2]))[0] = corex2(0)->C0_WR_UACNTL ;
|
||
((u32 *)(&cpu_cnt_tmp[0][2]))[1] = corex2(0)->C0_WR_UACNTH ;
|
||
((u32 *)(&cpu_cnt_tmp[0][3]))[0] = corex2(0)->C0_TL_CKCNTL ;
|
||
((u32 *)(&cpu_cnt_tmp[0][3]))[1] = corex2(0)->C0_TL_CKCNTH ;
|
||
} else if (j == 1) {
|
||
((u32 *)(&cpu_cnt_tmp[1][0]))[0] = corex2(0)->C1_IF_UACNTL ;
|
||
((u32 *)(&cpu_cnt_tmp[1][0]))[1] = corex2(0)->C1_IF_UACNTH ;
|
||
((u32 *)(&cpu_cnt_tmp[1][1]))[0] = corex2(0)->C1_RD_UACNTL ;
|
||
((u32 *)(&cpu_cnt_tmp[1][1]))[1] = corex2(0)->C1_RD_UACNTH ;
|
||
((u32 *)(&cpu_cnt_tmp[1][2]))[0] = corex2(0)->C1_WR_UACNTL ;
|
||
((u32 *)(&cpu_cnt_tmp[1][2]))[1] = corex2(0)->C1_WR_UACNTH ;
|
||
((u32 *)(&cpu_cnt_tmp[1][3]))[0] = corex2(0)->C1_TL_CKCNTL ;
|
||
((u32 *)(&cpu_cnt_tmp[1][3]))[1] = corex2(0)->C1_TL_CKCNTH ;
|
||
}
|
||
}
|
||
|
||
const char *CNTLX[] = {"IF_UACNT", "RD_UACNT", "WR_UACNT", "TL_CKCNT"};
|
||
|
||
for (j = 0 ; j < CPU_CORE_NUM ; j++) {
|
||
all_cnt = 0 ;
|
||
u64 ddd = cpu_cnt_tmp[j][3] - cpu_cnt[j][3] ;
|
||
/*printf("cpu[%d] TL_CKCNT = %d \r\n", j, ddd);*/
|
||
|
||
for (i = 0 ; i < 3 ; i++) {
|
||
/*printf("0x%08x%08x , 0x%08x%08x \r\n" ,((u32*) &cpu_cnt[j][i])[1],((u32*) &cpu_cnt[j][i])[0] ,((u32*)&cpu_cnt_tmp[j][i])[1], ((u32*)&cpu_cnt_tmp[j][i])[0]);*/
|
||
effic = cpu_cnt_tmp[j][i] - cpu_cnt[j][i] ;
|
||
/*printf("sub = %08x%08x \r\n" ,((u32*)&effic)[1] ,((u32*)&effic)[0] );*/
|
||
all_cnt += effic ;
|
||
/*printf("cpu[%d] %s = %d \r\n", j, CNTLX[i], effic);*/
|
||
printf("cpu[%d] %s effic = %llu%% \r\n", j, CNTLX[i], effic * 100 / ddd) ;
|
||
}
|
||
|
||
/*printf("0x%08x%08x , 0x%08x%08x \r\n" ,((u32*) &cpu_cnt[j][i])[1],((u32*) &cpu_cnt[j][i])[0] ,((u32*)&cpu_cnt_tmp[j][i])[1], ((u32*)&cpu_cnt_tmp[j][i])[0]);*/
|
||
|
||
effic = cpu_cnt_tmp[j][3] - cpu_cnt[j][3] ;
|
||
|
||
/*printf("all cnt = %08x%08x \r\n" ,((u32*)&effic)[1] ,((u32*)&effic)[0]);*/
|
||
effic = (all_cnt * 100) / effic ;
|
||
printf("cpu %d TL_CKCNT effic %d%% \r\n", j, (u32)effic) ;
|
||
memcpy((void *)&cpu_cnt[j], (void *)&cpu_cnt_tmp[j], sizeof(u64) * 4) ;
|
||
}
|
||
}
|
||
#endif
|