1-Linux 保存kernel panic信息到flash

ramoops&pstore简要说明 1. pstore pstore是persistent storage的缩写。内核发生异常时如果能将日志等信息保存下来不丢失,那么就可以通过这些信息来定位问题。不同的平台可以提供的存储位置不同,例如有些平台支持硬盘,有些不支持。除了平台差异,异常类型也决定了在发生异常时该存储位置是否还可用。 pstore的目标是提供一套通用的接口用来存储异常信息。pstore以文件系统的形式提供用户空间接口, 阅读详情
AI摘要

文章详细介绍了在嵌入式Linux系统中,如何在内核发生panic时捕获并保存崩溃日志。主要讨论了mtdoops和pstore两种方法,包括它们的工作原理、配置步骤以及实际操作中的问题和解决方案。mtdoops通过将日志保存到非易失性存储,如MTD分区,而pstore则利用内存缓冲区并在重启后写入到指定位置。文章还提到了在某些情况下,如emmc驱动未支持panic_write时的处理方式,以及如何通过修改内核看门狗行为确保系统在panic后能自动重启。

在系统运行过程中,如果内核发生了panic,那么开发人员需要通过内核报错日志来进行定位问题。但是很多时候出现问题的时候没有接调试串口,而报错日志是在内存里面的,重启后就丢失了。所以需要一种方法,可以在系统发生crash时,将crash info保存于非易失存储器中。

1、捕获panic原理

内核使用kmsg_dump_register()函数来注册捕获panic或者oops,如今内核已经有多种捕获panic的方式,最新的是pstore方式。

根据网上搜寻的资料,在pstore文件系统之前其实有不少类似的实现。

  • apanic

Android最早的panic信息记录的方案。在linux 2.6的安卓的内核中找到,却没有提交到社区,后来被放弃维护了。网上找不到放弃的原因,我自己猜测是因为其只适用于mtd nand,然而现在的Android基本用的都是emmc。apanic应该是Android Panic的缩写吧,可以实现在内核崩溃时,把日志转存到mtd nand。

  • ramoops

这里指的是最早的ramoops实现,在最新代码已经整合入pstore中,以pstore/ram的后端形式存在。ramoops可以把日志转存到重启不掉电的ram中。这里对ram有一点要求,即使重启ram的数据也不能丢失。

  • crashlog

这是openwrt提供的内核patch,并没有提交到内核社区。它也是基于ram,只能转存Panic/Oops的日志。

  • mtdoops

MTD子系统支持的功能,与pstore非常相似,只支持转存Panic/Oops日志,不能以文件呈现,需要用户自行解析整个MTD分区。(因为功能的相似,我实现了mtdpstore用于替代mtdoops)

  • kdump

如果说pstore是个轻量级的内核崩溃日志转存的方案,kdump则是一个重量级的问题分析工具。在崩溃时,由kdump产生一个用于捕抓当前信息的内核,该内核会收集内存所有信息到dump core文件中。在重启后,捕抓到的信息保存在特定的文件中。类似的还有netdump和diskdump。kdump的方案适用于服务器这种有大量资源的设备,功能也非常强大,但对嵌入式设备非常不友好。

Linux pstore 实现自动“抓捕”内核崩溃日志:
:https://cloud.tencent.com/developer/article/1646413?from=15425&areaSource=102001.1&traceId=OMnQ0q6ZZQELlvCmhM3dr

2、mtdoops方式实现
2.1 mtdoops配置打开

menuconfig,mtd_oops勾选上

Device Drivers  --->
    Memory Technology Device (MTD) support  ---> 
        Log panic/oops to an MTD buffer 

代码./drivers/mtd/mtdoops.c

mtd添加kpanic分区用来日志保存

partition@a0000 {
	label = "kpanic";
	reg = <0xa0000 0x60000>;
};

在./drivers/mtd/mtdoops.c添加对应的分区名字

static char mtddev[80] = "kpanic";
2.2 内核写入mtd流程说明

mtd初始化成功后,会进入mtdoops_notify_add()函数。

该函数会做如下几件事

  • 判断保存panic的分区是哪个,并且判断分区大小之类的边界值
  • 注册panic回调函数,这样当内核出现panic时就会执行回调函数
  • 读取分区头部信息,确认分区存储情况,下一次保存panic的地址
static void mtdoops_notify_add(struct mtd_info *mtd)
{
	struct mtdoops_context *cxt = &oops_cxt;
	u64 mtdoops_pages = div_u64(mtd->size, record_size);
	int err;

    /*判断是否为保存panic的分区名称
    开头可以定义分区名称如下:static char mtddev[80] = "kpanic";
    */
	if (!strcmp(mtd->name, mtddev))
		cxt->mtd_index = mtd->index;

	if (mtd->index != cxt->mtd_index || cxt->mtd_index < 0)
		return;

	if (mtd->size < mtd->erasesize * 2) {
		printk(KERN_ERR "mtdoops: MTD partition %d not big enough for mtdoops\n",
		       mtd->index);
		return;
	}
	if (mtd->erasesize < record_size) {
		printk(KERN_ERR "mtdoops: eraseblock size of MTD partition %d too small\n",
		       mtd->index);
		return;
	}
	if (mtd->size > MTDOOPS_MAX_MTD_SIZE) {
		printk(KERN_ERR "mtdoops: mtd%d is too large (limit is %d MiB)\n",
		       mtd->index, MTDOOPS_MAX_MTD_SIZE / 1024 / 1024);
		return;
	}

	/* oops_page_used is a bit field */
	cxt->oops_page_used = vmalloc(DIV_ROUND_UP(mtdoops_pages,
			BITS_PER_LONG) * sizeof(unsigned long));
	if (!cxt->oops_page_used) {
		printk(KERN_ERR "mtdoops: could not allocate page array\n");
		return;
	}

    /*注册panic回调函数*/
	cxt->dump.max_reason = KMSG_DUMP_OOPS;
	cxt->dump.dump = mtdoops_do_dump;
	err = kmsg_dump_register(&cxt->dump);
	if (err) {
		printk(KERN_ERR "mtdoops: registering kmsg dumper failed, error %d\n", err);
		vfree(cxt->oops_page_used);
		cxt->oops_page_used = NULL;
		return;
	}

    /*检测分区存储情况*/
	cxt->mtd = mtd;
	cxt->oops_pages = (int)mtd->size / record_size;
	find_next_position(cxt);
	printk(KERN_INFO "record_size:%d,max_count:%d,next_count:%d\n", record_size, cxt->oops_pages, cxt->nextcount);
	printk(KERN_INFO "mtdoops: Attached to MTD device %d\n", mtd->index);
}

捕获到panic后执行如下回调函数

static void mtdoops_do_dump(struct kmsg_dumper *dumper,
			    enum kmsg_dump_reason reason)
{
	struct timeval tv;
	struct rtc_time tm;
	int skip = MTDOOPS_HEADER_SIZE;
	int len;
	struct mtdoops_context *cxt = container_of(dumper,
			struct mtdoops_context, dump);

	/* Only dump oopses if dump_oops is set */
	if (reason == KMSG_DUMP_OOPS && !dump_oops)
		return;

    /*添加一些自定义信息,比如panic时间,固件版本等信息*/
	do_gettimeofday(&tv);
	rtc_time_to_tm(tv.tv_sec + KPANIC_CST_OFFSET_S, &tm);
	len = sprintf(cxt->oops_buf + skip, "PANIC time:(%d-%02d-%02d %02d:%02d:%02d)\n", 
							tm.tm_year+1900, tm.tm_mon + 1, tm.tm_mday,
							tm.tm_hour, tm.tm_min, tm.tm_sec);
	skip += len;
	len = sprintf(cxt->oops_buf + skip, "PANIC version: %s\n", zr_firmware_ver);
	skip += len;

	kmsg_dump_get_buffer(dumper, true, cxt->oops_buf + skip,
			     record_size - skip, NULL);

	/* Panics must be written immediately */
	if (reason != KMSG_DUMP_OOPS)
		mtdoops_write(cxt, 1);

	/* For other cases, schedule work to write it "nicely" */
	schedule_work(&cxt->work_write);
}

调用mtdoops_write()函数将kmsg_dump_get_buffer的信息下入mtd分区。

static void mtdoops_write(struct mtdoops_context *cxt, int panic)
{
	struct mtd_info *mtd = cxt->mtd;
	size_t retlen;
	u32 *hdr;
	int ret;

	/* Add mtdoops header to the buffer */
	hdr = cxt->oops_buf;
	hdr[0] = cxt->nextcount;
	hdr[1] = MTDOOPS_KERNMSG_MAGIC;

	if (panic) {
		ret = mtd_panic_write(mtd, cxt->nextpage * record_size,
				      record_size, &retlen, cxt->oops_buf);
		if (ret == -EOPNOTSUPP) {
			printk(KERN_ERR "mtdoops: Cannot write from panic without panic_write\n");
			return;
		}
	} else
		ret = mtd_write(mtd, cxt->nextpage * record_size,
				record_size, &retlen, cxt->oops_buf);

	if (retlen != record_size || ret < 0)
		printk(KERN_ERR "mtdoops: write failure at %ld (%td of %ld written), error %d\n",
		       cxt->nextpage * record_size, retlen, record_size, ret);
	mark_page_used(cxt, cxt->nextpage);
	memset(cxt->oops_buf, 0xff, record_size);

	mtdoops_inc_counter(cxt);
}

这边的区别在于,为啥要使用mtd_panic_write写入,而不用普通mtd_write函数。

因为内核要挂死的时候,如果还是按原本的设备驱动流程去写flash,会出现写不成功的情况,所以不同的存储驱动一般都适配了对应的panic_nand_write函数。

如果是nand flash,mtd_panic_write最终会调用到./drivers/mtd/nand/raw/nand_base.c下面的panic_nand_write函数

static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
			    size_t *retlen, const uint8_t *buf)
{
	struct nand_chip *chip = mtd_to_nand(mtd);
	int chipnr = (int)(to >> chip->chip_shift);
	struct mtd_oob_ops ops;
	int ret;

	/* Grab the device */
	panic_nand_get_device(chip, mtd, FL_WRITING);

	chip->select_chip(mtd, chipnr);

	/* Wait for the device to get ready */
	panic_nand_wait(mtd, chip, 400);

	memset(&ops, 0, sizeof(ops));
	ops.len = len;
	ops.datbuf = (uint8_t *)buf;
	ops.mode = MTD_OPS_PLACE_OOB;

	ret = nand_do_write_ops(mtd, to, &ops);

	*retlen = ops.retlen;
	return ret;
}
2.3 mtdoops写入测试

这个命令可以让kernel crash

 echo c > /proc/sysrq-trigger

报错日志如下:

root@zihome:/# echo c > /proc/sysrq-trigger
[  915.096147] sysrq: SysRq : Trigger a crash
[  915.101081] CPU 1 Unable to handle kernel paging request at virtual address 00000000, epc == 8124ac98, ra == 8124b0c4
[  915.111744] Oops[#1]:
[  915.114033] CPU: 1 PID: 671 Comm: ash Not tainted 4.4.198 #0
[  915.119694] task: 87da85e0 task.stack: 86362000
[  915.124219] $ 0   : 00000000 00000001 00000001 81910000
[  915.129462] $ 4   : 00000063 00000001 000002ad 00157000
[  915.134703] $ 8   : 00000000 00005e30 00000000 00000134
[  915.139941] $12   : 00000000 00000000 00000134 00000000
[  915.145181] $16   : 81913ae0 81910000 00000063 00000000
[  915.150419] $20   : 00000007 81913c60 77ddf518 77de0d8c
[  915.155662] $24   : 00000018 81250e74                  
[  915.160900] $28   : 86362000 86363df8 00000000 8124b0c4
[  915.166143] Hi    : 00000000
[  915.169019] Lo    : 122f2000
[  915.171907] epc   : 8124ac98 sysrq_handle_crash+0x10/0x18
[  915.177309] ra    : 8124b0c4 __handle_sysrq+0xcc/0x1b8
[  915.182443] Status: 11007c03 KERNEL EXL IE 
[  915.186639] Cause : c080000c (ExcCode 03)
[  915.190642] BadVA : 00000000
[  915.193521] PrId  : 0001992f (MIPS 1004Kc)
[  915.197612] Modules linked in: mt753x iptable_nat nf_nat_ipv4 nf_conntrack_ipv6 nf_conntrack_ipv4 ipt_REJECT ipt_MASQUERADE xt_time xt_tcpudp xt_tcpmss xt_string xt_statistic xt_state xt_recent xt_nat xt_multiport xt_mark xt_mac xt_limit xt_length xt_iprange xt_hl xt_helper xt_ecn xt_dscp xt_conntrack xt_connmark xt_connlimit xt_connbytes xt_comment xt_TCPMSS xt_REDIRECT xt_LOG xt_HL xt_DSCP xt_CLASSIFY ts_kmp ts_fsm ts_bm nf_reject_ipv4 nf_nat_redirect nf_nat_masquerade_ipv4 nf_nat nf_log_ipv4 nf_defrag_ipv6 nf_defrag_ipv4 mtfwd mapfilter iptable_mangle iptable_filter ipt_ECN ip_tables crypto_hw_eip93 crc_ccitt fuse act_ipt em_nbyte em_meta em_text sch_codel em_cmp act_connmark nf_conntrack em_u32 sch_ingress sg ip6t_REJECT nf_reject_ipv6 nf_log_ipv6 nf_log_common ip6table_mangle ip6table_filter ip6_tables x_tables msdos ip_gre gre ifb l2tp_netlink l2tp_core udp_tunnel ip6_udp_tunnel ip_tunnel vfat fat nls_utf8 nls_iso8859_1 nls_cp437 nls_base sha1_generic ecb des_generic authenc leds_gpio sd_mod scsi_mod gpio_button_hotplug ext4 jbd2 mbcache mbcache2 crc32c_generic [last unloaded: mt753x]
[  915.294698] Process ash (pid: 671, threadinfo=86362000, task=87da85e0, tls=77de7d48)
[  915.302438] Stack : 87c29c50 8180b5f8 81e62d9c 00157000 00000002 00000002 77ddd340 86363f08
          77ddc000 77ddc000 77ddf518 8124b21c 00000000 8123eb14 00000000 86107640
          80c5f700 8113f30c 80df4018 0000000d 87d63016 00000000 00000000 854be5a0
          00000002 810ecd58 00000000 00000924 00000000 0000000b 865f8d20 00000020
          865f8d38 0000000a 00000000 87da85d8 fffffff6 81035494 865f8d38 00000000
          ...
[  915.338093] Call Trace:
[  915.340541] [<8124ac98>] sysrq_handle_crash+0x10/0x18
[  915.345601] [<8124b0c4>] __handle_sysrq+0xcc/0x1b8
[  915.350393] [<8124b21c>] write_sysrq_trigger+0x40/0x5c
[  915.355552] [<8113f30c>] proc_reg_write+0x68/0xac
[  915.360259] [<810ecd58>] __vfs_write+0x28/0x110
[  915.364795] [<810ed764>] vfs_write+0xb0/0x194
[  915.369154] [<810ee13c>] SyS_write+0x74/0xf0
[  915.373439] [<810078d8>] syscall_common+0x30/0x54
[  915.378141] 
[  915.379627] 
Code: 3c038191  ac62c6e4  0000000f <03e00008> a0020000  27bdffe0  24020007  afb10018  2491ffd0 
[  915.389901] ---[ end trace 2a7448a53c8e5e61 ]---
[  915.396246] Fatal exception: panic in 5 seconds
[  915.415478] mtdoops: ready 15, 16 (no erase)

重启后查看mtd日志

如果我们定义的kpanic分区位于mtd1,则如下查看

root@openwrt:/tmp# cat /dev/mtdblock1 > 1.txt
root@openwrt:/tmp# cat 1.txt
3、pstore方式实现

在测试emmc的硬件板子,会出现mtdoops: Cannot write from panic without panic_write,因为emmc的驱动里面没有panic_write函数。

root@openwrt:/lib/modules/4.19.81# echo c > /proc/sysrq-trigger 
[ 1496.199280] sysrq: SysRq : Trigger a crash
[ 1496.203539] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
...
[ 1496.596036] Call trace:
[ 1496.598553]  sysrq_handle_crash+0x14/0x20
[ 1496.602681]  write_sysrq_trigger+0x6c/0x80
[ 1496.606903]  proc_reg_write+0x5c/0x98
[ 1496.610675]  __vfs_write+0x18/0x130
[ 1496.614266]  vfs_write+0xb4/0x178
[ 1496.617678]  ksys_write+0x50/0xa0
[ 1496.621089]  __arm64_sys_write+0x18/0x20
[ 1496.625130]  el0_svc_common+0x8c/0xf0
[ 1496.628901]  el0_svc_handler+0x68/0x70
[ 1496.632762]  el0_svc+0x8/0xc
[ 1496.635727] Code: 52800020 b908d020 d5033e9f d2800001 (39000020) 
[ 1496.642007] ---[ end trace d88c536421afe116 ]---
[ 1496.647533] Kernel panic - not syncing: Fatal exception
[ 1496.652921] SMP: stopping secondary CPUs
[ 1496.656960] Kernel Offset: disabled
[ 1496.660551] CPU features: 0x0,20002000
[ 1496.664410] Memory Limit: none
[ 1496.668301] mtdoops: Cannot write from panic without panic_write
[ 1496.674491] Rebooting in 3 seconds..

如果修改mtdoops的panic_write改成直接mtd_write的话,会出现如下错误,没有写入成功,类似上面说的系统已经出问题了,不能按正常设备驱动写入。

[   58.047260] Call trace:
[   58.049780]  sysrq_handle_crash+0x14/0x20
[   58.053912]  write_sysrq_trigger+0x6c/0x80
[   58.058137]  proc_reg_write+0x5c/0x98
[   58.061913]  __vfs_write+0x18/0x130
[   58.065508]  vfs_write+0xb4/0x178
[   58.068922]  ksys_write+0x50/0xa0
[   58.072336]  __arm64_sys_write+0x18/0x20
[   58.076381]  el0_svc_common+0x8c/0xf0
[   58.080155]  el0_svc_handler+0x68/0x70
[   58.084018]  el0_svc+0x8/0xc
[   58.086987] Code: 52800020 b908d020 d5033e9f d2800001 (39000020) 
[   58.093271] ---[ end trace 487bc19a9b8382f3 ]---
[   58.105794] Kernel panic - not syncing: Fatal exception
[   58.111188] SMP: stopping secondary CPUs
[   58.115232] Kernel Offset: disabled
[   58.118827] CPU features: 0x0,20002000
[   58.122686] Memory Limit: none
[   63.225303] mtk-msdc 11230000.mmc: msdc_request_timeout: aborting cmd/data/mrq
[   63.232774] mtk-msdc 11230000.mmc: msdc_request_timeout: aborting mrq=00000000045fc364 cmd=18
[   63.241587] mtk-msdc 11230000.mmc: msdc_request_timeout: aborting cmd=18
[   88.164968] WARNING: CPU: 1 PID: 10 at irq_work_queue_on+0x30/0x108

研究mtd调用emmc写入没研究成功,所以接着研究通过pstore的方式进行写入。

3.1 pstore配置打开
|-> File systems
    |-> Miscellaneous filesystems
      |-> Persistent store support
        |-> Log kernel console messages    # console 前端
        |-> Log user space messages      # pmsg 前端
        |-> Persistent function tracer      # ftrace 前端
        |-> Log panic/oops to a RAM buffer     # pstore/ram 后端
        |-> Log panic/oops to a block device   # pstore/blk 后端

当panic出现后,pstore会将dmesg的信息保存到内存,重启后,再从内存中读出来。

由于要存在内存下,所以我们就需要分配一段固定的内存给oops保存。

首先查看iomem哪一块内存可以使用,如下:

root@Openwrt:~# cat /proc/iomem

...

40000000-42ffffff : System RAM
43030000-4fffffff : System RAM
  44000000-44615fff : reserved
  48080000-487bffff : Kernel code
  487c0000-4880ffff : reserved
  48810000-488affff : Kernel data
  4e7f2000-4f5fffff : reserved
  4f7f2000-4f7f7fff : reserved
  4fc00000-4fdfffff : reserved
  4ff4b000-4ffabfff : reserved
  4ffac000-4ffd3fff : reserved
  4ffd6000-4ffd6fff : reserved
  4ffd7000-4ffd7fff : reserved
  4ffd8000-4ffd9fff : reserved
  4ffda000-4fff6fff : reserved
  4fff7000-4fffffff : reserved

RAM 的物理地址空间为 40000000-4fffffff,256MB。选择在 Kernel code 和 Kernel data 之外的 40000000 作为 ramoops 的起始地址,大小为 1MB。

修改后的RAM,如下:多了一块预留的内存。

40000000-42ffffff : System RAM
  41000000-410fffff : reserved
43030000-4fffffff : System RAM
  44000000-44615fff : reserved
  48080000-487bffff : Kernel code
  487c0000-4880ffff : reserved
  48810000-488affff : Kernel data
  4e7f1000-4f5fffff : reserved
  4f7f1000-4f7f6fff : reserved
  4fc00000-4fdfffff : reserved
  4ff4b000-4ffabfff : reserved
  4ffac000-4ffd3fff : reserved
  4ffd6000-4ffd7fff : reserved
  4ffd8000-4ffd9fff : reserved
  4ffda000-4fff6fff : reserved
  4fff7000-4fffffff : reserved

所以在dts里面添加如下配置:

	reserved-memory {
		#address-cells = <2>;
		#size-cells = <2>;
		ranges;

		...

		ramoops@40000000 {
			compatible = "ramoops";
			reg = <0x0 0x41000000 0x0 0x00100000>;
			record-size     = <0x00020000>;
			console-size    = <0x00020000>;
			ftrace-size     = <0x00020000>;
		};

	};

嵌入式Linux上使用Ramoops:http://www.gongkong.com/article/202209/101525.html

3.2 pstore实现流程说明
3.3 pstore写入测试

制造panic

root@zihome:/# echo c > /proc/sysrq-trigger 
[766252.198643] sysrq: SysRq : Trigger a crash
[766252.202989] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
[766252.212172] Mem abort info:
[766252.215150]   ESR = 0x96000046
[766252.218383]   Exception class = DABT (current EL), IL = 32 bits
[766252.224572]   SET = 0, FnV = 0
[766252.227811]   EA = 0, S1PTW = 0
[766252.231132] Data abort info:
[766252.234185]   ISV = 0, ISS = 0x00000046
[766252.238230]   CM = 0, WnR = 1
[766252.241375] user pgtable: 4k pages, 39-bit VAs, pgdp = 000000005925b985
[766252.248287] [0000000000000000] pgd=0000000049706003, pud=0000000049706003, pmd=0000000000000000
[766252.257356] Internal error: Oops: 96000046 [#1] SMP
[766252.262470] Modules linked in: zfirewall mt753x zdlogin pppoe ppp_async pppox ppp_generic iptable_nat ipt_REJECT ipt_MASQUERADE xt_time xt_tcpudp xt_tcpmss xt_string xt_statistic xt_state xt_recent xt_quota xt_pkttype xt_owner xt_nat xt_multiport xt_mark xt_mac xt_limit xt_length xt_iprange xt_hl xt_helper xt_ecn xt_dscp xt_conntrack xt_connmark xt_connlimit xt_connbytes xt_comment xt_bpf xt_addrtype xt_TCPMSS xt_REDIRECT xt_NETMAP xt_LOG xt_HL xt_FLOWOFFLOAD xt_DSCP xt_CT xt_CLASSIFY ts_kmp ts_fsm ts_bm slhc nf_reject_ipv4 nf_nat_ipv4 nf_log_ipv4 nf_flow_table_hw nf_flow_table nf_conntrack_rtcache nf_conntrack_netlink nf_conncount iptable_raw iptable_mangle iptable_filter ipt_ECN ip_tables crc_ccitt br_netfilter 8250_pci fuse sch_teql sch_sfq sch_red sch_prio sch_pie sch_multiq sch_gred sch_fq sch_dsmark
[766252.336250]  sch_codel em_text em_nbyte em_meta em_cmp act_simple act_police act_pedit act_ipt act_gact act_csum act_connmark sch_tbf sch_ingress sch_htb sch_hfsc em_u32 cls_u32 cls_tcindex cls_route cls_matchall cls_fw cls_flow cls_basic act_skbedit act_mirred znetstat sg hid evdev input_core xt_set ip_set_list_set ip_set_hash_netportnet ip_set_hash_netport ip_set_hash_netnet ip_set_hash_netiface ip_set_hash_net ip_set_hash_mac ip_set_hash_ipportnet ip_set_hash_ipportip ip_set_hash_ipport ip_set_hash_ipmark ip_set_hash_ip ip_set_bitmap_port ip_set_bitmap_ipmac ip_set_bitmap_ip ip_set nfnetlink ip6table_nat ip6t_NPT ip6t_MASQUERADE nf_nat_ipv6 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_log_ipv6 nf_log_common ip6table_mangle ip6table_filter ip6_tables ip6t_REJECT x_tables nf_reject_ipv6
[766252.409111]  nfsv4 nfsv3 nfsd nfs msdos bonding ip6_gre ip_gre gre ifb sit sctp ipip ip6_tunnel tunnel6 tunnel4 ip_tunnel rpcsec_gss_krb5 auth_rpcgss oid_registry tun vfat fat udf crc_itu_t ntfs lockd sunrpc grace minix isofs hfsplus hfs cramfs configfs cifs autofs4 rxrpc dns_resolver fscache nls_utf8 nls_iso8859_1 nls_cp437 vxlan udp_tunnel ip6_udp_tunnel sha512_generic sha1_generic seqiv pcbc md5 md4 fcrypt des_generic cts ctr ccm cbc arc4 usb_storage sdhci_pltfm sdhci leds_gpio xhci_plat_hcd ohci_pci uhci_hcd ohci_platform ohci_hcd ehci_pci ehci_platform ehci_hcd gpio_button_hotplug xfs reiserfs jfs f2fs ext4 mbcache jbd2 exfat btrfs zstd_decompress zstd_compress xxhash xor raid6_pq libcrc32c crc32c_generic crc32_generic [last unloaded: mt753x]
[766252.477621] Process ash (pid: 1143, stack limit = 0x00000000d9570130)
[766252.484353] CPU: 0 PID: 1143 Comm: ash Tainted: G S      W         4.19.81 #0
[766252.491797] Hardware name: ZIHOME ZH-A0501 Board (DT)
[766252.497091] pstate: 80000005 (Nzcv daif -PAN -UAO)
[766252.502122] pc : sysrq_handle_crash+0x14/0x20
[766252.506701] lr : __handle_sysrq+0xd0/0x170
[766252.511008] sp : ffffff800a30bcf0
[766252.514508] x29: ffffff800a30bcf0 x28: ffffffc00bbb9f80 
[766252.520072] x27: 0000000000000000 x26: 0000000000000000 
[766252.525636] x25: 0000000056000000 x24: 0000000000000015 
[766252.531200] x23: ffffff800883ef70 x22: 0000000000000000 
[766252.536764] x21: 0000000000000008 x20: 0000000000000063 
[766252.542328] x19: ffffff8008825000 x18: 0000000000000000 
[766252.547892] x17: 0000000000000000 x16: 0000000000000000 
[766252.553456] x15: 0000000000000000 x14: 0000000000000000 
[766252.559019] x13: ffffff800886b2a0 x12: 0000000000000000 
[766252.564583] x11: ffffff8008818548 x10: 0000000000000010 
[766252.570147] x9 : 0000000000000000 x8 : 0000000000000000 
[766252.575711] x7 : 000000000000000f x6 : 000000000000028b 
[766252.581274] x5 : 0000000000000001 x4 : 0000000000000001 
[766252.586838] x3 : 0000000000000007 x2 : 0000000000000007 
[766252.592401] x1 : 0000000000000000 x0 : 0000000000000001 
[766252.597965] Call trace:
[766252.600572]  sysrq_handle_crash+0x14/0x20
[766252.604791]  write_sysrq_trigger+0x6c/0x80
[766252.609103]  proc_reg_write+0x5c/0x98
[766252.612965]  __vfs_write+0x18/0x130
[766252.616646]  vfs_write+0xb4/0x178
[766252.620148]  ksys_write+0x50/0xa0
[766252.623649]  __arm64_sys_write+0x18/0x20
[766252.627780]  el0_svc_common+0x8c/0xf0
[766252.631641]  el0_svc_handler+0x68/0x70
[766252.635591]  el0_svc+0x8/0xc
[766252.638647] Code: 52800020 b908d020 d5033e9f d2800001 (39000020)
[766252.645017] ---[ end trace f30f2fc370a0dcc8 ]---
[766252.658770] Kernel panic - not syncing: Fatal exception
[766252.664248] SMP: stopping secondary CPUs
[766252.668379] Kernel Offset: disabled
[766252.672062] CPU features: 0x0,20002000
[766252.676010] Memory Limit: none
[766252.688058] Rebooting in 3 seconds..

重启成功后,手动挂载查看内存保存的数据。

mount -t pstore pstore /sys/fs/pstore

将pstore的内容挂载到文件系统,如果有内容的话就会在文件系统下生成文件,如下:

root@openwrt:/# ls /sys/fs/pstore/
console-ramoops-0

我们可以添加启动脚本,当发下存在内容的话,则把内容写入到mtd分区

mtd -q write /sys/fs/pstore/console-ramoops-0 kpanic

当然这样有很多弊端,比如

  • panic后还没重启成功,写入的mtd的时候系统被断电了,那就没有日志了
  • 不像mtdoops那样,可以存储多份panic日志,做标记循环存储
  • 好像reboot的时候,也会生成pstore文件,需要过滤,不是panic的没有必要存。

添加重启后自动写入脚本

cat /etc/init.d/zpstore 
#!/bin/sh /etc/rc.common

START=99
STOP=99

start() {
    mount -t pstore pstore /sys/fs/pstore

    local pstore_file="/tmp/pstore_file"
    need_save=0

    if [ -f $pstore_file ];then
            rm ${pstore_file}
    fi
    touch ${pstore_file}

    for line in `ls /sys/fs/pstore/`
    do
            local file=/sys/fs/pstore/$line
            local panic_msg="$(grep -rn "Call trace" $file)"  #包含Call trace字段的说明是panic信息,进行保存

            if [ "$panic_msg" != "" ]; then
                    need_save=1
                    echo "PANIC time: $(date)" >> $pstore_file
                    cat $file >> $pstore_file
            fi
    done

    if [ $need_save == 1 ]; then
            mtd -q write $pstore_file kpanic
    fi
}

重启后查看mtd日志

如果我们定义的kpanic分区位于mtd1,则如下查看

root@openwrt:/tmp# cat /dev/mtdblock1 > 1.txt
root@openwrt:/tmp# cat 1.txt
4、panic写入后没有自动重启问题解决

有时候panic挂了,也写入mtd。但是系统没有重启。可以观察到内核主动调用的reboot好像被写mtd的打断了,没有调用成功。

但是内核看门狗也没有把系统重启,将内核看门狗的日志打印出来,可以观察到还是有进程一直在给看门狗喂狗(应该是procd进程没Kill掉,一直5秒喂一次狗导致)

内核看门狗代码位于./drivers/watchdog/mt7621_wdt.c中

static int mt762x_wdt_ping(struct watchdog_device *w)
{
	rt_wdt_w32(TIMER_REG_TMRSTAT, TMR1CTL_RESTART);

	return 0;
}

所以在内核看门狗中添加panic捕获机制,如果出现panic的时候,将看门狗触发时间改成3秒,这个就算procd进行没挂,等5秒再喂狗也来不及了,系统会被看门狗重启。

代码如下:

static int mt762x_panic_notify(struct notifier_block *this, unsigned long code, void *unused)
{
	printk("mt762x_panic_notify\n");
	printk("Rebooting in 3 seconds..");
	mt762x_wdt_stop(&mt762x_wdt_dev);
	mt762x_wdt_set_timeout(&mt762x_wdt_dev, 3);
	mt762x_wdt_start(&mt762x_wdt_dev);     /* Turn on the WDT to avoid panic hangup */

	return NOTIFY_DONE;
}

static struct notifier_block mt762x_panic_notifier = {
	.notifier_call = mt762x_panic_notify,
};


static int mt762x_wdt_probe(struct platform_device *pdev)
{
	....

	atomic_notifier_chain_register(&panic_notifier_list, &mt762x_panic_notifier);

	....
}
5、有时候重启的时候会挂,但是panic没有写入mtd

还不知道原因

[  286.332508] get_wdev_by_idx: invalid idx(1)
[  286.336937] CPU 0 Unable to handle kernel paging request at virtual address 000000b0, epc == 814f6ec0, ra == 8125bd80
[  286.347597] Oops[#1]:
[  286.349875] CPU: 0 PID: 7557 Comm: reboot Not tainted 4.4.198 #0
[  286.355885] task: 87e691a0 task.stack: 8061a000
[  286.360413] $ 0   : 00000000 00000001 00000010 00000000
[  286.365656] $ 4   : 87e04c00 8180c26c 00000200 0014d000
[  286.370895] $ 8   : 00000000 00005e30 00000000 00000133
[  286.376135] $12   : 00000000 00000000 00000133 00000000
[  286.381372] $16   : 87e04c74 87e04468 81cd0000 81d40000
[  286.386613] $20   : 81d10000 8180c26c 87e04c9c 77e8fd8c
[  286.391852] $24   : 00000002 814f6e80                  
[  286.397091] $28   : 8061a000 8061bd78 00000000 8125bd80
[  286.402332] Hi    : 00000000
[  286.405207] Lo    : 122f2000
[  286.408095] epc   : 814f6ec0 rt_pci_shutdown+0x40/0x204
[  286.413329] ra    : 8125bd80 device_shutdown+0x168/0x210
[  286.418635] Status: 11008403 KERNEL EXL IE 
[  286.422830] Cause : c0800008 (ExcCode 02)
[  286.426834] BadVA : 000000b0
[  286.429710] PrId  : 0001992f (MIPS 1004Kc)
[  286.433800] Modules linked in: mt753x iptable_nat nf_nat_ipv4 nf_conntrack_ipv6 nf_conntrack_ipv4 ipt_REJECT ipt_MASQUERADE xt_time xt_tcpudp xt_tcpmss xt_string xt_statistic xt_state xt_recent xt_nat xt_multiport xt_mark xt_mac xt_limit xt_length xt_iprange xt_hl xt_helper xt_ecn xt_dscp xt_conntrack xt_connmark xt_connlimit xt_connbytes xt_comment xt_TCPMSS xt_REDIRECT xt_LOG xt_HL xt_DSCP xt_CLASSIFY ts_kmp ts_fsm ts_bm nf_reject_ipv4 nf_nat_redirect nf_nat_masquerade_ipv4 nf_nat nf_log_ipv4 nf_defrag_ipv6 nf_defrag_ipv4 mtfwd mapfilter iptable_mangle iptable_filter ipt_ECN ip_tables crypto_hw_eip93 crc_ccitt fuse act_ipt em_nbyte em_meta em_text sch_codel em_cmp act_connmark nf_conntrack em_u32 sch_ingress sg ip6t_REJECT nf_reject_ipv6 nf_log_ipv6 nf_log_common ip6table_mangle ip6table_filter ip6_tables x_tables msdos ip_gre gre ifb l2tp_netlink l2tp_core udp_tunnel ip6_udp_tunnel ip_tunnel vfat fat nls_utf8 nls_iso8859_1 nls_cp437 nls_base sha1_generic ecb des_generic authenc leds_gpio sd_mod scsi_mod gpio_button_hotplug ext4 jbd2 mbcache mbcache2 crc32c_generic [last unloaded: mt753x]
[  286.530843] Process reboot (pid: 7557, threadinfo=8061a000, task=87e691a0, tls=77e96d48)
[  286.538927] Stack : fee1dead 77e8b000 77e8e518 77e8fd8c 87e04c74 87e04468 87e04c68 81d40000
          81d10000 8180c26c 87e04c9c 77e8fd8c 00000000 8125bd80 87e69480 00000000
          00000000 81900000 00000000 81900000 81910000 01234567 fee1dead 77e8b000
          77e8e518 8104fff4 00000000 00000001 8061be50 81900000 00000000 8105030c
          8111dfe0 00000000 fffffffb 8782e144 0000000d 810bb3e0 8782e010 00000000
          ...
[  286.574568] Call Trace:
[  286.577013] [<814f6ec0>] rt_pci_shutdown+0x40/0x204
[  286.581895] [<8125bd80>] device_shutdown+0x168/0x210
[  286.586873] [<8104fff4>] kernel_restart+0x14/0x68
[  286.591576] [<8105030c>] SyS_reboot+0x134/0x21c
[  286.596116] [<810078d8>] syscall_common+0x30/0x54
[  286.600816] 
[  286.602302] 
Code: 8c4300d0  8e422340  30420010 <1040000a> 8c7600b0  3c0281cd  8c421fd0  30420002  10400005 
[  286.612430] ---[ end trace 97f3cc1d21a76f95 ]---
[  286.618682] Fatal exception: panic in 5 seconds
[  291.631880] Kernel panic - not syncing: Fatal exception
[  291.639833] CPU 0 Unable to handle kernel paging request at virtual address 0000024c, epc == 812851e4, ra == 81278f30
[  291.650442] Oops[#2]:
[  291.652725] CPU: 0 PID: 7557 Comm: reboot Tainted: G      D         4.4.198 #0
[  291.659950] task: 87e691a0 task.stack: 8061a000
[  291.664478] $ 0   : 00000000 00000001 00000000 00000000
[  291.669726] $ 4   : 86558018 00000000 000d8000 00000000
[  291.674973] $ 8   : 86558018 00000000 c0047000 6e202d20
[  291.680221] $12   : 7320746f 00000000 00000000 69636e79
[  291.685468] $16   : 00000000 81910000 00000001 000d8000
[  291.690716] $20   : 81d30000 81d30000 81d30000 81d30000
[  291.695963] $24   : 00000018 812851c0                  
[  291.701210] $28   : 8061a000 8061ba68 00000001 81278f30
[  291.706460] Hi    : 0000003f
[  291.709337] Lo    : 2e147bde
[  291.712249] epc   : 812851e4 panic_nand_write+0x24/0xe0
[  291.717477] ra    : 81278f30 mtdoops_write+0x64/0xf4
[  291.722439] Status: 11008402 KERNEL EXL 
[  291.726374] Cause : 40800008 (ExcCode 02)
[  291.730381] BadVA : 0000024c
[  291.733261] PrId  : 0001992f (MIPS 1004Kc)
[  291.737355] Modules linked in: mt753x iptable_nat nf_nat_ipv4 nf_conntrack_ipv6 nf_conntrack_ipv4 ipt_REJECT ipt_MASQUERADE xt_time xt_tcpudp xt_tcpmss xt_string xt_statistic xt_state xt_recent xt_nat xt_multiport xt_mark xt_mac xt_limit xt_length xt_iprange xt_hl xt_helper xt_ecn xt_dscp xt_conntrack xt_connmark xt_connlimit xt_connbytes xt_comment xt_TCPMSS xt_REDIRECT xt_LOG xt_HL xt_DSCP xt_CLASSIFY ts_kmp ts_fsm ts_bm nf_reject_ipv4 nf_nat_redirect nf_nat_masquerade_ipv4 nf_nat nf_log_ipv4 nf_defrag_ipv6 nf_defrag_ipv4 mtfwd mapfilter iptable_mangle iptable_filter ipt_ECN ip_tables crypto_hw_eip93 crc_ccitt fuse act_ipt em_nbyte em_meta em_text sch_codel em_cmp act_connmark nf_conntrack em_u32 sch_ingress sg ip6t_REJECT nf_reject_ipv6 nf_log_ipv6 nf_log_common ip6table_mangle ip6table_filter ip6_tables x_tables msdos ip_gre gre ifb l2tp_netlink l2tp_core udp_tunnel ip6_udp_tunnel ip_tunnel vfat fat nls_utf8 nls_iso8859_1 nls_cp437 nls_base sha1_generic ecb des_generic authenc leds_gpio sd_mod scsi_mod gpio_button_hotplug ext4 jbd2 mbcache mbcache2 crc32c_generic [last unloaded: mt753x]
[  291.834567] Process reboot (pid: 7557, threadinfo=8061a000, task=87e691a0, tls=77e96d48)
[  291.842654] Stack : c004704d 00000001 81d3df40 81910000 00001f68 00004b08 00006b50 00000000
          000000f0 00000000 00000155 8107200c 81800000 818034f0 ff0a0000 81d3df40
          81910000 00000001 8190e134 81278f30 00000001 c004704e 00000000 81d30000
          00002000 8061badc c0047000 8190e134 81d30000 00000000 81d30000 81d3df40
          00000029 812790b0 00000000 00000003 8190d5f4 00000000 00000000 0000000e
          ...
[  291.878358] Call Trace:
[  291.880810] [<812851e4>] panic_nand_write+0x24/0xe0
[  291.885697] [<81278f30>] mtdoops_write+0x64/0xf4
[  291.890319] [<812790b0>] mtdoops_do_dump+0xf0/0x11c
[  291.895215] [<81074ed8>] kmsg_dump+0xdc/0x11c
[  291.899590] [<81032b88>] panic+0xcc/0x204
[  291.903608] [<81018aec>] die+0x128/0x130
[  291.907551] [<81021ea8>] __do_page_fault+0x360/0x48c
[  291.912522] [<81005420>] ret_from_exception+0x0/0x10
[  291.917483] 
[  291.918972] 
Code: 8c9000f0  00c09821  00071840 <8e02024c> 8e050498  00023027  00e09021  00c33004  00531806 
[  291.929226] ---[ end trace 97f3cc1d21a76f96 ]---
[  291.936505] Fatal exception: panic in 5 seconds

kernel crash dump info 保存:https://blog.youkuaiyun.com/u012385733/article/details/79257442

内核printk原理介绍:https://zhuanlan.zhihu.com/p/521094976

kmsg_dump kmsg_dump提供一种机制在系统挂掉的时候将log转存到其他介质如ramoos或者mtd等.我们以mtd中的使用为例来分析kmsg_dump机制. 使用kmsg_dump之前要先使用kmsg_dump_register来注册一个dumper,用于实际的log写函数. 我们先来看看kmsg_dump_register的定义,只定义了一个dump_list,将系统中所有注册的dump都挂在同一 阅读详情

相关推荐

PSTORE ramoops 在Linux x86_64 与 arm64上使用

Pstore中的ramoops,分别在linux x86_64 与arm64上的使用。其中主要说明了怎么自动分配一段内存来作为ramoops 存储log的预留内存的方式。

bboy_knowns的博客 3050

linux内核panic

1. Linux Kernel Panic的产生的原因      panic是英文中是惊慌的意思,Linux Kernel panic正如其名,linux kernel不知道如何走了,它会尽可能把它此时能获取的全部信息都打印出来。 有两种主要类型kernel panic,后面会对这两类panic做详细说明: 1.hard panic(也就是Aieee信息输出) 2.soft p

ylyuanlu的专栏 5万+

STM32MP1 eMMC启动PANIC及CubeProgrammer连不上解决

在嵌入式Linux开发中,启动链路的稳定性直接决定产品能否可靠工作。从片上ROM加载FSBL,到U-Boot引导内核,再到挂载rootfs,每个环节都依赖设备树、分区表和bootargs的正确配置。当eMMC作为启动介质时,分区编号或MMC设备序号的偏差,极易引发Kernel panic,屏幕上的“Unable to mount root fs”让开发者误以为硬件损坏。同时,调试工具STM32CubeProgrammer的连接受限于芯片复位状态与BOOT引脚配置,启动循环中的芯片常常报“No target

weixin_30336061的博客 326

嵌入式系统linux 记录内存panic

简介 在内存发生panic时,需要把panic的日志保存下来。以方便日后进行分析。 目前有三种记录的方式: kdump; mtdoops; crashlog(这是openwrt特别的功能,正式linux内核中没有) 大家对kdump比较了解。它主要使用于x86系统。因为它使用占用大量内存和硬盘。 mtdoops和crashlog主要用于嵌入式的环境。也只是记录文本日志。 mtdo

刘末的专栏 6117

Linux内核头文件缺失:解决“Unable to find kernel source tree”错误

在Linux系统中,内核模块是扩展内核功能的核心机制,它允许动态加载驱动程序、文件系统支持等组件。其工作原理在于,模块编译时必须严格匹配当前运行内核的接口定义和数据结构,这需要内核头文件提供精确的“蓝图”。这一机制的技术价值在于保证了系统的稳定性和安全性,避免了因模块与内核版本不匹配导致的崩溃。在应用场景上,无论是安装NVIDIA显卡驱动以支持CUDA深度学习计算,还是部署VirtualBox等虚拟化环境,都依赖于此。当出现“Unable to find the kernel source tree”报错时

weixin_34294649的博客 480

04 _openWRT环境kernel分析

/***************************************************************************************************************** Document Author : ELvins ...

Tree_in_sea的博客 789

Linux系统Kernel Panic定义

Linux系统Kernel Panic定义 Panic即恐慌,内核恐慌指的是一类消息,它由操作系统发现难以修复的内部错误后,显示为“panic”,主要在Unix或类Unix上使用该术语。 内核处理程序对于panic的处理,通常是将调试信息输出到文件或者屏幕,然后让计算机停止运行。 嵌入式设备出于debug的需要,也可以在debug信息写入到Flash的指定空闲分区中,这样在系统重启后仍然可以看到该信息。 ...

zhengyuchao_的博客 2263

嵌入式Linux启动全解析:Uboot、Kernel与Rootfs的协作与实战

在嵌入式系统开发中,系统启动流程是理解设备从硬件上电到应用运行的核心基础。其基本原理遵循经典的引导加载程序(Bootloader)→操作系统内核(Kernel)→根文件系统(Rootfs)的递进式加载链。Bootloader(如Uboot)负责初始化最基础的硬件环境,为加载内核做好准备;内核则接管硬件资源,进行深度初始化并管理进程、内存等核心子系统;最终,内核需要挂载一个包含应用程序和库的根文件系统,才能完成启动并进入用户空间。这一流程的技术价值在于实现了硬件抽象与软件分层,使得嵌入式设备能够运行复杂的应用

weixin_33698043的博客 324

Kernel panic - not syncing: Attempted to kill init!(移植linux2.6.29.4进友善mini2440开发板时遇到)

移植linux2.6.29.4进友善mini2440开发板 发布时间:2009-07-08 23:48:48 技术类别:ARM     终于移植成功,总结下: 移植linux2.6.29.4内核+yaffs2文件系统过程 软件平台:vm(fodera 9)+arm-linux-gcc 4.3.2 参考资料:网上n多资料

Allen.Yao的专栏 4928

联想ThinkPad声卡驱动安装避坑指南:从E470到X1 Carbon的通用解法

本文详细介绍了ThinkPad声卡驱动安装的全流程,从硬件识别到驱动获取、安装技巧及深度排错。涵盖E470到X1 Carbon等不同机型的通用解法,帮助用户解决音频驱动问题,提升使用体验。重点讲解了声音驱动的精准识别和安装策略,确保系统稳定运行。

weixin_29207439的博客 706

一次HTTP完整得请求过程

一次HTTP完整的请求过程 一,大致流程: 根据域名和DNS解析到服务器的IP地址(DNS+CDN) 通过ARP协议获得IP地址对应的物理机器得MAC地址 浏览器对服务器发起三次握手 建立TCP连接后发起HTTP请求报文 服务器响应HTTP请求,将响应报文返回浏览器 短连接情况下,请求结束通过TCP四次挥手关闭连接,长连接在没有访问服务器得若干时间后,进行连接关闭 浏览器得到响应信...

qq_40760617的博客 342

Linux驱动中写panic数据到裸设备

环境      内核版本:linux-2.6,当发生内核崩溃时,重启之前把panic打印信息保存在flash裸设备中保存; 代码     kernel/panic.c ++ @@ -48,6 +48,10 @@ long (*panic_blink)(int state); EXPORT_SYMBOL(panic_blink); +extern void xd_store_cr...

TSZ0000的博客 698

C语言头文件完全解析(连“#”我都给你讲明白)

C语言头文件完全解析 引言 本文将尽量详细的介绍c语言的头文件所包含的知识,如有错误,还望指正。 萌新们肯定疑惑为什么每次打代码都要写一个所谓的头文件(如:#include<stdio.h>),这里先简单让大家有个了解,你所用的 printf("%d",a)就是这个 stdio里的东西,如果没有这个头文件,编译器都不知道 printf是个什么东东。所以头文件就是一个准备好的大仓库,你可...

CRAZY_eyes的博客 7万+

自定义Yocto Machine的eMMC启动Panic恢复实战

在嵌入式Linux产品开发中,Yocto Project用于定制系统镜像,而eMMC作为核心存储介质,其启动机制与SD卡差异明显。STM32MP13系列处理器的启动链路涉及ROM、TF-A、FIP、U-Boot及内核多个阶段,任一环节配置不一致都可能导致Kernel Panic。典型故障如自定义Machine后eMMC启动时报“VFS unable to mount root fs”,同时STM32CubeProgrammer无法重新连接目标板,这往往源于分区表、bootargs与设备树配置未对齐,或下载模

weixin_34232744的博客 433

手把手教你用TL431设计反激电源补偿器(附波特图调试技巧)

本文详细介绍了如何使用TL431设计反激电源补偿器,并提供了波特图调试技巧。通过实战经验分享,帮助工程师快速掌握补偿网络设计、分压电阻计算和稳定性判据,避免常见设计误区,提升电源稳定性与效率。

weixin_29201859的博客 376

避坑指南:SAP成本中心分割结构配置常见错误及解决(含KA06/KL01前置步骤)

本文深入解析了SAP成本中心会计中分割结构配置的关键步骤与常见错误。重点强调了配置前必须通过KA06创建次级成本要素(类别42)和通过KL01创建活动类型这两个核心前置步骤,并详细剖析了在OKES中定义分割规则及版本时的高频报错原因与解决方案,帮助顾问和运维人员有效规避配置陷阱,确保成本分摊的准确性。

pear55的博客 864

2440 nand flash挂载不了文件系统解决

最近把落了灰尘的2440板子拿出来,移植linux,uboot烧进去,运行正常,内核编译好了下载进去,也能跑,做了文件系统下载进去启动,挂载不上,kernel panic 了 VFS: Mounted root (yaffs filesystem) on device 31:3. Freeing init memory: 160K Warning: unable to open an initial console. Failed to execute /linuxrc. Attempting ...

Lin9276的专栏 869

零中频架构实战:用Matlab模拟AD9361收发信号(附完整代码)

本文详细介绍了如何使用Matlab模拟AD9361射频收发器的零中频架构,解决镜像干扰等关键挑战。通过完整的代码示例和系统级建模方法,帮助工程师掌握RFIC设计中的自适应校准算法和性能优化技巧,特别适用于SDR系统开发。

weixin_30733003的博客 538

Petalinux QSPI启动实战:Zynq嵌入式Linux固件量产部署指南

QSPI启动是嵌入式Linux产品化落地的关键技术,其本质是构建从BootROM到init进程的可信启动链。它依托硬件初始化、分阶段引导(FSBL→U-Boot→Kernel→RootFS)、Flash分区管理与内核解压机制,实现掉电不丢配置、启动时间可控、固件安全升级等工业级需求。相比SD卡启动的易松动与JTAG依赖,QSPI凭借焊接式高可靠性、低功耗和10万次擦写寿命,成为工控网关、边缘AI设备等场景的首选启动介质。但其时序敏感、分区严格、烧录容错率低等特点,要求开发者深度理解Petalinux工具链如

weixin_34389926的博客 246

DeepSeek与豆包无缝对接:5分钟搞定智能周报自动化(附完整代码)

本文详细介绍了如何利用DeepSeek与豆包API,快速搭建一个智能周报自动化系统。通过整合豆包平台的工作流数据,并调用DeepSeek大模型进行深度分析与内容生成,该系统能在5分钟内自动抓取、分析多源信息,并生成结构清晰、富有洞察力的团队周报,显著提升工作效率。

weixin_29029995的博客 490

YOLOv13改进策略【小目标改进】| Shape-NWD:融合改进,结合Shape-IoU和NWD 更好地适应小目标特性

Bw−wgt2h−hgt2weight2Bweight2w−wgt​2h−hgt​2​其中weight2weight = 2weight2。

Limiiiing的博客 586

linux内核配置失败,linux_内核移植方法及错误

1.问题一下载内核到flash中,运行到如下即停止没有下文:Uncompressing Linux……………………done,booting the kernel卡在这里不动了原因分析:可能是内核的启动参数传递时没有填写正确,也可能是在linux内核中没对flash分区,还有另一可能原因是在内核编译配置时没将串口驱动勾选。解决办法:如果是命令参数问题,则作如下修改:注释掉arch/arm/kerne...

weixin_29748637的博客 884

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

对Linux分区失败的一个研究

嵌入式Linux操作系统目前已经广泛应用手机终端产品的开发,对于常见的嵌入式Linux操作系统,在终端主板上需要下载的软件包含几个部分:U-boot、Kernel、文件系统和用户应用程序。U-boot负责对文件系统和内核分行分区,主板在起动时加载主程序等工作;Kernel特定于嵌入式板子的定制内核以及内核的启动参数,并包括对某些功能的支持; 文件系统包括根文件系统和建立于Flash内存设备之上文件

gutian029的专栏 947

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

STM32MP135 eMMC启动内核Panic后的恢复实战

嵌入式Linux系统的启动依赖BootROM、FSBL、U-Boot与内核的逐级引导,任一环节异常都会导致系统失联。STM32MP135作为入门级工业MPU,采用eMMC作为唯一启动介质时,若内核发生Panic,可能因启动链路死循环使CubeProgrammer无法识别设备。从根文件系统挂载失败、设备树配置错误、bootargs传递错位等角度剖析内核Panic的典型成因,并给出强制进入DFU模式、清除eMMC引导数据、重新烧录的完整恢复流程。该排查方法适用于基于Yocto定制machine的嵌入式Linux

weixin_30326741的博客 408

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

从零构建最小Linux根文件系统:BusyBox实战与嵌入式开发指南

根文件系统是Linux操作系统启动和运行的基础,它为用户空间程序提供必要的运行环境、库文件和配置。其核心原理在于遵循文件系统层次结构标准,通过init进程作为首个用户空间程序来挂载虚拟文件系统、创建设备节点并启动服务。在嵌入式开发和系统定制领域,构建最小根文件系统具有极高的技术价值,它能帮助开发者深入理解系统启动流程,实现对系统组件的完全掌控,并满足IoT设备等对存储空间有严格限制的应用场景需求。本文以BusyBox这一集成数百个Unix工具的瑞士军刀为核心,结合ext4和jffs2等文件系统格式,详细演示

weixin_33913332的博客 1022

linux挂载u 盘只能root,为什么小弟我的uclinux无法挂载根文件系统?Kernel panic - not syncing: VFS: Unable to mount root fs on...

为什么小弟我的uclinux无法挂载根文件系统?Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)为什么小弟我的uclinux无法挂载根文件系统?Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(...

weixin_30050671的博客 292
上一篇: 2023新的征程
下一篇: 5-Linux 内存溢出oom
Creator_Ly
博客等级 码龄11年 633粉丝 212原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Creator_Ly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值