首先,加载启动生成的内核时,没有任何显示!就是说,在u-boot打印出信息:Starting kernel ...后,屏幕上再无任何输出。
这里需要简单介绍一下Beaglebone Black单板的输出。它有一个micro HDMI,这个经过转换后,连接到所用的SOC AM3358上的图形显示卡(可直接驱动LCD)上。很显然,这个输出不适合开发过程中使用,因为它依赖比较复杂的驱动程序。单板机通常有JTAG接口,可以用来显示输出,也可以用来调试单板机的运行。这个比较偏向硬件,可能是硬件工程师喜欢的方式。对于我来讲,使用串口进行输入输出是比较合适的方式。串口的电路和驱动都比较简单,适合做最初的开发使用。AM3358有6个串口(UART0 ~ UART5),Beaglebone black将UART 0的管脚直接接了出来,总共六根。因为SOC工作在TTL电压(3.3V),接口没有在电气物理层面上做转换使之符合RS232的要求,所以不能直接连接任何设备的串口,比如PC机的串口。好在市场上存在这种USB转串口的, 接口为TTL 3.3V的连接线,通过它,可以将这个串口直接连接至PC机的USB端口。
在LINUX PC上,用minicom终端软件,通过USB转RS232的设备,可以对Beaglebone black的启动过程进行监测,并可以做交互。
内核启动后,没有观测到任何输出,这是一个比较棘手的问题,因为没有任何信息可供参考判断。内核启动的第一步,首先是将内核解压到一个固定的物理地址开始的区域,在TI的SOC上,一般这个地址是0x8000 8000,因为TI的ARM架构的SOC, 内存开始地址通常为0x8000 0000。在过去版本的正常启动里,解压开始和结束,会输出“Uncompressing Linux... done, booting the kernel.”。如何知道究竟运行到了哪里?为什么出错?
好在单板机上,一般都有几个led显示管,通过写入一个内存区域的二进制位,来点亮它。那么可以找到驱动某个led的物理地址,在内核设置并启用虚拟内存机制之前,直接在对应的地址位写1来点亮某个led。启用虚拟地址机制后,就无法如此 *** 作,因为不知道这个物理地址对应的虚拟地址是什么,甚至都不知道这个地址的对应关系是否已经建立。不过,至少在虚拟地址机制开启前,可以通过这个方式来查找内核启动过程是否走过了某一段。很不幸的是,使用这种方式,验证了内核已经正确执行到了开始启用虚拟内存的地方。如果虚拟内存机制设置完毕,就会跳转到内核"start_kernel"这个函数,它是一个C程序。由此开始,内核就基本上是在执行C语言的代码了!
为什么解压缩完成却没有输出“Uncompressing Linux... done, booting the kernel.”?原来是使用了设备描述树来创建设备的内核,在开始阶段(读取并分析设备描述树之前),并没有创建任何串口设备。如果是在开始就创建并使用这些设备,那么就是又回到用静态变量来存储设备和驱动的老做法了!所以使用Device Tree Blob来指定设备的内核,在启动开始的解压缩阶段,再也无法输出类似的信息了!
既然是通过设备描述树来指定设备,那么也许要查看一下设备描述树的源文件,看看那里对uart0是如何描述的。通过查看"am335x-boneblack.dts"文件和它所包含的文件,发现uart0启用时,需要用"pinctl-single"这个管脚复用的驱动来设置管脚。在内核配置文件里,有选择这个驱动的选项,但是因为我追求最小内核,所以没有选用它!重新配置内核选项,选中这个驱动,内核启动的输出就正常了!
这里顺带解释一下管脚复用。SOC芯片,一般都集成了CPU和其它很多外设,例如串口控制器,USB控制器,等等。芯片输出的管脚,不能完全将所有的外设连接都输出,这样就存在多个外设信号连接到一个管脚的现象。例如串口0的RX信号,和I2C 2的SDA信号,还有其它6种信号,共用一个管脚!如果需要将这个管脚设置为做串口0的RX信号,就需要在一个内存地址(寄存器)里写入0, 如果需要它做为I2C 2的SDA,需要写入3。管理这种复用的驱动程序,最简单的那种(每个管脚配置占用四个字节),叫pinctl-single。之前内核不能输出信息,就是因为没有配置选中这个驱动。
内核启动完成,最后加载一个内存根文件系统,并尝试执行根目录下的init程序。这个初始根文件系统的内容是最简单和常用的命令。用klibc和busybox的生成结果,充当这个文件系统的内容,是最常用的做法。内存文件系统(非内存块设备)和内核初始根文件系统,是LINUX里的发明,降低了内核复杂度的同时,增加了灵活性!
内核启动完成,执行klibc的SHELL(sh.shared)后,却发现内核没有识别到MMC卡(或是4GB 的eMMC)!根据内核启动过程的输出提示,发现是加载对应MMC的电源驱动失败。还是查找设备描述树源文件,发现Beaglebone black的mmc使用一个最简单的电源驱动:regulator-fixed。而内核配置里,漏掉了这个驱动。又是最求最小内核配置惹的祸!重新配置并选中这个驱动,现在看起来一切正常。
到此为止,一个小的系统就诞生了。它运行在Beaglebone black的板子上,MMC卡,USB和网卡都可以使用用。当然这还是一个比较小的配置,以后根据需要,可能还需要追加必要的驱动。下一步就是开始编译生成系统的各种程序了。首当其冲的就应该是"systemd",它是最新的,也是最流行的,替代过去UNIX/Linux INIT的程序。
int reuse = 1setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&reuse)//设置套接字属性为重用bind地址,
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)