电路原理图:控制LED1,就是控制cpu上的GPIOC12管脚
cpu datasheet:GPIOC12配置输出模式
控制输出高/低电平
GPIOCALTFN0
GPIOCOUTENB
GPIOCOUT
内核态控制GPIO管脚有两种方式:
1)类似裸板中直接通过特殊功能寄存器控制
2)通过GPIO库函数(本质就是将操作特殊功能寄存器的过程封装起来了)
这里我们使用第二种方式
Linux系统中使用GPIO库函数的标准套路(gpio_left.c):
1)申请GPIO管脚
int gpio_request(unsigned gpio,const char *name)
gpio,要申请的GPIO管脚
name,名称
返回值,0 申请成功 1 申请失败
2)使用GPIO管脚
int gpio_direction_output(unsigned gpio,int value)
作用:将指定的管脚设置为输出模式
value,0 默认输出低电平 非0 默认输出高电平
gpio,管脚编号1
void gpio_set_value(unsigned gpio,int value)
作用:将指定的gpio管脚设置为value,0/非0 低/高电平
int gpio_direction_input(unsigned gpio,int value)
作用:将指定的管脚设置为输入模式
int gpio_get_value(unsigned gpio)
作用:获取指定管脚的电平状态
返回值:0/非0 低/高电平
3)释放GPIO管脚
void gpio_free(unsigned gpio)
实验步骤:
vi led_drv.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/gpio.h>
#include <mach/platform.h>
MODULE_LICENSE("GPL");
dev_t dev; //num
unsigned int major = 0; //main num
unsigned int minor = 5; //ci num
struct cdev led_cdev;
int led_open(struct inode *inode,struct file *filp){
gpio_set_value(PAD_GPIO_C+12,0);
gpio_set_value(PAD_GPIO_C+11,0);
gpio_set_value(PAD_GPIO_C+7,0);
gpio_set_value(PAD_GPIO_B+26,0);
printk("<2>" "OK %s\n",__func__);
return 0;
}
int led_release(struct inode *inode,struct file *filp){
gpio_set_value(PAD_GPIO_C+12,1);
gpio_set_value(PAD_GPIO_C+11,1);
gpio_set_value(PAD_GPIO_C+7,1);
gpio_set_value(PAD_GPIO_B+26,1);
printk("<2>" "OK %s\n",__func__);
return 0;
}
struct file_operations led_fops={
.owner = THIS_MODULE,
.open = led_open,
.release = led_release,
};
int __init led_drv_init(void){
if(major){
//dev = major<<20|minor;
dev = MKDEV(major,minor);
register_chrdev_region(dev,1,"myleds");
}
else{
alloc_chrdev_region(&dev,minor,1,"myleds");
printk("<2>" "major=%d minor=%d\n",MAJOR(dev),MINOR(dev));
}
cdev_init(&led_cdev,&led_fops);
cdev_add(&led_cdev,dev,1);
gpio_request(PAD_GPIO_C+12,"myleds");
gpio_direction_output(PAD_GPIO_C+12,1);
gpio_request(PAD_GPIO_C+11,"myleds");
gpio_direction_output(PAD_GPIO_C+11,1);
gpio_request(PAD_GPIO_C+7,"myleds");
gpio_direction_output(PAD_GPIO_C+7,1);
gpio_request(PAD_GPIO_B+26,"myleds");
gpio_direction_output(PAD_GPIO_B+26,1);
return 0;
}
void __exit led_drv_exit(void){
cdev_del(&led_cdev);
unregister_chrdev_region(dev,1);
gpio_free(PAD_GPIO_C+12);
gpio_free(PAD_GPIO_C+11);
gpio_free(PAD_GPIO_C+7);
gpio_free(PAD_GPIO_B+26);
}
module_init(led_drv_init);
module_exit(led_drv_exit);
make
//最好将内核中自带的LED驱动裁剪掉
cd /home/tarena/driver/kernel/
make menuconfig
Device Drivers --->
-*- LED Support --->
< > LED Support for GPIO connected LEDs
< > PWM driven LED Support
[ ] LED Trigger support
make uImage
cp arch/arm/boot/uImage /tftpboot
在开发板上执行
insmod led_drv.ko
mknod /dev/myleds c 244 5
./test
观察LED的变化
管脚编号在cfg_××××.c文件好像在common目录下中编辑好了 ↩︎