打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Linux下第一个原创LED驱动全攻略

最近这几天接触了char driver,由于自己之前没有看过LDD3,所以刚开始的时候对这种操作有很多的不理解,程序代码也不知道是什么。但是我看了好久,其实还是很容易理解的。现在我来分析下我完全靠自己理解写的一个最简单的led驱动代码,希望对大家有所帮助。

/*****************************************************************************

* addr  :Changchun University of Science and Technology

*

* time  :2012.10.26

*

*

* author:yuqingzhang

*

*

* ****************************************************************************/ 

#include <linux/config.h>

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/fs.h>

#include <linux/init.h>

#include <linux/devfs_fs_kernel.h>

#include <linux/miscdevice.h>

#include <linux/delay.h>

#include <asm/irq.h>

#include <asm/arch/regs-gpio.h>

#include <asm/hardware.h>

#include <asm/uaccess.h>

#include <linux/mm.h>

#include <linux/ioport.h>

#include <asm/io.h>

#include <linux/ioport.h>

#include <linux/fs.h>

#define DEVICE_NAME "myledconfigs"

#define LED_MAJOR   231

int init_module(void);

void cleanup_module(void);

/*choose GPIO*/

static unsigned long led_table [] = {

S3C2410_GPB5,

S3C2410_GPB6,

S3C2410_GPB8,

S3C2410_GPB10,

    };

/*put GPIO OUT*/

static unsigned int led_cfg_table [] = {                       

S3C2410_GPB5_OUTP, 

S3C2410_GPB6_OUTP,

S3C2410_GPB8_OUTP,

S3C2410_GPB10_OUTP,

};

static int s3c2440_led_ioctl(

struct inode *inode,

struct file *file,

unsigned int cmd,

unsigned long arg)

{

if (arg > 4)

 {

return -EINVAL;

}

else

s3c2410_gpio_setpin(led_table[arg], !cmd);

}

首先是头文件,这些都是linux2.6.12内核下的一些头文件。关于S3C2440的底层文件已经有大神为我们写了,都在、include/asm/archarch/arm/mach-s3c2410/gpio.c两个目录下。

#define DEVICE_NAME "myledconfigs"是我们定义的drive人文件名称,他会随驱动编译过后insmod下在dev下生成myledconfigs文件。这将是我们应用程序所要用到的。

static int s3c2440_led_ioctl(

struct inode *inode,

struct file *file,

unsigned int cmd,

unsigned long arg)

这是函数很很重要的系统函数,我们应用层的程序都要通过它来执行,因为在应用层我们用open打开dev/"myledconfigs目录,open会返回一个int变量,然后我们可以通过这个函数来决定我们应用层所要执行的用到的底层。

static int __init s3c2440_led_init(void)

{

int tmp;

int i;

tmp = register_chrdev(LED_MAJOR,DEVICE_NAME, &s3c2440_leds_fops);

if (tmp < 0) 

{

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

return tmp;

}

devfs_mk_cdev(MKDEV(LED_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,DEVICE_NAME);

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

{

s3c2410_gpio_cfgpin(led_table[i],led_cfg_table[i]);

s3c2410_gpio_setpin(led_table[i],1);

}

printk(DEVICE_NAME "initialized\n");

return 0;

}

/*this is rmmod order*/

static void __exit s3c2440_led_exit(void)

{

devfs_remove(DEVICE_NAME);

unregister_chrdev(LED_MAJOR, DEVICE_NAME);

}

module_init(s3c2440_led_init);

module_exit(s3c2440_led_exit);

MODULE_LICENSE("GPL");

这两个函数initexit是用来动态加载的。一般驱动有两种模式被应用。一种是静态加载,一种是动态加载。静态加载时通过makefile时候通过obj ,动态加载时obj -m

应用程序如下:#include "stdio.h"

#include "unistd.h"

#include "sys/types.h"

#include "sys/ioctl.h"

#include "stdlib.h"

#include "termios.h"

#include "sys/stat.h"

#include "fcntl.h"

#include "sys/time.h"

int main(void)

{

int on=1;

int off=0;

int led;

int fd;

pid_t pid;

pid=fork();

if (pid<0)

{

printf("fork is wrong\n");

exit(1);

}

fd=open("/dev/myledconfigs",0);

if(fd<0)

{

perror("open device myledconfigs");

exit(1);

}

printf("leds test show,press ctrl+c to exit \n");

if (pid==0)

{

while(1)

{ printf("This is the Child-progress\n");

ioctl(fd,on,0);

ioctl(fd,on,1);

sleep(1);

on=!on;

}

}

else

{

while(1)

{

printf("This is the parent\n");

ioctl(fd,off,2);

ioctl(fd,off,3);

sleep(1);

off=!off;

}

}

close(fd);

return 0;

}

这里是两个进程来实现换灯闪的。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
linux GPIO驱动
嵌入式开发入门到放弃的关键时刻
LED驱动(原创)
单片机和嵌入式系统linux的区别
嵌入式Linux GPIO 操作
linux下利用C语言获取mac地址 - Linux平台C语言开发专版 - LUPA开源社...
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服