搜索
您的当前位置:首页正文

嵌入式ARM平台下的Linux字符设备驱动实例

来源:好走旅游网
嵌入式ARM平台下的Linux字符设备驱动实例

6.1 下面以一个名为S3C2440_leds.c”的简单控制目标板LED亮灭的驱动为例进行分析。(目标板为天嵌TQ2440;Linux2.6.25.8)。主要功能是通过应用程序调用该驱动来按制目标板的四个LED灯的亮灭。

驱动源程序如下:

#include #include #include #include #include #include

#include #include

#define DEVICE_NAME \"leds\" /* 加载模式后,执行”cat /proc/devices”命令看到 的设备名称 */

#define LED_MAJOR 231 /* 主设备号 */ /* 应用程序执行 ioctl(fd, cmd, arg)时的第 2 个参数 */ #define IOCTL_LED_ON 0 #define IOCTL_LED_OFF 1

/* 用来指定 LED 所用的 GPIO 引脚 */ static unsigned long led_table [] = { S3C2410_GPB5, S3C2410_GPB6, S3C2410_GPB7, S3C2410_GPB8,

};

/* 用来指定 GPIO 引脚的功能:输出 */ static unsigned int led_cfg_table [] = { S3C2410_GPB5_OUTP, S3C2410_GPB6_OUTP, S3C2410_GPB7_OUTP, S3C2410_GPB8_OUTP, };

/*应用程序对设备文件/dev/leds 执行 open()时, *就会调用s3c24xx_leds_open */

static int s3c24xx_leds_open(struct inode *inode, struct file *file)

{

int i;

for(i=0; i<4; i++)

{

s3c2410_gpio_cfpin(led_table[i], led_cfg_table[i]) } return 0;

}

/*应用程序对设备文件/dev/leds 执行 iotcl()时, *就会调用s3c24xx_leds_iotcl */

static int s3c24xx_leds_iotcl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) {

if (arg > 4)

{

return -EINVAL; }

switch(cmd) {

case IOCTL_LED_ON:

s3c2410_gpio_setpin(led_table[arg], 0); return 0;

case IOCTL_LED_OFF:

s3c2410_gpio_setpin(led_table[arg], 1); return 0; default:

return -EINVAL; }

}

/*这个结构是字符设备驱动程序的核心

*当应用程序操作设备文件时调用的 open、read等函数, *最终会调用这个结构中指定的对应函数 static sturct file_operations s3c24xx_leds_fops = { .owner = THIS_MODULE, .open = s3c24xx_leds_open, .ioctl = s3c24xx_leds_ioctl };

/*模块的初始化函数*/

static int __init s3c24xx_leds_init(void) {

int ret;

ret = register_chrdev(LED_MAJOR, DEVICE_NAME, &s3c24xx_leds_fops);

if(ret < 0) {

printk(DEVICE_NAME \"can't register major number\\n\"); return ret; }

printk(DEVICE_NAME \"initialized\\n\"); return 0; }

/*模块的撤销函数*/

static void __exit s3c24xx_leds_exit(void) {

unregister_chrdev(LED_MAJOR, DEVICE_NAME); }

/*指定驱动程序的初始化函数和卸载函数*/ module_init(s3c24xx_leds_init); module_exit(s3c24xx_leds_exit);

/*加入描述信息*/

MODULE_AUTHOR(\"ckz\");

MODULE_DESCRIPTION(\"S3C2440 LED Driver\"); MODULE_LICENSE(\"GPL\");

写好的驱动放在内核源文件目录下:linux2.6.25.8]#drivers/char/

6.2 以模块形式编译及加载

修改同目录下的“Kconfig”文件,在合适的地方添加如下内容: Config S3C2440_LEDS

tristate “S3C2440 LEDS Driver” depends on ARCH_S3C2440 help

LEDS on S3C2440

然后再通目录下修改“Makefile”,添加如下内容:

Obj-$(CONFIG_ S3C2440_LEDS) += S3C2440_leds o

添加完成以上内容之后,输入#make menuconfig,然后配置如下 Device Drivers -󰀀

Character devices ->

S3C2440 LEDS Driver 将其选择为“M”,然后保存配置,编译出内核镜像烧写到开发板中。

然后再使用命令#make SUBDIR=drivers/char modules,编译出驱动模块,在内核目录下的“drivers/char”下面,名为 S3C2440_leds.Ko,将其复制到开发板中的/lib目录中。

加载、卸载驱动到目标系统中。

在/lib目录下:

***] insmod S3C2440_leds.KO /***加载驱动***/ ***] rmmod S3C2440_leds.KO /***卸载驱动***/

6.3 下面编写简单的应用程序来测试刚才的驱动程序,新建名为leds.c的文件

#include #include #include #include

int main(int argc, char **argv) { }

因为这只是一个简单的应用程序所以没有必要编写Makefile文件,直接使用arm-linux-gcc 命令编译并将其传到目标板上运行即可!

在终端中输入:./leds 2 0

则目标板上的第二个LED灯亮被点亮。

int on; int led_no;

int fd;

if (argc != 3 || sscanf(argv[1], \"%d\ on < 0 || on > 1 || led_no < 1 || led_no > 4) {

fprintf(stderr, \"Usage: leds led_no 0|1\\n\"); exit(1);

}

fd = open(\"/dev/GPIO-Control\if (fd < 0) { perror(\"open device leds\"); }

exit(1);

ioctl(fd, on, (led_no-1)); close(fd); return 0;

因篇幅问题不能全部显示,请点此查看更多更全内容

Top