383 lines
11 KiB
C
383 lines
11 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/mman.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "pet_sm_mgt.h"
|
|
#include "msg_transfer_mem.h"
|
|
#include "ospHeartbeat.h"
|
|
#include "ospSem.h"
|
|
//#include "ospSoftQue.h"
|
|
//#include "ospMsg.h"
|
|
//#include "ospDbg.h"
|
|
#include "ucp_printf.h"
|
|
#include "ospDelay.h"
|
|
#include "ospDump.h"
|
|
#include "ospCfgToBin.h"
|
|
#include "ospSwTimer.h"
|
|
|
|
#define RESTART_REGISTER_LEN (0x1000)
|
|
#define RESTART_REGISTER_SUBCTRL0_BASE (0x04A88000)
|
|
#define RESTART_REGISTER_SUBCTRL1_BASE (0x04AD8000)
|
|
#define RESTART_REGISTER_SUBCTRL2_BASE (0x04B28000)
|
|
#define RESTART_REGISTER_SUBCTRL3_BASE (0x04B78000)
|
|
#define RESTART_REGISTER_RST_CFG_BASE (0x04550000)
|
|
|
|
|
|
#define OSP_HEARTBEAT_NAME "OspHeartbeatTimer"
|
|
#define OSP_HEARTBEAT_TMR_OUT (1000) /* 1000ms->1s */
|
|
#define OSP_HB_MAX_CORE_NUM 2//(12) /* 监测的最多核数 */
|
|
#define OSP_HB_MAX_COUNTER (3) /* 失信计数最大值 */
|
|
|
|
#define OSP_HEARTBEAT_OFF (1) /* 不检测心跳 */
|
|
#define OSP_HEARTBEAT_ON (0) /* 检测心跳 */
|
|
|
|
#define HB_NO_CHECK (1) /* 不再被检测 */
|
|
#define HB_CHECK (0) /* 被检测 */
|
|
|
|
static uint8_t gsu8OspHeartbeatSwitch = 0; /* 默认检测心跳 */
|
|
static OspHeartbeatInfo_t gsstOspHeartbeatCounter[OSP_HB_MAX_CORE_NUM];
|
|
|
|
uint8_t* gu8virRegAddr = NULL;
|
|
uint8_t* gu8VirSubctrlAddr = NULL;
|
|
uint8_t* gu8VirRstCfgAddr = NULL;
|
|
|
|
uint32_t g32heartbeatCounter[MAX_NUM_SPU] = {0};
|
|
|
|
uint32_t get_heartbeat_status(void)
|
|
{
|
|
volatile uint32_t vu32counter = 0;
|
|
uint32_t u32coreHeartbeatBitmap = SUCCESS;
|
|
uint32_t u32coreHeartbeatMask = 0xEFF;
|
|
uint8_t u8loop = 0;
|
|
|
|
PetSmLocalMgt_t* pPetSmLocalMgt = get_pet_sm_local_mgt();
|
|
UcpHandshake_t* pHandshake = pPetSmLocalMgt->pHandshake;
|
|
|
|
for (u8loop = 0; u8loop < MAX_NUM_SPU; u8loop++)
|
|
{
|
|
vu32counter = pHandshake->heartbeat[u8loop];
|
|
if (vu32counter == g32heartbeatCounter[u8loop])
|
|
{
|
|
u32coreHeartbeatBitmap |= (1 << u8loop);
|
|
}
|
|
|
|
/* update */
|
|
g32heartbeatCounter[u8loop] = vu32counter;
|
|
}
|
|
|
|
u32coreHeartbeatBitmap &= u32coreHeartbeatMask;
|
|
|
|
UCP_PRINT_LOG("[get_heartbeat_status]: HeartbeatBitMap = 0x%x\r\n", u32coreHeartbeatBitmap);
|
|
|
|
return u32coreHeartbeatBitmap;
|
|
}
|
|
|
|
|
|
/* 获取对应核的心跳计数 */
|
|
uint32_t OspGetHeartbeat(uint8_t u8CoreId)
|
|
{
|
|
PetSmLocalMgt_t* pPetSmLocalMgt = get_pet_sm_local_mgt();
|
|
UcpHandshake_t* pHandshake = pPetSmLocalMgt->pHandshake;
|
|
return pHandshake->heartbeat[u8CoreId];
|
|
}
|
|
|
|
|
|
/* 重启寄存器 */
|
|
int8_t OspRestartRegister(uint8_t u8CoreId)
|
|
{
|
|
uint64_t u64SubctrlAddr = 0;
|
|
int iOspRestartFd = -1;
|
|
int8_t i8ApcId = -1;
|
|
|
|
switch(u8CoreId)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
{
|
|
i8ApcId = 0;
|
|
u64SubctrlAddr = RESTART_REGISTER_SUBCTRL0_BASE;
|
|
break;
|
|
}
|
|
case 2:
|
|
case 3:
|
|
{
|
|
i8ApcId = 1;
|
|
u64SubctrlAddr = RESTART_REGISTER_SUBCTRL1_BASE;
|
|
break;
|
|
}
|
|
case 4:
|
|
case 5:
|
|
{
|
|
i8ApcId = 2;
|
|
u64SubctrlAddr = RESTART_REGISTER_SUBCTRL2_BASE;
|
|
break;
|
|
}
|
|
case 6:
|
|
case 7:
|
|
{
|
|
i8ApcId = 3;
|
|
u64SubctrlAddr = RESTART_REGISTER_SUBCTRL3_BASE;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
i8ApcId = -1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (-1 == i8ApcId)
|
|
{
|
|
UCP_PRINT_ERROR("OspRestartRegister: coreid(%d) error.\r\n", u8CoreId);
|
|
return OSP_ERROR;
|
|
}
|
|
UCP_PRINT_DEBUG("OspRestartRegister: Start to restart register(coreid = %d).\r\n", u8CoreId);
|
|
|
|
iOspRestartFd = open("/dev/mem", O_RDWR|O_SYNC);
|
|
if (0 > iOspRestartFd)
|
|
{
|
|
UCP_PRINT_ERROR("OspRestartRegister: open /dev/mem error.\r\n");
|
|
return OSP_ERROR;
|
|
}
|
|
UCP_PRINT_DEBUG("OspRestartRegister: start mmap(subctrl).\r\n");
|
|
|
|
gu8VirSubctrlAddr = (uint8_t*)mmap(NULL, RESTART_REGISTER_LEN, PROT_READ|PROT_WRITE, MAP_SHARED, iOspRestartFd, u64SubctrlAddr);
|
|
if ((uint8_t*)(-1) == gu8VirSubctrlAddr)
|
|
{
|
|
UCP_PRINT_ERROR("OspRestartRegister: mmap error.\r\n");
|
|
return OSP_ERROR;
|
|
}
|
|
UCP_PRINT_DEBUG("OspRestartRegister: start mmap(rst_cfg).\r\n");
|
|
|
|
gu8VirRstCfgAddr = (uint8_t*)mmap(NULL, RESTART_REGISTER_LEN, PROT_READ|PROT_WRITE, MAP_SHARED, iOspRestartFd, RESTART_REGISTER_RST_CFG_BASE);
|
|
if ((uint8_t*)(-1) == gu8VirRstCfgAddr)
|
|
{
|
|
UCP_PRINT_ERROR("OspRestartRegister: mmap error.\r\n");
|
|
return OSP_ERROR;
|
|
}
|
|
UCP_PRINT_DEBUG("OspRestartRegister: Set register for restart.\r\n");
|
|
|
|
/* 根据coreid设置对应寄存器 */
|
|
|
|
|
|
*((volatile uint32_t*)(gu8VirSubctrlAddr)) |= 0xC; //enable ISO, set bit2,3 to 1
|
|
*((volatile uint32_t*)(gu8VirSubctrlAddr)) &= 0xFFFFFFFD; //apc_arstn is valid, reset bus of apc0
|
|
*((volatile uint32_t*)(gu8VirRstCfgAddr+0x274+i8ApcId*4)) = (0xFFFFFF & (*((volatile uint32_t*)(gu8VirRstCfgAddr+i8ApcId*4)))) | (4 << 24); //reset apc0 core, set bit24 to 0
|
|
osp_delay(1000);
|
|
*((volatile uint32_t*)(gu8VirSubctrlAddr)) |= 0x2; //apc_arstn is invalid, dereset bus of apc0
|
|
*((volatile uint32_t*)(gu8VirRstCfgAddr+0x274+i8ApcId*4)) = (0xFFFFFF & (*((volatile uint32_t*)(gu8VirRstCfgAddr+i8ApcId*4)))) | (5 << 24); //dereset apc0 core, set bit24 to 1
|
|
*((volatile uint32_t*)(gu8VirSubctrlAddr)) &= 0xFFFFFFF3; //disable ISO, set bit2,3 to 0
|
|
|
|
return OSP_OK;
|
|
}
|
|
|
|
/* DUMP DM内存 */
|
|
int8_t OspDumpDm2Ddr(uint8_t u8CoreId)
|
|
{
|
|
#ifdef HEARTBEAT_ENABLE
|
|
return osp_dump_dm_by_coreid(u8CoreId);
|
|
#else
|
|
return OSP_OK;
|
|
#endif
|
|
}
|
|
|
|
#define OSP_LOAD_APE0_OUT "./loadelf_8g -ape dump_im.ape0.out %d 1"
|
|
#define OSP_LOAD_APE1_OUT "./loadelf_8g -ape dump_im.ape1.out %d 1"
|
|
|
|
/* 二次加载 */
|
|
int8_t Osp2Loader(uint8_t u8CoreId)
|
|
{
|
|
char cmd[128] = {0};
|
|
if (u8CoreId <= 7)
|
|
{
|
|
if (0 == u8CoreId%2)
|
|
{
|
|
sprintf(cmd, OSP_LOAD_APE0_OUT, u8CoreId);
|
|
}
|
|
else
|
|
{
|
|
sprintf(cmd, OSP_LOAD_APE1_OUT, u8CoreId);
|
|
}
|
|
UCP_PRINT_DEBUG("Osp2Loader: cmd = %s \r\n", cmd);
|
|
system(cmd);
|
|
return OSP_OK;
|
|
}
|
|
return OSP_ERROR;
|
|
}
|
|
|
|
/* DUMP IM内存 */
|
|
int8_t OspDumpIm2Ddr(uint8_t u8CoreId)
|
|
{
|
|
#ifdef HEARTBEAT_ENABLE
|
|
return osp_get_im2ddr_to_file(u8CoreId);
|
|
#else
|
|
return OSP_OK;
|
|
#endif
|
|
}
|
|
|
|
#define OSP_GET_DUMP_DM2TMP "./exp_file dump_dm_core* /tmp/dumpfile"
|
|
#define OSP_GET_DMMP_IM2TMP "./exp_file dump_im_core* /tmp/dumpfile"
|
|
|
|
void OspGetFileOut(uint8_t u8CoreId)
|
|
{
|
|
//UCP_PRINT_DEBUG("OspGetFileOut: cmd = %s \r\n", OSP_GET_DUMP_DM2TMP);
|
|
system(OSP_GET_DUMP_DM2TMP);
|
|
|
|
//UCP_PRINT_DEBUG("OspGetFileOut: cmd = %s \r\n", OSP_GET_DMMP_IM2TMP);
|
|
system(OSP_GET_DMMP_IM2TMP);
|
|
|
|
//UCP_PRINT_DEBUG("OspGetFileOut: OK \r\n");
|
|
return ;
|
|
}
|
|
|
|
/* 重启 */
|
|
void OspRestartPro(uint8_t u8CoreId)
|
|
{
|
|
int8_t ret = 0;
|
|
|
|
UCP_PRINT_DEBUG("OspRestartPro : u8CoreId = %d \r\n", u8CoreId);
|
|
|
|
if (7 < u8CoreId)
|
|
{
|
|
UCP_PRINT_ERROR("OspRestartPro: core_id = %d(big).\r\n", u8CoreId);
|
|
return ;
|
|
}
|
|
|
|
ret = OspRestartRegister(u8CoreId);
|
|
if (OSP_ERROR == ret)
|
|
{
|
|
UCP_PRINT_ERROR("OspRestartPro: Call OspRestartRegister return error.\r\n");
|
|
return ;
|
|
}
|
|
|
|
//UCP_PRINT_DEBUG("OspRestartPro : OspRestartRegister return ok \r\n");
|
|
|
|
ret = OspDumpDm2Ddr(u8CoreId);
|
|
if (OSP_ERROR == ret)
|
|
{
|
|
UCP_PRINT_ERROR("OspRestartPro: Call OspDumpDm2Ddr return error.\r\n");
|
|
return ;
|
|
}
|
|
//UCP_PRINT_DEBUG("OspRestartPro : OspDumpDm2Ddr return ok \r\n");
|
|
|
|
ret = Osp2Loader(u8CoreId);
|
|
if (OSP_ERROR == ret)
|
|
{
|
|
UCP_PRINT_ERROR("OspRestartPro: Call Osp2Loader return error.\r\n");
|
|
return ;
|
|
}
|
|
//UCP_PRINT_DEBUG("OspRestartPro : Osp2Loader return ok \r\n");
|
|
|
|
ret = OspDumpIm2Ddr(u8CoreId);
|
|
if (OSP_ERROR == ret)
|
|
{
|
|
UCP_PRINT_ERROR("OspRestartPro: Call OspDumpIm2Ddr return error.\r\n");
|
|
return ;
|
|
}
|
|
//UCP_PRINT_DEBUG("OspRestartPro : OspDumpIm2Ddr return ok \r\n");
|
|
|
|
OspGetFileOut(u8CoreId);
|
|
|
|
UCP_PRINT_DEBUG("****************************************************** \r\n");
|
|
return ;
|
|
}
|
|
|
|
|
|
/* 心跳定时器超时处理函数
|
|
1. 若不需要监测直接返回
|
|
2. 监测每个核的心跳计数
|
|
2.1 与上次的对比,一致则看是否达到最大失信计数--重启
|
|
2.2 不一致,更新上次计数
|
|
*/
|
|
void OspHeartbeatTimeoutPro(void)
|
|
{
|
|
static uint32_t su32Cnt = 0;
|
|
uint8_t u8CoreId = 0;
|
|
uint32_t u32HeartbeatCunt = 0;
|
|
su32Cnt++;
|
|
//UCP_PRINT_DEBUG("OspHeartbeatTimeoutPro: Enter >>> (%d)", su32Cnt);
|
|
|
|
/* 若心跳监测关闭,则不监测各核心跳 */
|
|
if (OSP_HEARTBEAT_OFF == gsu8OspHeartbeatSwitch)
|
|
{
|
|
UCP_PRINT_ERROR("OspHeartbeatTimeoutPro: .gsu8OspHeartbeatSwitch is OSP_HEARTBEAT_OFF.\r\n");
|
|
return ;
|
|
}
|
|
|
|
/* 监测各核心跳 */
|
|
for( u8CoreId = 0; u8CoreId < OSP_HB_MAX_CORE_NUM; u8CoreId++)
|
|
{
|
|
if (HB_NO_CHECK == gsstOspHeartbeatCounter[u8CoreId].u32CheckFlag)
|
|
{
|
|
continue;
|
|
}
|
|
u32HeartbeatCunt = OspGetHeartbeat(u8CoreId);
|
|
UCP_PRINT_DEBUG("OspHeartbeatTimeoutPro: coreId(%d) LastBeat(%d) NowBeat(%d)\r\n", u8CoreId, gsstOspHeartbeatCounter[u8CoreId].u32LastCounter, u32HeartbeatCunt);
|
|
if (gsstOspHeartbeatCounter[u8CoreId].u32LastCounter == u32HeartbeatCunt)
|
|
{
|
|
gsstOspHeartbeatCounter[u8CoreId].u32LossCounter++;
|
|
|
|
if (gsstOspHeartbeatCounter[u8CoreId].u32LossCounter > OSP_HB_MAX_COUNTER)
|
|
{
|
|
UCP_PRINT_ERROR("OspHeartbeatTimeoutPro: CoreID(%d) should be restart...\r\n", u8CoreId);
|
|
OspRestartPro(u8CoreId);
|
|
if (0 == u8CoreId%2)
|
|
{
|
|
gsstOspHeartbeatCounter[u8CoreId].u32CheckFlag = HB_NO_CHECK;
|
|
gsstOspHeartbeatCounter[u8CoreId+1].u32CheckFlag = HB_NO_CHECK;
|
|
}
|
|
else
|
|
{
|
|
gsstOspHeartbeatCounter[u8CoreId].u32CheckFlag = HB_NO_CHECK;
|
|
gsstOspHeartbeatCounter[u8CoreId-1].u32CheckFlag = HB_NO_CHECK;
|
|
}
|
|
return ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gsstOspHeartbeatCounter[u8CoreId].u32LastCounter = u32HeartbeatCunt;
|
|
gsstOspHeartbeatCounter[u8CoreId].u32LossCounter = 0;
|
|
}
|
|
}
|
|
return ;
|
|
}
|
|
|
|
/* 心跳处理函数:
|
|
1. 创建定时器
|
|
2. 启动定时器
|
|
*/
|
|
int8_t OspHeartbeatPro(void)
|
|
{
|
|
int8_t ret = 0;
|
|
uint8_t u8TimerIndex = 0;
|
|
|
|
memset(gsstOspHeartbeatCounter, 0, sizeof(gsstOspHeartbeatCounter));
|
|
gsu8OspHeartbeatSwitch = OSP_HEARTBEAT_ON;
|
|
//return OSP_OK;
|
|
|
|
/* 创建定时器 */
|
|
ret = OspTmrCreate((const char*)OSP_HEARTBEAT_NAME, OSP_HEARTBEAT_TMR_OUT, OSP_TMR_PERIODIC, (OSP_CALLBACK)OspHeartbeatTimeoutPro, NULL);
|
|
if (OSP_ERROR == ret)
|
|
{
|
|
UCP_PRINT_ERROR("OspHeartbeatPro: OspTmrCreate return error.\r\n");
|
|
return OSP_ERROR;
|
|
}
|
|
u8TimerIndex = ret;
|
|
|
|
/* 启动定时器 */
|
|
ret = OspTmrStart(u8TimerIndex);
|
|
if (OSP_ERROR == ret)
|
|
{
|
|
UCP_PRINT_ERROR("OspHeartbeatPro: OspTmrStart return error.\r\n");
|
|
return OSP_ERROR;
|
|
}
|
|
return OSP_OK;
|
|
}
|
|
|
|
|