作者:chenzhufly QQ:36886052 ( 转载请注明出处)
一路走来,熟悉硬件系统,搭建软件开发环境,编译Linux系统等等,现在也该到对硬件做一些事情了,这是我这几天的研究心得,与君共享。
1. GPIO的char型驱动,这里主要就是点个灯,感受一下驱动的设计和硬件的控制驱动程序:
#include <linux/module.h>
#include <linux/leds.h>
#include <linux/io.h>
#include <linux/semaphore.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <mach/gpio.h>
#include <plat/mux.h>
#include <linux/gpio.h>
/*******************************************/
#define NAME "leds"
#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))
static int major =251;//定义主设备号
/*******************************************/
void led_on(void)
{
gpio_set_value(GPIO_TO_PIN(1,22), 1);
}
void led_off(void)
{
gpio_set_value(GPIO_TO_PIN(1,22), 0);
}
void led_init(void)
{
int result;
/* Allocating GPIOs and setting direction */
result = gpio_request(GPIO_TO_PIN(1,22), "Leds");//usr1
if (result != 0)
printk("gpio_request(1_22) failed!\n");
result = gpio_direction_output(GPIO_TO_PIN(1,22), 1);
if (result != 0)
printk("gpio_direction(1_22) failed!\n");
}
struct light_dev
{
struct cdev cdev;
unsigned char value;
};
struct light_dev *light_devp;
MODULE_AUTHOR("chenzhufly");
MODULE_LICENSE("Dual BSD/GPL");
// 打开和关闭函数
int light_open(struct inode *inode,struct file *filp)
{
struct light_dev *dev;
// 获得设备结构体指针
dev = container_of(inode->i_cdev,struct light_dev,cdev);
// 让设备结构体作为设备的私有信息
filp->private_data = dev;
return 0;
}
int light_release(struct inode *inode,struct file *filp)
{
return 0;
}
// ioctl
int light_ioctl(struct file *filp,unsigned int cmd,
unsigned long arg)
{
struct light_dev *dev = filp->private_data;
switch(cmd)
{
case 0:
dev->value = 0;
led_off();
break;
case 1:
dev->value = 1;
led_on();
break;
default:
return -ENOTTY;
// break;
}
return 0;
}
struct file_operations light_fops =
{
.owner = THIS_MODULE,
.unlocked_ioctl = light_ioctl,
.open = light_open,
.release = light_release,
};
// 模块加载函数
int light_init(void)
{
int ret;
led_init();
printk(KERN_ALERT "led modules is install\n");
ret=register_chrdev(major,NAME,&light_fops);
if(ret<0)
{
printk("unable to register myled driver!\n");
return ret;
}
return 0;
}
// 模块卸载函数
void light_cleanup(void)
{
unregister_chrdev(major,NAME);
printk("Goodbye,cruel world!\n");
}
module_init(light_init);
module_exit(light_cleanup);
应用程序:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <unistd.h>
#include <sys/ioctl.h>
int main(int argc, char * argv)
{
int i, n, fd;
fd = open("/dev/leds", O_RDWR);
if (fd < 0)
{
printf("can't open /dev/leds!\n");
exit(1);
}
while (1) {
ioctl(fd, 1, 1);
sleep(1);
ioctl(fd, 0, 1);
sleep(1);
}
close(fd);
return 0;
}
Makefile文件:
CROSS_COMPILE=/home/chenzhufly/beaglebone/linux-devkit/bin/arm-arago-linux-gnueabi-
obj-m := leds.o
KDIR := /home/chenzhufly/beaglebone/board-support/linux-3.1.0-psp04.06.00.03.sdk
PWD := $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
app: leds_test.c
$(CROSS_COMPILE)gcc -o leds_test leds_test.c
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
leds.sh脚本
mknod /dev/leds c 251 0
./leds_test
2. 使用echo命令,这个我在前面也说过
root@beaglebone:~# echo 1 >
/sys/class/leds/beaglebone::usr1/brightness
关闭usr1
root@beaglebone:~# echo 0 > /sys/class/leds/beaglebone::usr1/brightness
3. 做个应用程序实现流水灯功能吧
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#define LED1 "/sys/class/leds/beaglebone::usr1/brightness" // usr1 led
#define LED2 "/sys/class/leds/beaglebone::usr2/brightness" // usr2 led
#define LED3 "/sys/class/leds/beaglebone::usr3/brightness" // usr3 led
int main(void)
{
int f_led1 = open(LED1, O_RDWR);
int f_led2 = open(LED2, O_RDWR);
int f_led3 = open(LED3, O_RDWR);
unsigned char dat1, dat2, dat3;
unsigned char i = 0;
if (f_led1 < 0)
{
printf("error in open %s",LED1);
return -1;
}
if (f_led2 < 0)
{
printf("error in open %s",LED2);
return -1;
}
if (f_led3 < 0)
{
printf("error in open %s",LED3);
return -1;
}
//add 10 times
for(i=1; i<30; i++)
{
dat1 = ((i%3) == 1) ? '1' : '0';
dat2 = ((i%3) == 2) ? '1' : '0';
dat3 = ((i%3) == 0) ? '1' : '0';
write(f_led1, &dat1, sizeof(dat1));
write(f_led2, &dat2, sizeof(dat2));
write(f_led3, &dat3, sizeof(dat3));
usleep(300000);
}
// all the bright
{
dat1 = '1';
dat2 = '1';
dat3 = '1';
write(f_led1, &dat1, sizeof(dat1));
write(f_led2, &dat2, sizeof(dat2));
write(f_led3, &dat3, sizeof(dat3));
}
}
有兴趣的可以试试,等我找个示波器测试一下IO的速率,再贴个图上来。
chenzhufly,你好。
如何编译获得驱动程序文件leds.o? 是用命令行还是Makefile文件。
能不能把驱动程序leds.c 和Makefile共享一下。
我复制粘贴得到的文件编译无法成功。
出现以下信息: make: Entering directory `/home/zdp/ti-sdk-am335x-evm-05.03.02.00/board-support/linux-3.1.0-psp04.06.00.03.sdk' /home/zdp/Makefile:9: *** missing separator. Stop. make: *** [_module_/home/zdp] Error 2 make: Leaving directory `/home/zdp/ti-sdk-am335x-evm-05.03.02.00/board-support/linux-3.1.0-psp04.06.00.03.sdk'
[ 本帖最后由 zhdphao 于 2012-6-2 14:44 编辑 ]还是没有编译成功,我已经改动了makefile文件,如下:
ARCH=arm
CROSS_COMPILE= arm-arago-linux-gnueabi-
obj-m := leds.o
KDIR := /home/zdp/AM335X-LINUX-PSP-04.06.00.03/src/kernel/linux-04.06.00.03/include/
PWD := $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
app: leds_test.c
$(CROSS_COMPILE)gcc -o leds_test leds_test.c
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
[ 本帖最后由 zhdphao 于 2012-6-3 16:13 编辑 ]