拿到Beaglebone Black以后,我最先考虑的是如何用它控制硬件,包括ARM片上的硬件资源和外接的各种设备。通过我的前几篇日志也给出了若干硬件的使用方法,但是总感觉缺乏条理。因此查了一些资料,在此做一点总结。
我们知道Linux系统分为用户空间和内核空间,系统调用函数和Linux API(本质上也是在使用系统调用)是内核空间和用户空间之间的接口,设备驱动程序是内核空间和机器硬件之间的接口。我们在用户空间想要访问硬件,必须通过系统调用操作驱动程序来实现。因为Linux中一切皆文件,所以对硬件的操作等同于对设备文件的操作。在Beaglebone中通过使用capemgr加载device tree文件来加载设备,通常设备经过加载以后就会出现在 /dev 目录中,我们可以在c语言程序中使用open()、close()、read()、write()、ioctl()等系统调用函数对其进行操作。这些函数操作的具体实现,就是在相应的驱动程序中定义的了,一般需要查询相应驱动的说明或阅读驱动源码来得知。
通常所说的驱动程序是属于内核空间的程序,编写驱动程序比较复杂、调试不方便而且有一定危险。实际上,在用户空间也可以编写简单的驱动程序,方法是利用 /dev/mem 这个设备,将芯片的寄存器映射到用户空间中,然后我们就可以像操作单片机一样控制芯片的外设了。一个很好的例子是这位仁兄写的C语言操作Beaglebone的GPIO的函数库,就是用这个方法实现的。感兴趣的话可以到这里去看一看他的思路和源代码 www.element14.com/community/community/knode/single-board_computers/next-gen_beaglebone/blog/2013/10/10/bbb--beaglebone-black-io-library-for-c
必须了解的是,在用户空间的驱动程序有很多力不能及的地方,比如:无法使用中断、响应速度慢、很多设备不能在用户空间处理等等。
上面说的是在c程序中操作硬件的方法。但在shell中一般不能直接读写 /dev 目录下的设备文件,也不能进行ioctl()操作。如果我们想在shell中操作硬件怎么办?这就要用到 /sys 目录了。/sys 目录中存放着系统内核和驱动相关的内容,它是一个虚拟的文件系统,这个文件系统的目录结构实质上就是内核对象模型树。我们可以对这里的文件进行读写操作来实现对设备的操作。至于每个设备里都有哪些文件,操作哪些文件能产生什么效果,还是由设备驱动程序定义的了。(前提是设备驱动中设置了相应的sysfs,否则就没法在shell里访问了。)