嵌入式LINUX新手问题大全——常见错误已及解决方法

时间:2022-09-07 16:05:42
前言
这里是在群里整理的同学们遇到的问题,有错和问题的情况下希望大家提出来发
[url=mailto:邮件至 1402284892@qq.com]邮件至 1402284892@qq.com[/url]
, 或者直接问老大。群里很多问题答案都是未果的。希望问题已解决的同学说一下
"问题已解决",如果能把
解决问题的思路解释一下就可以更好为大家做记录了,谢谢大家合作!大家问问
题的时候希望大家先整理
一下思路,把要问的问题详细的描述清楚。如果群里也许有些问题没有具体总结
到,大家也可以发邮件给我,我好做记录。现在文档的分类还不是很清晰,以后会尽量分好类的。如果有哪里整理的不好还望指出,
以后会加以修正。

注: 这是群里聊天的真实记录,没有任何修改,会有问替请问答疑助手
播放器下载: http://dl.dbank.com/c06bbt0sxp

1. 问:注册了输入设备就应该后续调用
input_attach_handler(dev, handler)
复制代码
然后根据id来判断是否支持
id = input_match_device(handler->id_table, dev)
复制代码
可是它仅仅弄了个id = 1,居然做到了匹配所有,我还是不大懂?
答: 看代码,
if (drvier_info)...
复制代码
就全部匹配.

2.  问:busybox中的库文件用的是2.7,但是不能启动内核了,不能找到linuxrc
答:  应该是文件系统没做好,或是没烧好

3. 问:
mem_cfg_val:
    @ 存储控制器13个寄存器的设置值
    .long   0x22011110      @ BWSCON
复制代码
答: BWSCON这个值 0x22011110      是这么算出来的呢
答:看看反汇编是个好方法,再对照2440手册,这基本上是用来配置BANK位宽的
完全手册上有介绍

4.问:为什么中断程序里:
sub ir,lr, #4
复制代码
答: 发生中断时,PC的值已经指向了下一条指令,但是PC所指的指令并没有被执行,所以返回时,要减4

5. 问:老师,那个TAG,一般都是放在四个分区的哪个位置的,比如是在,256K的u-boot中,还是param分区中?他的物理地址大概在哪啊
答:TAG是UBOOT运行时临时生成的,不在存在FLASH里



6. 移植uboot出现
SMDK2410 # nfs 32000000 192.168.1.51:/work/nfs_root/uImage_new
dm9000 i/o: 0x20000000, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 08:00:3e:26:0a:5b
could not establish link
Using dm9000 device
File transfer via NFS from server 192.168.1.51; our IP address is 192.168.1.17
Filename '/work/nfs_root/uImage_new'.
Load address: 0x32000000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ##############T T *** ERROR: Cannot umount
复制代码
答:修改drivers/net/nfs.c里面的#define NFS_TIMEOUT (10*2000UL),把这个超时时间调大点

7.问:JZ2440插上TF卡后,怎么去挂载,去格式化TF卡?
答:接上去后,看看串口打印信息,接上去后,串口就自动有显示了
贴出来

8. 问:韦老师,编译内核出现
/i686/cmovbc.so.6: version `GLIBC_2.11' not found
复制代码
是什么原因
答:编译器版本太老,换个新点的

9. 问:我该找些什么书看呢,老师在视频里写驱动都是加载是不是真正做项目时候
答:对于驱动程序,可以编进内核里,也可以insmod
实际工作中也是这2种方式
对于稳定的驱动,可以编进内核里
对于经常修改的,insmod
至于启动后就显示界面,这就要写应用程序;另一个是修改启动脚本──这可以看根文件系统视频,了解init进程

10.问:老师,手机刷的ROM到底是啥
答:内核、文件系统

11.uImage和zImage在uboot中的环境变量设置有什么不同?
答:uboot不支持zImage

12.问:老师, 那个linux的启动  arm和powerpc是不是差别有点大?
答: 同一个版本的内核,启层过程是类似的

13.问:韦老师,内核反汇编为什么不是
arm-linux-objdump -D uImage > uImage.dis?
复制代码
答: vmlinux才是原汁原味的内核,uImage = 64字节头部+被压缩的vmlinux

14.问:这里dm9000的操作有个地方不大明白?
static void dm9000_reset(board_info_t * db){
writeb(DM9000_NCR, db->io_addr);
udelay(200);
writeb(NCR_RST, db->io_data);
udelay(200);
}...   <span style="line-height: 1.5;">reset操作就是往下面寄存器写NCR_RST,可是上面函数中db->io_addr代表S3C2410_CS4</span>
复制代码


答:对于DM9000,要把数据B写入地址A,是这样操作的:
先把A作为数值发给io_addr;再把B作为数值发给io_data。
io_addr和io_data的差别在于地址线BIT2,对应DM9000的CMD引脚.

15.问:最近在弄mini2440的摄像头,在运行测试程序时出现提示
map framebuffer failed
复制代码
不知道什么问题会导致framebuff  failed
答: 从你提供的信息来看是mmap时出错,可以在摄像头的的mmap函数里加打印看它为何返回错误

16。问:我这最近在玩GSM模块,需要用到uart;我发现在终端中,开发板自己本身用的是s3c2410_serial0, 我想知道是如何来确定引脚引脚与设备文件的关系?,在/dev下,还有很多tty设备文件,这些是具体怎么关联到引脚上的?
答: /dev/tty1,2...等都是虚拟的设备,不用管它。
你只需要管/dev/s3c2410_serial0,1,2;在驱动程序里,它会操作的UART的对应寄存器,设置对应的引脚

17.问:嵌入式Linux低功耗进入睡眠后,我们通过外部中断进行唤醒。我想问一下,这里外部中断唤醒,是不是就像我们申请的Linux中断处理一样,申请注册中断处理函数? 一直疑惑,这里不知道中断唤醒的入口是在什么地方?
答: 对于休眠唤醒的过程我还没有深究,不过它不止涉及内核及驱动,还涉及BOOT。
过程是这样的:
1. 休眠转为唤醒时,相当于按下复位键,这意味着BOOT会重新运行。
2.在BOOT里,你要判断是正常复位还是休眠唤醒
3.如果是唤醒,就去设置CPU状态....
后面的我就没有深究了;

18.问:移植内核网卡收不到数据
答: JZ2440上使用的是最新的DM9000C芯片,
内核里自带的DM9000驱动适用于老款DM9000,但是不适合
dm9000dev.c是我从厂家得到的最新驱动,在它上面修改

19.问:linux中如何确定中断号?
答:在内核源码里,对每一个中断都定义好了宏。
你只需要搜request_irq,就可以找到某一个宏,再查看这个宏在哪一个头文件里;
最后去看这个头文件,那里有众多宏,根据名字就可以确定你要的中断号是哪个了


20.问:在做iic裸板实验时候,考虑到链接地址是0x30000000,故将.bin用tftp下载
内存0x31000000位置,然后go  0x31000000执行没有现象,但是下到nand有现象?
然后用go测试led有现象?请问是怎么回事
答: 答:1. 链接地址是0x30000000的话,你就应该用tftp把它下载到0x30000000
    2. 程序已经在SDRAM里时,你的启动代码就不要做以下事情:
    a. 初始化时钟、初始化SDRAM
    b. 重定位代码

21.. 问:老师,在您的Mini文件系统下执行可执行程序怎么出现这种情况呢?是不是缺少什么库?
答:
1.开发板上lib目录来自编译器A
2.就要用同一个编译器A来编译应用程序


22.问:我加载lcd出现了如下错误,不知道是什么情况,麻烦看下
[root@Enjoylinux 3.4.55]# insmod lcd.ko
lcd: Unknown symbol unregister_framebuffer (err 0)
lcd: Unknown symbol framebuffer_alloc (err 0)
lcd: Unknown symbol register_framebuffer (err 0)
lcd: Unknown symbol framebuffer_release (err 0)
insmod: can't insert 'lcd.ko': unknown symbol in module or invalid parameter
复制代码
答:你应该把fbmem.c编进内核

23.问:问:用的是NFS启动,现在怀疑是库没考全,我用的是4.4.3编译器,目录内容如下
命令是:cp *.so* /ceshi/file_system/jy_fs/lib可是还是会出现我用老师的mini系统吧,倒是能起来,但是编译器版本和内核编译器又不一样,老出问题,一些驱动实验没法做,自己弄得这个还总不成功,郁闷啊
这个根文件到底哪里出了问题?
答:这肯定就是根文件系统没做好:
    1.根文件系统为内容不对,比如库没拷全
    2.根文件系统烧写到FLASH上不对
linuxrc是到/sbin/init的链接,在busybox里你可以看init.c的源码。
完全手册“根文件系统”那章讲有这个

24.问: 加载nand驱动出现
unknow symbol nand_scan
复制代码
答:CONFIG_MTD_NAND 要配上,
对于这类问题,你可以在source insight里看看nand_scan函数在哪个C文件里定义,
再去看同目录的Makefile确定这个C文件对应哪个配置项

25. 问:我修改老师的输入子系统按键驱动到TQ2440开发板,加载驱动后,按按键,内核产生中断,但就是应用程序读不到数据,我的内核版本为2.6.36
答:1. 你的应用程序可能要在按下“回车按钮”时,read才有返回
    2.建议用 命令:
hexdump /dev/event0
复制代码


26.问:irq和frq的区别是?
答:从硬件角度来说,FIQ是中断的一种,但是硬件上它的响应速度更快。
这需要从根源说起:
1.IRQ模式有若干个自己的寄存器,修改有m个
2.FIQ模式也有若干个自己的寄存器,修改有n个,在ARM里n > m
3. 发生中断时,会进入IRQ模式或FIQ模式,中断的处理过程是这样:
a. CPU切换个IRQ或FIQ模式后,使用的是这些模式自己的寄存器
b. 保存被中断的现场,就是保存中断发生瞬间各个寄存器的值
    既然IRQ、FIQ里有m、n个自己的寄存器,那么这m/n个寄存器就不用保存了:从这里看,n > m,所以FIQ的处理更快一点,但是微乎其微。
c. 执行中断处理函数
d. 恢复被中断的寄存器值,返回继续执行


4. 从中断控制器的角度来说,发生IRQ异常时,可能有多种来源,比如可能是GPIO中断,可能是UART中断等等,所以在“中断处理函数”里,要分辨是哪一个种;
    在ARM架构里,只有一个中断能设置为FIQ,所以发生FIQ异常时,自然不需要去分辨是哪一个中断源。
    从这点上看,FIQ比IRQ快。

但是,为了避免软件复杂,普通的LINUX里没有用FIQ;
只有在实时LINUX或是ARM单片机里,FIQ才有意义。


27. 问:我制作了根文件系统,在启动之后停在这里了:
NET: Registered protocol family 1
NET: Registered protocol family 17
VFS: Mounted root (cramfs filesystem) readonly.
Freeing init memory: 116K
Failed to execute /linuxrc.  Attempting defaults...
Kernel panic - not syncing: No init found.  Try passing init= option to kernel.
复制代码
我内核boot option里面的命令行设置为:
noitinrd root=/dev/mtdblock2 rootfstype=cramfs console=ttySAC0,115200 init=/linurc mem=64M
复制代码
做根文件系统时linuxrc的内容如下:
#!/bin/sh
echo "mount /etc as ramfs"
/bin/mount -n -t ramfs ramfs /etc
/bin/cp -a /mnt/etc/* /etc
echo "re-create the /etc/mtab entries"
# re-create the /etc/mtab entries
/bin/mount -f -t cramfs -o remount,ro /dev/mtdblock/3 /
/bin/mount -f -t ramfs ramfs /etc
exec /sbin/init

rcS如下:
#!/bin/sh
/bin/mount -a
复制代码

请问大侠,这个问题怎么解决,我内核版本是2.6.19.2的!
答:
这类问题很常见,先总体介绍一下解决思路。
能出现让人激动的的控制台,那么系统移植已经接近完成;但是不少人在最后一步出现问题。
要点如下:
1. 在正确的位置烧写正确格式的文件系统映象:
2. 内核支持这种文件系统格式
3. 文件系统的内容要完备

上面说得简单,一个个介绍。
1. 在正确的位置烧写正确的文件系统映象:
(a). 正确的位置
嵌入式开发中,常通过bootloader烧写文件系统映象,假设写在flash的地址A处。
内核启动时,显然要从地址A处读取文件系统,内核是怎么知道的呢?通过命令行参数,比如“root=/dev/mtdblock2 ”。/dev/mtdblock2 又是怎么和地址A对应上的呢?内核将flash划分为
几个分区,这是在代码中固定的。/dev/mtdblock2是第3个分区,它的开始地址必须是A。
在内核启动时,可以看到这些分区的开始地址、结束地址,比如内核启动时会有类似下面的信息:

Creating 3 MTD partitions on "NAND 64MiB 3,3V 8-bit":
0x00000000-0x00030000 : "bootloader"
0x00050000-0x00250000 : "kernel"
0x00250000-0x03ffc000 : "root"
复制代码
对于上面的内核信息,/dev/mtdblock2对应root分区,开始地址为0x00250000,使用bootloader写文件系统映象时,烧写的地址必须是0x00250000

所以,要保证3点:① bootloader烧到地址A,② 地址A是内核某个分区的开始地址,③ 命令行参数“root=/dev/mtdblockXXX ”是这个分区
(b). 正确格式的文件系统映象
不同的bootloader支持的烧写的文件系统映象格式不同、使用的烧写命令也可能不同,请注意这点。
另外,马大哈们制作文件系统映象时,使用的工具也不要弄错了。
最后,请保证这个文件系统映象是“真的烧写了”,因为如果flash只是擦除而没有烧写,它也是“正确的、可以挂接的文件系统”──有人碰到这个问题,我和他答非所问地折腾了很久。

2. 内核支持这种文件系统格式
配置内核时选上要支持的文件系统格式

1、2这两个问题如果不能保证,内核启动时会出现类似如下错误:

VFS: Cannot open root device "mtdblock2" or unknown-block(2,0)
Please append a correct "root=" boot option
复制代码
如果1、2能保证,就可以挂接上文件系统,出现类似下面的字样时,革命已经成功了80%:
VFS: Mounted root (cramfs filesystem) readonly.
Freeing init memory: 116K
复制代码
3. 文件系统的内容要完备
挂接文件系统后,内核就会读取、执行文件系统中的某个文件,通过它来启动应用程序。这个文件要么通过命令行参数“init=xxxx”来指定,要么取默认的文件(下面说明)。
一般制作文件系统映象时,都是在一个目录(假设目录名为rootfs)下放好各种东西:bin/,sbin/,lib/等目录,etc/fstab等文件,然后将这个目录制作为文件系统映象。
可以想象,如果这个目录中的东西不对、不全,即使制作出了文件系统映象,也只是能识别出来,挂接上去;但是启动不了──所谓启动,不就是执行文件系统中的程序嘛?
这时会有类似以下的错误:
Failed to execute /linuxrc.  Attempting defaults...
Kernel panic - not syncing: No init found.  Try passing init= option to kernel.
复制代码
它说得很明显,"Failed to execute /linuxrc"──执行/linuxrc失败:
它为什么要执行/linuxrc,还不是因为你在命令行中加入了“init=/linuxrc”这个参数。
它为什么会失败?原因有二:
一、你制作文件系统映象时,rootfs目录下有linuxrc这个文件吗?
二、rootfs目录的linuxrc文件是正确的吗?
请好好确定这两点,大多数是没有linuxrc文件──linuxrc是busybox自动生成的,只要配置好就可以。
如果有linuxrc,那么就是它无法执行了(解决方法在下面)。

不用linuxrc行不行?当然行!看看内核文件init/main.c,有如下字样:
run_init_process("/sbin/init");
    run_init_process("/etc/init");
    run_init_process("/bin/init");
    run_init_process("/bin/sh");
    panic("No init found.  Try passing init= option to kernel.");
复制代码
就 是说,它会依次尝试执行/sbin/init、/etc/init、/bin/init、/bin/sh这些文件,都失败后才打印出错信 息"No init found.  Try passing init= option to kernel."。

所以,出现这个出错信息时,就表明了没有或是无法执行这些文件:命令行参数“init=xxxx”来指定的xxx文件、/sbin/init、/etc/init、/bin/init、/bin/sh。
一、请检查你的rootfs目录,看看这点些文件是否存在
二、使用file命令看看它们是什么文件类型,是否可执行。
使用busybox时,这些文件是到/bin/busybox文件的链接,那就看看busybox的文件类型,可以使用下面的命令:
$ file linuxrc
linuxrc: symbolic link to `bin/busybox'
$ file bin/busybox
bin/busybox: ELF 32-bit LSB executable, ARM, version 1, for GNU/Linux 2.4.3, dynamically linked (uses shared libs), stripped
复制代码
注意了:如果bin/busybox 是一个动态链接的文件,还要把它用到的库复制到rootfs中。唉,越说越复杂了。这些库在交叉编译工具的相应目录下,如果不知道,查google,否则再发帖。

最后一点,文件系统中各种配置文件、dev目录也要正确。出现问题时再在这个帖子中说吧。这样写下去真是没完没了。
回到这个帖子,它的内核打印信息为:
VFS: Mounted root (cramfs filesystem) readonly.
Freeing init memory: 116K
Failed to execute /linuxrc.  Attempting defaults...
Kernel panic - not syncing: No init found.  Try passing init= option to kernel.
复制代码





说明文件系统挂接成功(VFS: Mounted root (cramfs filesystem) readonly.);
还说明/linuxrc不存在或者不可执行(Failed to execute /linuxrc.  Attempting defaults...);
但是楼主的意思是linuxrc已经有了,内容为:
#!/bin/sh
echo "mount /etc as ramfs"
/bin/mount -n -t ramfs ramfs /etc
/bin/cp -a /mnt/etc/* /etc
echo "re-create the /etc/mtab entries"
# re-create the /etc/mtab entries
/bin/mount -f -t cramfs -o remount,ro /dev/mtdblock/3 /
/bin/mount -f -t ramfs ramfs /etc
exec /sbin/init
复制代码
它是一个脚本,它的执行依赖于/bin/sh,问题转为:/bin/sh是否存在?是否可以执行?
用file命令看看它的类型、是否需要动态库。

解决时请把经验留下。

28.问:NFS启动网络文件系统,板子可以PING通服务器,服务器的NFS的配置和共享目录也对,可以在PC上mount,但启动时还是停在Kernel panic - not syncing: No init found.  Try passing init= option to kernel.
答:把NFS目录下的文件系统的/etc/init.d/rcS 脚本里的ifconfig ethx xxx 去。


29.问:Mini2440启动后一直重启显示uboot界面
原因 : 电源供电不足 ,换标配电源

30. 问:用TFTP 从下载时,总出现
ARP Retry count exceeded; starting again
dm9000 i/o: 0x88001000, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 00:40:5c:26:0a:5b
operating at 100M full duplex mode
复制代码
答:uboot 的 /net/tftp.c的:原来是5000ul改为50000ul

31. 问: 使用GFLASH出现:未识别NOR FLASH
答:在
里执行
r
h
: 就是让板复位,然后马上停下来;这样就不会执行板上的程序,MMU就不会启动

32.问:yaffs2,但我的文件系统太大了
就是不通过内存直接下载到Flash中,可以不?
答:有一个方法,
1. 把文件系统压缩为tar.bz2
2. 用NFS命令启动,
3. flasherase那个分区,然后挂载
4. 解压tar.bz2到分区
如:
1.用nfs fs_bbbb启动
2.擦除FLASH分区
3.挂载FLASH分区
4.解压fs_aaa.tar.bz2到FLASH分区

33.问:  ?Black◎blocks(532501555)  16:50:47
Warning: dm9000 MAC addresses don't match:
Address in SROM is         ff:ff:ff:ff:ff:ff
Address in environment is  00:0c:29:4d:e4:f
复制代码
答: 修改代码,把这个警告去掉就可以了
对于真正的产品,MAC地址是写在一个ROM上的
对于2440省了这个ROM,所以读出来全是FFF
它去EEPROM上读,读出的值是FFFFF

34. 问:内核函数mmap的实现原理,机制?
答:让应用程序能直接访问内核空间的内存,通过MMU进行虚拟地址到物理地址的映射
44.各位大牛,问下NANDFLASH为啥没有时钟信号线?
答:读、写信号的变化沿处理数据

35。问:要实现宿主机Linux系统和目标机进行网络通信的话,必须将虚拟机的网络连接方式配置成Bridged,
这个怎么说呢?
答: 想上网时用NAT,想互通时用BRIDGER,设为桥接时,LINUX也相当于一*立的电脑,WINDOWS拨号上网,那么LINUX也要拨号才能上网,设为桥接时,LINUX也相当于一*立的电脑
WINDOWS拨号上网,那么LINUX也要拨号才能上网,设置NAT的话,LINUX就不用拨号了,设为NAT的话,LINUX的IP就不用去管它了,可以自动分配IP


36.问:如何让文件系统加载后,直接出现#?
答:
/etc/init.d/rcS下console::askfirst:-/bin/sh
复制代码
替换为respawn,其余不变

37.问:nfs可以手动挂载,再insmod 驱动的时候,或者cp一些文件的时候,就经常出现上面的现象:
nfs: server 192.168.2.16 not responding, still trying
nfs: server 192.168.2.16 OK
复制代码
答: mount -t nfs -o nolock,vers=2 serveri_ip:/......  /mnt

38. 请问下屏幕上的图像和字显示的不清晰 是什么原因
答:基本上是bpp设置得不对
你的驱动程序设计的bpp是多少?LCD控制器的寄存器设计对了吗

39.问:lcd屏亮一段时间后就黑屏
答:LCD黑屏的问题,可以在网上搜:2440 lcd 黑屏,有一个贴子 http://blog.csdn.net/dongliqiang2006/article/details/4262950  分析得很好

40. 为什么我的dnw用不不了
答:dnw不兼容win7,使用其他平台使用dnw吧
其他平台使用linux下的dnw前提:
1. 开发板运行于UBOOT,不要让开发板启动到LINUX
2. 这个UBOOT支持USB下载
3. 让VMWARE位于前台,接上USB线
4. 如果VMWARE没识别出新的USB设备,点菜单:vm->removable device

41. jz使用虚拟机上的uImage,板子PING不通PC
答:虚拟机上的uImage有点问题,当时做虚拟机时候没注意,请使用
cd1光盘上的uImage

42. 问:请教个问题,写了个GUI图形按钮 按了几百次以后,出现
Segmentation fault ,是否是内存泄露了?
答:段错误:发生的直接原因就是访问了非法地址,造成这个非法地址访问的原因,有可能是内存越界
内存泄露不会导致段错误

43.问:s3c2440第一期视频里的led闪烁那个leds的工程有人试过吗?
void  wait(volatile unsigned long dly) 这样不行void  wait( unsigned long dly)这样就可以
程序是烧到NOR
答. 看看反汇编是个好方法,烧到NOR的话,SP的设置不一样,ldr sp, =0x40000000+4096
这个函数被优化掉了,没有用栈

44. vivi.ko  依赖其他模块  需要加载 除了 使用 modeprobe xx 还有其他的办法吗?我自己写个V4L2驱动 现在加载这个好多V4L2里面函数没定义呢,是不是编译近内核就可以啊
答:可以先这样做,编译时如果发现某函数未定义,再去把这函数所在文件编进内核里

45.韦老师  给个学习 linux的 顺序 不然都感觉 很茫然
答:按视频顺序学习就可以了,这个顺序就我的学习经历。
1.先把开发板当作单片机来用,这可以让你熟悉LINUX环境编程、熟悉ARM板的硬件操作,就是写各种裸板程序
2.接着学习UBOOT,你可以认为UBOOT就是各种裸板程序的集合,对应u-boot,理解启动过程就可以了,如果觉得难,就看毕业班视频:自己写BOOTLOADER。这有助于理解uboot

3.接着移植LINUX,这稍做一下就可以了,不用深究,知道怎么配置、编译就可以
4.文件系统:这是要弄懂的,这让你对LINUX启动后的流程有所了解
5..驱动程序:这才是重点,看第2期视频吧。我都是由浅到深地讲.