作者:chenzhufly QQ:36886052 ( 转载请注明出处)
一路走来,熟悉硬件系统,搭建软件开发环境,编译Linux系统等等,现在也该到对硬件做一些事情了,这是我这几天的研究心得,与君共享。
1. GPIO的char型驱动,这里主要就是点个灯,感受一下驱动的设计和硬件的控制驱动程序: - #include <linux/init.h>
#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 <stdlib.h>
#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文件: - ARCH=arm
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脚本 - insmod leds.ko
mknod /dev/leds c 251 0 ./leds_test
复制代码
2. 使用echo命令,这个我在前面也说过 - 点亮usr1
root@beaglebone:~# echo 1 > /sys/class/leds/beaglebone::usr1/brightness
关闭usr1 root@beaglebone:~# echo 0 > /sys/class/leds/beaglebone::usr1/brightness
复制代码
3. 做个应用程序实现流水灯功能吧 - #include <stdio.h>
#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的速率,再贴个图上来。
|