嵌入式开发常见问题记录

目录

uboot

设备启动时概率卡死

内核分区坏块导致内核加载失败

内核

编译gpio驱动报错error: macro “__TIME__“ might prevent reproducible builds [-Werror=date-time]

rmmod 驱动失败

文件系统

对文件进行写操作之后,立马断电重启,内容没有更新

UBI 不同大小的flash ubi预留的坏块大小不同(4g当2g用,同样大小的分区,4gflash上的可用容量比2g小)

计算UBI剩余可用容量

用户层

dos2unix

路由器重启更换网段之后导致域名解析失败

中文文件从windows拷贝到linux乱码问题

设置mac报错:ififconfig: SIOCSIFFLAGS: Cannot assign requested address

利用tftpd.exe在uboot下升级时,能ping通,但是下载不了数据

ubifs 报错


uboot

设备启动时概率卡死

Ingenic T31,偶现卡死在uboot

后面发现uboot中自己开发过功能,里面有调用打印函数printf。接口调用在main_loop第一行, 此时串口和控制台有可能没有完全初始化好,有概率导致问题。
解决方法是,调整入口位置,放在读秒之前,给串口和控制台预留足够的初始化时间。

结论:Printf函数在uboot中的使用必须在串口(serial)和控制台初始化(console)后才能使用或者在屏幕上打印出来。

如果太靠前,可能会导致uboot卡死。

另外不同机器的串口或控制台初始化可能会有点时间差异,最好放在内核已经使用过printf的逻辑后面增加新代码或新功能

uboot 执行printf后异常死机问题定位_wait_66的博客-CSDN博客

内核分区坏块导致内核加载失败

大批量烧录时出现部分设备启动失败,接串口后打印如下 提示大小超过分区限制

查看bootcmd

这里写的是固定从内核分区读8MB大小的数据,如果内核分区出现坏块,那么实际可读的分区大小就会小于8MB。

查看坏块 nand bad

SigmaStar # nand bad

Device 0 bad blocks:
  0c000000
SigmaStar # 

查看分区起始地址

可以发现坏块刚好落在内核分区,证明我的猜想是正确的。

手动读取内核分区内容

执行 dcache on ; nand read.e 0x23000000 KERNEL ;实际上不用指定读取的长度,命令会自己计算的。

启动成功。

内核

编译gpio驱动报错error: macro “__TIME__“ might prevent reproducible builds [-Werror=date-time]

 在编译gpio驱动时出现报错

查看Makefile

知识补充:

这里 -C $(KDIR) 指明跳转到内核源码目录下读取那里的Makefile;M=$(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile

查看内核Makefile

# Prohibit date/time macros, which would make the build non-deterministic
KBUILD_CFLAGS   += $(call cc-option,-Werror=date-time)

这里把时间宏给禁用了,导致编译不过。

暂时注释掉这一行,重新编译即可

rmmod 驱动失败

rmmod: can't change directory to '5.10.61': No such file or directory

根据报错可知/lib/modules/下没有5.10.61这个路径,创建即可

文件系统

对文件进行写操作之后,立马断电重启,内容没有更新

问题现象:使用nand + ubifs,使用IO操作更新文件后,立马触发看门狗重启。发现文件没有更新。

问题原因:ubif挂载分区的时候使用的是 mount -t ubifs ubi0:mtd /mnt/mtd

这里补充一个知识点:

mount -t ubifs ubi0:mtd /mnt/mtd -o sync,noatime

(sync,async 同步模式,异步模式(defaults)

此选项的默认模式为异步模式。在同步模式下,内存的任何修改都会实时的同步到硬盘当中,这种模式的安全性基本属于最高,但是因为内存的数据基本一致都在变化,所以这种模式会使得程序运行变得缓慢,影响效率。而在异步模式下,虽然同步没有实时,但是现在考虑到日志文件系统的存在,所以安全性基本不用考虑,而异步模式的效率会更高,随意目前普遍使用异步模式为默认

atime(defaults),noatime 是否在读访问时更新atime)

因为默认是异步模式,所以文件实际上是没有立即落地的,此时断电或者看门狗重启就有丢失的风险。

解决方案:改成同步模式 mount -t ubifs ubi0:mtd /mnt/mtd -o sync,noatime

UBI 不同大小的flash ubi预留的坏块大小不同(4g当2g用,同样大小的分区,4gflash上的可用容量比2g小)

kernel/drivers/mtd/ubi/build.c

*这里我们使用的是整个闪存芯片的大小,而不仅仅是MTD分区大小,因为坏的擦除块的最大数量是整个设备的百分比,坏的擦除块不是公平地分布在闪存芯片上。因此,最坏的情况是,芯片的所有坏的擦除块都在我们正在连接的MTD分区中(ubi-> MTD)。

Linux 内核驱动解析 - UBI坏块预留大小 - 知乎 (zhihu.com)

(124条消息) 【NAND文件系统】UBI介绍_ubi文件系统_知否,知否的博客-CSDN博客

计算UBI剩余可用容量

(124条消息) UBI文件系统分区开销计算_ubi分区占用空间_ivansuntech的博客-CSDN博客

用户层

dos2unix

.sh去解析文件时,解析失败,cat看是正常的,但是vi进去发现后面有^M导致失败。

 

查看十六进制

是因为0d归位键,在板子上无法识别导致。之所以出现0d是因为,这个文件是在windows进行创建和编辑的,我们按下回车时windows下会加上0d 0a,linux下则只有0d。

针对这个问题我们可以用dos2unix去处理,这个是linux自带的一个命令,可以把文件转成unix格式的

-k的意思是保持输出文件的日期不变,由于这个命令不支持递归,所以当我们要转换目录下的所有文件时可以使用xargs, 例如find  ./  -name  "*"  | xargs  dos2unix  -k

路由器重启更换网段之后导致域名解析失败

在后台修改 /etc/resolv.conf 中的配置,用户进程空间仍然存放的是老的 nameserver ,所以会导致解析失败

解决方案可以在获取域名之前调用一下res_init()

res_init() 函数的作用是读取 /etc/resolv.conf 的内容, 如 nameserver 地址、负载均衡策略、重试次数、超时时间等,并将读取的这些数据放到 static 类型的 _res_ 结构体中。

中文文件从windows拷贝到linux乱码问题

win下的默认格式一般是gbk,linux下时utf-8,因此从win下拷贝到linux服务器会出现乱码问题

可以使用 convmv 命令解决

ubuntu联网apt-get install convmv 即可安装

主要选项:
1、-f ENCODING
指定目前文件名的编码,如-f gbk
2、-t ENCODING
指定将要转换成的编码,如-f utf-8
3、-r
递归转换目录下所有文件名
4、--list
列出所有支持的编码
5、--notest
默认是只打印转换后的效果,加这个选项才真正执行转换操作。

例如:convmv -f gbk -t utf-8 ./* -r --notest, 将当前目录下的所有文件从gdk转换成utf-8

设置mac报错:ififconfig: SIOCSIFFLAGS: Cannot assign requested address

MAC 地址第二位数字必须是偶数,如果是奇数,为组播地址,只能作为目的地址,不能作为源地址

利用tftpd.exe在uboot下升级时,能ping通,但是下载不了数据

问题原因: windows 防火墙导致, 关闭windows防火墙即可

ubifs 报错

 制作好的ubifs使用 flash_eraseall 和 nandwrite 擦写之后,启动时偶现报错

解决方案: 擦写之前将分区下的用户进程全部杀掉,牵扯有mount的目录 全部umount

可以使用fuser -mk /mnt/mtd 杀掉进程

代码实现参考下面:

static int force_umount(const char *p_mount_dir, unsigned int try_cnt)
{
	int i = 0;

	if (NULL == p_mount_dir)
	{
		printf("get null pointer, error!\n");
		return -1;
	}

	char cmd_buf[256];

	/* fuser -mk /mnt/mtd 只能调用1次, 否则/mnt/mtd被umount后再次调用 fuser -mk /mnt/mtd 将会杀死所有进程 */
	memset(cmd_buf, 0, sizeof(cmd_buf));
	sprintf(cmd_buf, "cd /; fuser -mk %s", p_mount_dir);
	printf("cmd_buf=%s\n", cmd_buf);
	system(cmd_buf);
	memset(cmd_buf, 0, sizeof(cmd_buf));
	sleep(1);

	for (i = 0; i < try_cnt; i++)
	{
		if (0 == umount(p_mount_dir))
		{
			printf("%s umount success!\n", p_mount_dir);
			break;
		}
		else
		{
			printf("waitting [%s] umount......\n", p_mount_dir);
		}

		sleep(1);
	}

	if (i >= try_cnt)
	{
		printf("after %d try, %s not umount~~~~~\n", try_cnt, p_mount_dir);
		return -1;
	}

	return 0;
}

int main()
{
    force_umount("/mnt/mtd", try_cnt);
    return 0;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值