嵌入式linux led驱动有几种写法,嵌入式Linux字符设备LED驱动-基于树莓派

个人原创,转载请注明原文出处

http://blog.csdn.net/u011897065/article/details/41307339

参考文章:

http://blog.csdn.net/embbnux/article/details/17712547

首先先说下大致步骤:

1)、电路连接

2)、内核字符设备驱动编写

3)、Makefile和Kconfig添加

4)、编译内核

5)、复制内核到SD卡

6)、树莓派上编写相应的C程序调用系统API驱动LED

一、电路连接

首先先看树莓派B+GPIO口接口图:

嵌入式linux led驱动有几种写法,嵌入式Linux字符设备LED驱动-基于树莓派_第1张图片

首先看GPIO_LED连接电路:我的Led分别连接到GPIO4,GPIO8,GPIO9,GPIO10,GPIO11,GPIO23,GPIO24,GPIO18

嵌入式linux led驱动有几种写法,嵌入式Linux字符设备LED驱动-基于树莓派_第2张图片

实物图:

嵌入式linux led驱动有几种写法,嵌入式Linux字符设备LED驱动-基于树莓派_第3张图片

二、Rpi字符设备驱动编写

在树莓派Linux   /drivers/char路径下新建Led.c,编写程序。

/*

-------------------------------------------------------------------

*File name  : Led.c

*Author     : SSC_学行者

*Discription: 树莓派Led字符设备驱动文件。

-------------------------------------------------------------------

*/

#include #include #include #include #include #include #include #include #include #include #include #include #include #define DEVICE_NAME "Pi_Led"

#define DRIVER_NAME "pi_led"

//class声明内核模块驱动信息,是UDEV能够自动生成/dev下相应文件

static dev_t pi_led_devno; //设备号

static struct class *pi_led_class;

static struct cdev pi_led_class_dev;

struct gpio_chip *gpiochip;

//Led  GPIO引脚定义

#define led_1 (4u )

#define led_2 (8u )

#define led_3 (9u )

#define led_4 (10u)

#define led_5 (11u)

#define led_6 (23u)

#define led_7 (24u)

#define led_8 (18u)

static unsigned char pin_table[8]={led_1,led_2,led_3,led_4,led_5,led_6,led_7,led_8};

//这部分函数为内核调用后open的设备IO操作,和裸板程序一样

int open_flag=0;

static int pi_led_open(struct inode *inode, struct file *filp)

{

printk("Open led ing!\n");

if(open_flag ==0){

open_flag =1;

printk("Open led success!\n");

return 0;

}

else{

printk("Led has opened!\n");

}

return 0;

}

//这部分函数为内核调用后ioctl的设备IO操作,和裸板程序一样

static long pi_led_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

{

unsigned char i ;

unsigned char data;

for(i = 0 ; i < 8 ; i ++ ){

data = (cmd&0x01);

if(i>7)

i = 7 ;

gpiochip->set(gpiochip, pin_table[i], data);

cmd >>= 1 ;

}

return 0;

}

static int pi_led_release(struct inode *inode,struct file *file){

printk("Led has release!\n");

return 0;

}

//file_operations使系统的open,ioctl等函数指针指向我们所写的led_open等函数,

//这样系统才能够调用

static struct file_operations pi_led_dev_fops = {

.owner          =THIS_MODULE,

.open       =pi_led_open,

.unlocked_ioctl = pi_led_ioctl,

.release       = pi_led_release,

};

static int is_right_chip(struct gpio_chip *chip, void *data)

{

if (strcmp(data, chip->label) == 0)

return 1;

return 0;

}

//内核加载后的初始化函数.

static int __init pi_led_init(void)

{

struct device *dev;

int major; //自动分配主设备号

major = alloc_chrdev_region(&pi_led_devno,0,1,DRIVER_NAME);

//register_chrdev 注册字符设备使系统知道有LED这个模块在.

cdev_init(&pi_led_class_dev, &pi_led_dev_fops);

major = cdev_add(&pi_led_class_dev,pi_led_devno,1);

//注册class

pi_led_class = class_create(THIS_MODULE,DRIVER_NAME);

dev = device_create(pi_led_class ,NULL,pi_led_devno,NULL,DRIVER_NAME);

gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip);

gpiochip->direction_output(gpiochip, led_1, 1);

gpiochip->direction_output(gpiochip, led_2, 1);

gpiochip->direction_output(gpiochip, led_3, 1);

gpiochip->direction_output(gpiochip, led_4, 1);

gpiochip->direction_output(gpiochip, led_5, 1);

gpiochip->direction_output(gpiochip, led_6, 1);

gpiochip->direction_output(gpiochip, led_7, 1);

gpiochip->direction_output(gpiochip, led_8, 1);

gpiochip->set(gpiochip, led_1, 1);

gpiochip->set(gpiochip, led_2, 1);

gpiochip->set(gpiochip, led_3, 1);

gpiochip->set(gpiochip, led_4, 1);

gpiochip->set(gpiochip, led_5, 1);

gpiochip->set(gpiochip, led_6, 1);

gpiochip->set(gpiochip, led_7, 1);

gpiochip->set(gpiochip, led_8, 1);

printk("pi led init ok!\n");

return 0;

}

//内核卸载后的销毁函数.

void pi_led_exit(void)

{

gpio_free(led_1);

gpio_free(led_2);

gpio_free(led_3);

gpio_free(led_4);

gpio_free(led_5);

gpio_free(led_6);

gpio_free(led_7);

gpio_free(led_8);

device_destroy(pi_led_class,pi_led_devno);

class_destroy(pi_led_class);

cdev_del(&pi_led_class_dev);

unregister_chrdev_region(pi_led_devno, 1);

printk("pi led exit ok!\n");

}

module_init(pi_led_init);

module_exit(pi_led_exit);

MODULE_DESCRIPTION("Rasp Led Driver");

MODULE_AUTHOR("SSC_学行者<1129584094>");

MODULE_LICENSE("GPL");

1129584094>

三、Maklefile和Kconfig内容添加

在 /drivers/char目录下的Makefile中添加一下语句:

obj-$(CONFIG_FB_LED)          += Led.o

在相同目录下的Kconfig中添加一下语句:

config FB_LED

tristate "LED connected to Raspberry Pi GPIO support"

depends on FB

select FB_SYS_FILLRECT

select FB_SYS_COPYAREA

select FB_SYS_IMAGEBLIT

select FB_SYS_FOPS

select FB_DEFERRED_IO

help

This driver is for Leds.

SSC_学行者.

四、内核编译

使用menuconfig来编译

在Linux文件夹下:

选择编译选项:

make ARCH=arm CROSS_COMPILE=../RpiTools/arm-bcm2708/arm-bcm2708hardfp-linux-gnueabi/bin/arm-bcm2708hardfp-linux-gnueabi- menuconfig

开始编译:

make ARCH=arm CROSS_COMPILE=../RpiTools/arm-bcm2708/arm-bcm2708hardfp-linux-gnueabi/bin/arm-bcm2708hardfp-linux-gnueabi- -j3

转换内核格式:

cd ../RpiTools/mkimage/

./imagetool-uncompressed.py ../../RpiLinux/arch/arm/boot/zImage

五、拷贝内核到SD卡上

首先先备份SD卡中的kernel.img(也可以直接删除),将mkimage目录下的内核(kernel.img)拷贝到SD中。

六、在树莓派上编写C程序测试

#include#include #include #include #include

//左移函数

unsigned char corr(unsigned char data)

{

unsigned char _data;

_data = data ;

_data <<= 1;

data &=0x80;

if(data)

_data += 1 ;

return _data ;

}

int main(void)

{

int data=0xfe;

int led_no;

int fd;

int i;

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

if (fd < 0) {

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

}

if (fd < 0) {

perror("open device led");

exit(1);

}

for(i=0;i<=7;i++){

ioctl(fd,data, led_no);

corr(data);

sleep(1);

}

close(fd);

return 0;

}

你可能感兴趣的:(嵌入式linux,led驱动有几种写法)