文档首页/ LiteOS/ 维测指南/ 临终遗言使用方法
更新时间:2021-07-08 GMT+08:00
分享

临终遗言使用方法

功能说明

临终遗言日志存储钩子函数,实现日志存储的读写函数的注册,接口详细信息可以查看API参考。

接口名

描述

LOS_ExcInfoRegHook

注册读写临终遗言日志的钩子函数,并设置记录临终遗言日志的起始地址、大小和缓冲区。

LOS_ExcInfoRegHook有4个参数:

  • startAddr:临终遗言日志的存储起始地址。
  • space:临终遗言日志的存储空间大小。
  • buf:临终遗言日志在内存中的buffer地址,大小space。
  • LogReadWriteFunc:读写异常信息的钩子函数。该函数的入参包括startAddr、space、rwFlag和buf。rwFlag是读写标记,0为写,1为读。其余3个入参同LOS_ExcInfoRegHook。

使用方法

  1. 通过make menuconfig开启临终遗言记录功能,即配置LOSCFG_SHELL_EXCINFO_DUMP=y,该功能默认关闭,菜单路径为:Debug ---> Enable a Debug Version ---> Enable Shell ---> Enable Shell excInfo。
  2. 注册读写钩子函数。

    1. 编写读写临终遗言日志的钩子函数,示例代码如下。
      #include "los_base.h"
      #if defined(LOSCFG_SHELL_EXCINFO) && defined(LOSCFG_DRIVERS_MTD_SPI_NOR)
      #include "linux/mtd/mtd.h"
      #include "linux/module.h"
      #include "linux/mtd/mtd_list.h"
      #include "spinor.h"
      #endif
      #include "los_hwi.h"
      #ifdef LOSCFG_FS_VFS
      #include "fs/fs.h"
      #endif
      
      #ifdef LOSCFG_SHELL_EXCINFO_DUMP
      STATIC struct mtd_info *g_mtdSpinor = NULL;
      STATIC VOID OsSpiflashErase(UINT32 start, size_t size)
      {
          struct erase_info eraseInfo;
          (VOID)memset_s(&eraseInfo, sizeof(struct erase_info), 0, sizeof(struct erase_info));
          eraseInfo.mtd = g_mtdSpinor;
          eraseInfo.callback = NULL;
          eraseInfo.fail_addr = (UINT64)MTD_FAIL_ADDR_UNKNOWN;
          eraseInfo.addr = start;
          eraseInfo.len = size;
          eraseInfo.time = 1;
          eraseInfo.retries = 1;
          eraseInfo.dev = 0;
          eraseInfo.cell = 0;
          eraseInfo.priv = 0;
          eraseInfo.state = 0;
          eraseInfo.next = NULL;
          eraseInfo.scrub = 0;
          (VOID)g_mtdSpinor->erase(g_mtdSpinor, &eraseInfo);
      }
      STATIC INT32 OsWriteExcInfoToSpiFlash(UINT32 startAddr, UINT32 space, const CHAR *buf)
      {
          UINT32 outLen;
          OsSpiflashErase(startAddr, LOS_Align(space, g_mtdSpinor->erasesize));
          return g_mtdSpinor->write(g_mtdSpinor, (loff_t)startAddr, space, &outLen, buf);
      }
      STATIC INT32 OsReadExcInfoForSpiFlash(UINT32 startAddr, UINT32 space, CHAR *buf)
      {
          UINT32 outLen;
          return g_mtdSpinor->read(g_mtdSpinor, (loff_t)startAddr, space, &outLen, buf);
      }
      
      /* Be called in the exception. */
      VOID OsReadWriteExceptionInfo(UINT32 startAddr, UINT32 space, UINT32 flag, CHAR *buf)
      {
          if ((buf == NULL) || (space == 0)) {
              PRINT_ERR("buffer is null or space is zero\n");
              return;
          }
      
          g_mtdSpinor = get_mtd("spinor");
          if (g_mtdSpinor == NULL) {
              (VOID)spinor_init();
              g_mtdSpinor = get_mtd("spinor");
              if (g_mtdSpinor == NULL) {
                  PRINT_ERR("Init spinor is failed\n");
                  return;
              }
          }
      
          if (flag == 0) {
              if (OsWriteExcInfoToSpiFlash(startAddr, space, buf) != LOS_OK) {
                  PRINT_ERR("Exception information written to 0x%x flash failed\n", startAddr);
              }
      #ifndef LOSCFG_EXC_INTERACTION
              /*
               * When system is in the exception interaction, this buf was free,
               * but this feature is still running. This buffer may be used again
               * without malloc.
               * So, consider whether or not the "buf" is released according to actual use.
               */
              free(buf);
      #endif
          } elseif (flag == 1) {
              if (OsReadExcInfoForSpiFlash(startAddr, space, buf) != LOS_OK) {
                  PRINT_ERR("Exception information read from 0x%x flash failed\n", startAddr);
              }
          } else {
              PRINT_ERR("flag is error\n");
          }
      }
      #endif
      #endif
    2. 在初始化函数如app_init中注册钩子函数,示例代码如下。
      #ifdef LOSCFG_SHELL_EXCINFO_DUMP
      #define EXCINFO_RECORD_BUF_SIZE     (16 * 1024)   /* 用户自己定义 */
      #define EXCINFO_RECORD_ADDR         (0xffffffff)  /* 此处是非法值,需要用户自己定义 */
          CHAR *buf = (CHAR *)malloc(EXCINFO_RECORD_BUF_SIZE);
          if (buf != NULL) {
              (VOID)memset_s(buf, EXCINFO_RECORD_BUF_SIZE, 0, EXCINFO_RECORD_BUF_SIZE);
              LOS_ExcInfoRegHook(EXCINFO_RECORD_ADDR, EXCINFO_RECORD_BUF_SIZE, buf, OsReadWriteExceptionInfo);
          } else {
              PRINTK("shell excinfo malloc failed!\n");
          }
      #ifdef LOSCFG_FS_VFS
          los_vfs_init();
      #endif
      #endif
      • OsReadWriteExceptionInfo函数是对Nor Flash进行读写的功能函数,宏EXCINFO_RECORD_BUF_SIZE,EXCINFO_RECORD_ADDR需要用户根据实际情况进行配置,建议该段代码放在用户业务代码前。
      • Nor Flash写数据之前要进行块擦除,块大小为64k,因此设置的临终遗言存储起始地址之后的64k区域,在写临终遗言信息时会被擦除,建议此区域不保存数据。

  3. 查看异常信息。

    系统复位重启后,Shell窗口中执行excInfo命令,会打印出已记录的临终遗言日志。

注意事项

保存临终遗言信息的buffer需要用户进行维护,重复调用注册函数时,需要用户自行释放前一次注册时传入的buffer。

相关文档