您的位置:首页 > 其它

为BBB制作专属自己的cape(二)

2013-12-15 00:40 239 查看
最新更新请见http://blog.csdn.net/wyt2013/article/details/18228095

本文是个人吐槽加进度记录贴,大家择己所需吧。里面的重要内容我会日后重新整理成日志。脑袋里问题堆栈压入太多层了。。。为了解决A,必须先搞定B;为了搞定B,必须先做到C……为了实现Y,必须先学会Z……Orz

我的目标是用手头的一个LCD模块为beaglebone black制作LCD cape,在我写上一篇日志的时候,我以为这没什么难的,套用现成的LCD4 cape的device tree就可以了,可是问题远远多过想象:

eeprom无法用i2cset写入信息

最后解决办法是利用sysfs接口添加eeprom为i2c设备,然后向设备中echo数据。(方法学习自 http://papermint-designs.com/community/node/331)

直接echo 16进制数据的方法是 echo -e "\x31\x41" > file 。file中就会保存下“1A”这两个字符。

目前系统存在Bug,无法在启动时加载自己的dtbo

症状是,只要eeprom里写的dtbo不是系统自带的,它就找不到这个dtbo。在找了60秒以后(找这么久干嘛?!我曾一度以为系统在那死掉了,没等到60秒就强制重启了好多次),继续加载系统,最后dmesg中会记录下加载失败的信息。

解决办法倒是有,但是要重新编译内核,我作为菜鸟还是先别碰内核了,万一搞坏了呢。解决方法的链接,给需要的人看http://hipstercircuits.com/enable-device-tree-overlay-on-startup-on-beaglebone-black/

eeprom的作用是在启动时判断要加载哪个cape,现在系统有这个bug,就不能用启动时加载的方法了,只能在启动之后手动加载cape,所以eeprom也用不上了。但是因为HDMI cape占用了LCD引脚,根据我前面说的,引脚被占用了以后就没法加载别的cape了,所以只要想办法先把HDMI cape卸载掉就能加载我的LCD cape了。

系统存在Bug,运行时卸载cape会导致kernel panic

卸载cape,这本来应该是一件很easy的事(见我之前关于device tree的日志),现在因为这个bug,只能换一种方法解决。经过一阵搜索,找到了办法,还好不是很麻烦。修改uEnv.txt就可以:

在插上beaglebone后,电脑上会出现一个可移动磁盘,打开它,里面有一个uEnv.txt文件,在下面加如下行文字(最后好像必须有空格或回车,否则第二个BB-BONELT-HDMIN还是会被加载,有待确定),就可以禁止HDMI cape启动了。

optargs=quiet capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN 

系统启动以后,用 cat $SLOTS 查看,会发现BB-BONELT-HDMI,BB-BONELT-HDMIN这两项还在。但是注意看,这两项前面没有了L字母,而eMMC是有L字母的,这就代表那两个没有被加载。

(方法学习自http://elinux.org/Beagleboard:Weather_Cape_Work-Around)

LCD与处理器的接口搞错

终于,可以在启动以后手动加载dtbo了。我试着直接加载LCD4 cape的dtbo文件,但是LCD却一直白屏,只能调调背光亮度啥的。背光能调说明dtbo已经起作用了(pwm引脚功能已经生效),但总是白屏说明可能是参数没设置好。于是查找大量LCD资料,并且反复读了好多遍我用的LCD模块的datasheet,调了很多次帧同步等参数,还是不行。最后发现,根本接口就不对。。我用的LCD模块只支持8080接口,而官方的LCD cape用的是RGB接口。。。(关于LCD我日后再写日志详述,驱动器和控制器这两个概念就让我迷惑了好久……)

tilcdc驱动似乎不支持8080接口

然后我悲伤地发现,tilcdc驱动似乎不支持8080接口。至少从device tree的描述上没看到跟8080接口有关的东西……不过想想也是,不同的LCD控制器应该有不同的寄存器设置时序,不可能写出统一的驱动的。

虽然STM32板子给了详细的用GPIO口驱动这个LCD模块的程序,但是,不能把这么强大的芯片当单片机使吧?芯片明明提供了LIDD模式来控制8080接口的LCD的,而且据网上说,直接用GPIO控制LCD的速度比单片机还要慢。。。所以,坚决不走死路!还是从驱动上想想办法吧,最好有现成的。毕竟我还不会自己写驱动。

经过一番在kernel的搜索,惊喜地发现居然有ili9320的现成驱动!这下又给了我希望!

ili9320驱动没有编译进内核

好吧……在beaglebone上任何地方都找不到lil9320驱动的影子。看来还得自己把驱动编译出来手动加载。我还不知道这个驱动该怎么用呢,但没别的路可走了,试试看吧。

beaglebone上本地编译驱动失败

首先想到的是本地编译,因为听说交叉编译内核环境的搭建很麻烦。但是beaglebone上缺乏相关的内核头文件,而且我的beaglebone还不会联网,没法升级和下载头文件。配置网络连接可能比较麻烦,要不干脆搭建一下交叉编译环境吧!反正以后也要用。(我现在觉得配置网络可能会远比我后面干的事简单。。)

Mac上搭建交叉编译环境失败

这个很好理解吧。。mac本来就是跟linux分道扬镳的,很多命令都没有,用homebrew也解决不了。算了,虚拟机ubuntu吧。
关于homebrew:http://brew.sh/index_zh-cn.html

建立交叉编译环境的曲折

我用了两天时间,不知道自己在干嘛,但就是沿着唯一能走的路在一直走,走着走着,才知道自己是在编译Angstrom开发工具链。

Angstrom使用OpenEmbedded(OE)来做自己的工具链。本来Angstrom官网上应该有详细的教程的,但是……

Angstrom官网崩溃了

我也崩溃了……官网上只剩下只言片语的提示,我的问题都是在Google groups里找到解决方法的,费了很多周折(感谢万能的Google)。
大家来感受下崩溃后的官网 http://www.angstrom-distribution.org

工具链编译超级慢

编译方法很简单,clone一个:

git clone git://github.com/Angstrom-distribution/setup-scripts.git

然后执行简单的3条命令就行了(beaglebone black也用MACHINE=beaglebone就可以):

MACHINE=beaglebone ./oebb.sh config beaglebone

MACHINE=beaglebone ./oebb.sh update

MACHINE=beaglebone ./oebb.sh bitbake virtual/kernel

我有必要在这里提前说一下,实际上在执行这3条命令前,一定要把 setup-scripts/conf/local.conf 这个文件里 INHERIT
+= "rm_work" 这行删掉或注释掉。否则编译结束后会把内核源文件删掉(这里面有内核头文件什么的)。但我一开始没注意,结果最后没有内核源文件,而且删掉那行重新编译也不行……我再想想办法。

这3条命令,特别是第3个命令,看似简单,实则……

加起来花了我3个G校园网流量和断断续续加起来约15个小时的电脑疯狂运行的代价!!注意,如果跟我一样用虚拟机的话,内存分配至少要2.5G以上,否则在parse的时候会提示no memery to allocate 内存不足。另外,中间有一个大文件(1.2G左右)需要下载,但是屏幕上没有任何下载速度或进度或文件大小的提示!!事实上屏幕上只有一句 do_fetch,然后一动不动。你需要耐心等待……最好有个显示网速的插件,好知道究竟有没有在下载。。。

针对内存不足的问题,似乎有办法只进行核心文件的编译,我没有试过,可以参考http://derekmolloy.ie/building-angstrom-for-beaglebone-from-source/和http://elene.dahners.com/blog/2012/10/22/compiling-a-kernel-module-for-beaglebone/ 。这两个网址都详细记录了编译Angstrom工具链的过程,建议新手仔细看一遍这两个网址和我的这篇文章然后再自己编译工具链。

下载本身就挺慢的了(130K/s左右),编译更慢。而且中间还有一个文件下载不下来,必须手动更改一下地址。具体哪个文件我记不清了,等遇到错误时就有显示了。把那个文件里https://launchpad.net/gcc-linaro/4.7/4.7-${RELEASE}/+download/gcc-${PV}-${RELEASE}.tar.bz2这句改成https://launchpadlibrarian.net/131881971/gcc-linaro-4.7-2013.02-01.tar.bz2 即可。

最后好不容易编译完了,因为一开始我忘记注释掉 INHERIT += "rm_work" 这句话,导致没有内核源文件……所以还是编译不了驱动。。

小白科普:驱动是属于内核空间的东西,内核空间用的头文件和库跟用户空间的完全不同,所以必须有内核源文件才能编译内核模块或驱动模块。而且因为内核跟硬件关系更紧密,所以交叉编译环境或者工具链(toolchain)更难建立一些,没有通用的解决方案。可以参考所使用操作系统的网站。

所以到现在还是零进展。。。

======================================================================

第二天更新!

工具链搭建完成!实现了交叉编译内核模块

又在虚拟机里执行了一下

MACHINE=beaglebone ./oebb.sh virtual/kernel -c compile -f

之后在 /home/user/setup-scripts/build/tmp-angstrom_v2012_12-eglibc/work/beaglebone-angstrom-linux-gnueabi/linux-mainline-3.8.13-r23a/git/ 目录下终于出现了内核源文件(这个目录原本是空的)。然后用了一个最简单的驱动模块编译测试成功!工具链基本搭建完成!

我的测试源文件(来源:网络)
#include <linux/module.h>
#include <linux/kernel.h>

static int __init enable_usermode(void)
{
printk(KERN_INFO "Usermode enabled.\n");
return 0;
}

static void __exit disable_usermode(void)
{
printk(KERN_INFO "Usermode disabled.\n");
}

module_init(enable_usermode);
module_exit(disable_usermode);
Makefile文件:
obj-m += enable_usermode.o

CROSS = /home/user/setup-scripts/build/tmp-angstrom_v2012_12-eglibc/sysroots/x86_64-linux/usr/bin/armv7a-vfp-neon-angstrom-linux-gnueabi/arm-angstrom-linux-gnueabi-
KDIR =  /home/user/setup-scripts/build/tmp-angstrom_v2012_12-eglibc/work/beaglebone-angstrom-linux-gnueabi/linux-mainline-3.8.13-r23a/git/

PWD := $(shell pwd)

all:
make -C $(KDIR) M=$(PWD) CROSS_COMPILE=$(CROSS) ARCH=arm modules
clean:
make -C $(KDIR) M=$(PWD) CROSS_COMPILE=$(CROSS) ARCH=arm clean
编译后生成了enable_usermode.ko文件,把它用sftp传到beaglebone上以后执行insmod,没有提示错误。接着使用dmesg命令可以查看到输出了“Usermode enabled.” 说明成功加载了驱动。

注意一点,Makefile不要直接从网上拷贝过去用。因为Makefile的命令必须以tab键为开头,我一开始就直接拷贝过去,结果tab全变成空格了。。让我困惑了很久。每次make都输出nothing to be done for "all".

menuconfig内核文件

摘自网络(http://www.cemetech.net/forum/viewtopic.php?t=7814&sid=6d6b8a6073427b7d947580f3b55ecf71)。
先执行 

MACHINE=beaglebone ./oebb.sh bitbake virtual/kernel -c -menuconfig

到最后会出现熟悉的菜单,配置好以后保存退出,然后再执行

MACHINE=beaglebone ./oebb.sh virtual/kernel -c compile -f 

就能编译出刚刚定制的内核文件了。然后再执行

MACHINE=beaglebone ./oebb.sh virtual/kernel -c compile_kernelmodules -f

就能编译出所有内核模块。后面还可以继续执行
MACHINE=beaglebone ./oebb.sh virtual/kernel -c package_write -f
MACHINE=beaglebone ./oebb.sh virtual/kernel -c deploy -f

等命令。

第二次编译内核要注意

如果直接执行上面的menuconfig,然后compile的话,它会说已经编译完成,无需重新编译。要想重新编译,需要先执行一步

MACHINE=beaglebone ./oebb.sh virtual/kernel -c cleansstate

注意这步执行完以后会把原来的内核源文件和menuconfig都删掉!(就是/home/user/setup-scripts/build/tmp-angstrom_v2012_12-eglibc/work/beaglebone-angstrom-linux-gnueabi/linux-mainline-3.8.13-r23a/ 这个目录里的内容全部删掉,只剩一个空的git目录)如果有需要保存的数据记得提前保存好。然后再执行上面说的menuconfig和compile就可以重新编译了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息