本篇文章为大家展示了基于OMAPL138的Linux设备驱动程序开发怎么入门,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
开发板LED编号和GPIO对应关系如下:
表 1
开发板型号 | GPIO0[0] | GPIO0[5] | GPIO0[1] | GPIO0[2] |
TL138/1808-EVM | D7 | D6 | D9 | D10 |
TL138/1808-EasyEVM | D7 | D6 | D9 | D10 |
TL138/1808-EthEVM | D7 | D6 | D9 | D10 |
TL138/1808F-EasyEVM | \ | GD1 | GD2 | GD3 |
TL138/1808F-EVM | \ | D1 | D2 | D3 |
开发板资料光盘中有LED设备驱动程序源码,其路径为:
led.c:demo\driver\linux-3.3\led\led.c
下面以TL138/1808-EVM开发板为例讲解此设备驱动程序。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
/* 因为使用了平台相关的头文件,所以编译时需要ARCH=arm */
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/da8xx.h>
#include <mach/mux.h>
/*定义4个用户LED对应的GPIO,开发板LED对应编号分别是D7,D6,D9,D10 */
#define DA850_USER_LED0 GPIO_TO_PIN(0, 0)
#define DA850_USER_LED1 GPIO_TO_PIN(0, 5)
#define DA850_USER_LED2 GPIO_TO_PIN(0, 1)
#define DA850_USER_LED3 GPIO_TO_PIN(0, 2)
/* assign the tl som board LED-GPIOs*/
static const short da850_evm_tl_user_led_pins[] = {
/* These pins are definition at <mach/mux.h> file */
DA850_GPIO0_0, DA850_GPIO0_1, DA850_GPIO0_2, DA850_GPIO0_5,
-1
};
/*定义4个LED对应的GPIO号、有效电平(熄灯电平)、名称、触发模式等*/
/*使用Linux提供的标准gpio-led框架*/
static struct gpio_led da850_evm_tl_leds[] = {
{
.active_low = 0, /*有效电平(熄灯电平):低电平*/
.gpio = DA850_USER_LED0, /*GPIO号:LED对应gpio管脚*/
.name = "user_led0", /*名称:对应/sys/class/leds/下的名称*/
.default_trigger = "default-on", /*触发模式:默认点亮*/
},
{
.active_low = 0,
.gpio = DA850_USER_LED1,
.name = "user_led1",
.default_trigger = "default-on",
},
{
.active_low = 0,
.gpio = DA850_USER_LED2,
.name = "user_led2",
.default_trigger = "default-on",
},
{
.active_low = 0,
.gpio = DA850_USER_LED3,
.name = "user_led3",
.default_trigger = "default-on",
},
};
static struct gpio_led_platform_data da850_evm_tl_leds_pdata = {
.leds = da850_evm_tl_leds,
.num_leds = ARRAY_SIZE(da850_evm_tl_leds),
};
static void led_dev_release(struct device *dev)
{
};
/*使用Linux提供的标准platform_device 框架*/
static struct platform_device da850_evm_tl_leds_device = {
.name = "leds-gpio",
.id = 1, /*先确定id号是否被使用,此id是platform_device的id,跟LED个数无关*/
.dev = {
.platform_data = &da850_evm_tl_leds_pdata,
.release = led_dev_release,
}
};
static int __init led_platform_init(void)
{
int ret;
#if 0
/*使用davinci pinmux设置接口,把LED对应的管脚配置成gpio模式*/
ret = davinci_cfg_reg_list(da850_evm_tl_user_led_pins);
if (ret)
pr_warning("da850_evm_tl_leds_init : User LED mux failed :"
"%d\n", ret);
#endif
/*注册LED device设备,系统LED框架将会接收到这个注册,生成相应LED节点*/
ret = platform_device_register(&da850_evm_tl_leds_device);
if (ret)
pr_warning("Could not register som GPIO expander LEDS");
else
printk(KERN_INFO "LED register sucessful!\n");
return ret;
}
static void __exit led_platform_exit(void)
{
platform_device_unregister(&da850_evm_tl_leds_device);
printk(KERN_INFO "LED unregister!\n");
}
module_init(led_platform_init);
module_exit(led_platform_exit);
MODULE_DESCRIPTION("Led platform driver");
MODULE_AUTHOR("Tronlong");
MODULE_LICENSE("GPL");
以上是LED设备驱动程序解析,对于Linux对LED设备框架,这里稍微说明一下:
Linux的LED设备类在内核"Documentation/leds/leds-class.txt"文件有详细说明。
注册一个LED设备成功后,会"/sys/class/leds/"生成相应的设备节点。
用户可以通过读写节点目录下的brightness文件控制LED亮灭。
对于GPIO口的操作,有以下几点步骤:
查看开发板的原理图,找到与LED连接的GPIO。TL138/1808-EVM开发板与LED连接的GPIO分别是GPIO0[5]、GPIO0[0]、GPIO0[1]、GPIO0[2]。
查看OMAP-L138的数据手册,查找对应PINMUX寄存器的地址,将对应的管脚的寄存器中相应位设置为GPIO的工作模式。本例中使用的是PINMUX1。
设置GPIO的方向寄存器。本例程中将GPIO口配置为输出。
配置GPIO的数据寄存器,写"1"表示输出高电平,写"0"表示输出低电平。
此处使用Makefile编译LED设备驱动程序。工程中源文件有时候很多,其按类型、功能、模块分别放在若干个目录中,Makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为Makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
开发板资料光盘中有LED设备驱动程序Makefile文件,其路径为:
Makefile: demo\driver\linux-3.3\led\Makefile
以下为LED设备驱动程序Makefile文件的解析:
ifneq ($(KERNELRELEASE),)
obj-m := led.o /*定义了要编译的驱动文件为led.c,生成的模块名字为led.ko*/
else
/*以下定义运行编译命令时使用的内核源码、驱动源码路径、平台、使用的交叉编译工具链等参数*/
all:
make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
/*定义运行"make clean"时清除的文件*/
clean:
rm -rf *.ko *.o *.mod.o *.mod.c *.symvers modul* .button.* .tmp_versions
#help: make KDIR=<you kernel path>
endif
图 1
将光盘"demo\driver\linux-3.3\led"的led.c和Makefile文件复制到开发系统Ubuntu任意路径,并在led.c和Makefile目录运行以下命令编译LED设备驱动程序:
Host# make KDIR=/home/tl/omapl138/linux-3.3
图 3
将光盘"demo\driver\linux-3.3\button"中的button.c和Makefile文件复制到Ubuntu任意路径,在button.c和Makefile文件所在目录运行如下命令编译按键设备驱动程序:
Host# make KDIR=/home/tl/omapl138/linux-3.3 CROSS_COMPILE=arm-none-linux-gnueabi-
图 5
可以看到在当前目录生成了测试程序镜像文件button_test。具体按键测试步骤请看用户手册快速体验相关小节。
假如需要将设备驱动程序模块静态编译进内核,请按照如下步骤操作。
以LED设备驱动程序为例,将光盘"demo\driver\linux-3.3\led"目录下的设备驱动程序源代码led.c放到内核源码"drivers/char"目录下,修改内核源码"drivers/char"目录下Kconfig菜单配置文件,在"menu "Character devices""行下面添加如下内容:
图 6
config USER_LED:USER_LED是驱动程序的配置名称。
tristate "user led":在使用"make menuconfig"配置内核时菜单栏出现的驱动名字。
depends on ARM:注明是ARM平台下的驱动程序。
default y:默认是静态编译到内核镜像的。
---help---:驱动程序的补充信息,让用户进一步了解此驱动程序的作用。
修改内核源码"drivers/char"目录下的Makefile编译文件,在最后添加如下内容:
obj-$(CONFIG_USER_LED) += led.o
图7
obj-$(CONFIG_USER_LED):"USER_LED"此内容必须和前面步骤Kconfig文件中添加的内容一致。
+= led.o:这个前缀必须是"led",编译驱动程序时,系统会去找"driver/char"目录下的led.c文件。
在内核源码顶层目录执行以下命令查看设备内核配置情况:
Host# make menuconfig ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
可在"device drivers->character devices"下有"user led"的驱动配置选项,如下图:
图 8
前面的"*"符号代表将设备驱动模块静态编译进内核。保存退出,并重新编译内核,然后使用编译得到的内核镜像启动开发板,可发现在不用安装led.ko的情况下,可以直接运行led_loop.sh来实现LED的循环点亮。
若需要将设备驱动模块编译成内核模块的形式,按空格键将"*"变为"M",变为空表示不编译。
上述内容就是基于OMAPL138的Linux设备驱动程序开发怎么入门,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。