yb_arm/osp/src/ospHeartbeat.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;
}