|
本帖最后由 简单侶途 于 2015-11-13 15:35 编辑
首先介绍我用到的硬件平台和内核版本:Linux cubietruck 3.4.79内核版本,硬件为cubietruck开发板
学习点亮LED入门参考资料,先可以看看下面3份简单的介绍,程序将要用到的,不做其他简单解释咯。
1.必备搭建的工具
实现操作必备的命令:
安装工具
#apt-get install gcc git build-essential libusb-dev pkg-config libusb-1.0
#git clone https://github.com/linux-sunxi/sunxi-tools
#cd sunxi-tools
#make
#cp bin2fex fex2bin fexc /bin
操作script.fex
#vi script.fex
提示:如何找到script.fex进行修改 (以下对于cubietruck卡系统启动)
# mount /dev/mmcblk0p1 /mnt/
#cd /mnt
#ls
lost+found pulse-PKdhtXMmr18n script.bin script.fex uEnv.txt uImage
2.修改配置文件,#后面的是注释,请忽略添加在script.fex文件下,script.fex文件修改以下部分,来实现控制4个led
#-----------------------------------------------------------------------------表情那里是PH20,不知道为何是表情
[gpio_para]
gpio_used = 1 #1为使能,0为失能
gpio_num = 4 #4为应用4个引脚配置
gpio_pin_1 = portH20<1><default><default><1> #num = 1
gpio_pin_2 = portH21<1><default><default><1> #num = 2
gpio_pin_3 = portH11<1><default><default><1> #num = 3
gpio_pin_4 = portH7<1><default><default><1> #num = 4
[leds_para]
leds_used = 0 #失能led系统配置,这些引脚被我引用为4个led控制引脚了
leds_num = 4
3.修改完后,记得执行
root@cubietruck:/mnt# fex2bin script.fex script.bin
#reboot
4.开始我们的第一门入门学习了,刚开始学的时候可以参考韦东山视频教程的点亮LED,不过平台不一样,大体框架还算类似- #include<linux/fs.h>
- #include<linux/module.h>
- #include<linux/errno.h>
- #include<linux/kernel.h>
- #include<linux/init.h>
- #include<linux/cdev.h>
- #include<linux/uaccess.h>
- #include<linux/device.h>
- #include<linux/types.h>
- #include <asm/gpio.h>
- #include <linux/gpio.h>
- #include <plat/sys_config.h>
- #include <linux/delay.h>
- #include <asm/irq.h>
- #include <asm/io.h>
- //设备类
- static struct class *leddrv_class;
- //分配 cdev
- static struct class_device *leddrv_class_dev;
- //主设备号
- static int major;
- static int status;//表示灯的状态
- static int led_open(struct inode *inode, struct file *file)
- {
- return 0;
- }
- static ssize_t led_read (struct file *file,char __user *buf,
- size_t count,loff_t *f_pos)
- {
- copy_to_user(buf,&status,4);
- return count;
- }
- static ssize_t led_write (struct file *file,char __user *buf,
- size_t count,loff_t *f_pos)
- {
- int val;
- /*1.从用户空间读取数据到内核空间*/
- copy_from_user(&val,buf,4);
- /*2.判断传入值val,进行GPIO电平控制*/
- if(val == 1){
- gpio_set_value(1,1);
- gpio_set_value(2,1);
- gpio_set_value(3,1);
- gpio_set_value(4,1);
- }
- else{
- gpio_set_value(1,0);
- gpio_set_value(2,0);
- gpio_set_value(3,0);
- gpio_set_value(4,0);
- }
- return 0;
- }
- //分配驱动操作
- static struct file_operations leddrv_fops = {
- .owner = THIS_MODULE,
- .open = led_open,
- .read = led_read,
- .write = led_write,
- };
- static int led_init(void)
- {
-
- major = register_chrdev(0, "led", &leddrv_fops);
- leddrv_class = class_create(THIS_MODULE, "led");
- leddrv_class_dev = device_create(leddrv_class, NULL, MKDEV(major, 0), NULL, "ledwht"); /* /dev/ledwht */
- /*申请GPIO资源*/
- if(gpio_request(1,"gpio")){
- printk("request gpio1 error\n");
- }
- if(gpio_request(2,"gpio")){
- printk("request gpio2 error\n");
- }
- if(gpio_request(3,"gpio")){
- printk("request gpio3 error\n");
- }
- if(gpio_request(4,"gpio")){
- printk("request gpio4 error\n");
- }
-
- /*配置为输出引脚*/
- gpio_direction_output(1,0);
- gpio_direction_output(2,0);
- gpio_direction_output(3,0);
- gpio_direction_output(4,0);
- return 0;
- }
- static void led_exit(void)
- {
- /*1.释放 GPIO 资源*/
- gpio_free(1);
- gpio_free(2);
- gpio_free(3);
- gpio_free(4);
- unregister_chrdev(major, "led");
- /*2.删除设备节点*/
- device_destroy(leddrv_class, MKDEV(major, 0));
- class_destroy(leddrv_class);
- }
- module_init(led_init);
- module_exit(led_exit);
- MODULE_LICENSE("GPL");
复制代码 5.测试驱动程序
1.insmod led_drv1.ko //加载驱动
2../led_app //同时点亮4个led
end--firstdriver---------------------------------------------------------------------------------------------------------------------------
6.对比一下两个文件可以看出,就寄存器部分不一样而已- #include<linux/fs.h>
- #include<linux/module.h>
- #include<linux/errno.h>
- #include<linux/kernel.h>
- #include<linux/init.h>
- #include<linux/cdev.h>
- #include<linux/uaccess.h>
- #include<linux/device.h>
- #include<linux/types.h>
- #include <asm/gpio.h>
- #include <linux/gpio.h>
- #include <plat/sys_config.h>
- #include <linux/delay.h>
- #include <asm/irq.h>
- #include <asm/io.h>
- #include <linux/moduleparam.h>
- #include <linux/poll.h>
- #include <linux/sched.h>
- #include <linux/spinlock.h>
- #include <linux/slab.h>
- #include <linux/ipmi.h>
- #include <linux/mutex.h>
- #include <linux/compat.h>
- /*两种方法寻找GPIO寄存器地址*/
- //#define PIO_BASE 0x01C20800
- #define PH_BASE (PIO_BASE + 7*0x24)
- #define PH_CFG2 (PH_BASE + 0x08)
- #define PH_DAT (PH_BASE + 0x10)
- //#define PH_BASE (PIO_BASE + 0xFC)
- //#define PH_CFG2 (PIO_BASE + 0x104)
- //#define PH_DAT (PIO_BASE + 0X10C)
- static volatile unsigned int *ph_cfg2;
- static volatile unsigned int *ph_dat;
- //设备类
- static struct class *leddrv_class;
- //分配 cdev
- static struct class_device *leddrv_class_dev;
- //主设备号
- static int major;
- static int led_open(struct inode *inode, struct file *file)
- {
- /*bit20[18:16],bit21[22:20]
- *open the roange_led and blue_led GPIO output
- *Output is 001
- */
- *ph_cfg2 &= ~((7<<16) | (7<<20));//清零000,这个步骤很重要,注释掉可以看下效果如何blue_led不能控制了
- *ph_cfg2 |= ((1<<16) | (1<<20));//设置001
- return 0;
- }
- static ssize_t led_write (struct file *file,char __user *buf,
- size_t count,loff_t *f_pos)
- {
- int val;
- /*1.从用户空间读取数据到内核空间*/
- copy_from_user(&val,buf,4);
- /*2.判断传入值val,进行GPIO电平控制*/
- if(val == 1){
- *ph_dat |= ((1<<20) | (1<<21));
- }else{
- *ph_dat &= ~((1<<20) | (1<<21));
- }
- return 0;
- }
- //分配驱动操作
- static struct file_operations leddrv_fops = {
- .owner = THIS_MODULE,
- .open = led_open,
- .write = led_write,
- };
- static int led_init(void)
- {
- ph_cfg2 = ioremap(PH_CFG2, 4);
- ph_dat = ioremap(PH_DAT, 4);
-
- major = register_chrdev(0, "led", &leddrv_fops);
- leddrv_class = class_create(THIS_MODULE, "led");
- leddrv_class_dev = device_create(leddrv_class, NULL, MKDEV(major, 0), NULL, "ledwht"); /* /dev/ledwht */
- return 0;
- }
- static void led_exit(void)
- {
- unregister_chrdev(major, "led");
- /*2.删除设备节点*/
- device_destroy(leddrv_class, MKDEV(major, 0));
- class_destroy(leddrv_class);
- iounmap(ph_cfg2);
- iounmap(ph_dat);
- }
- module_init(led_init);
- module_exit(led_exit);
- MODULE_LICENSE("GPL");
复制代码 7.第二个应用操作寄存器方法控制LED点亮led_orange,led_blue
现在就可以直接打开script.fex修改回原来到配置了
[gpio_para]
gpio_used = 1 #1为使能,0为失能
gpio_num = 4 #4为应用4个引脚配置
gpio_pin_1 = portH10<1><default><default><1> #num = 1//随便乱搞可以了,因为你可以直接操作地址来控制它
gpio_pin_2 = portH11<1><default><default><1> #num = 2
gpio_pin_3 = portH11<1><default><default><1> #num = 3
gpio_pin_4 = portH7<1><default><default><1> #num = 4
[leds_para]
leds_used = 0 #失能led系统配置,不失能也可以,但是LED在你打开./led_app后会被系统改变状态
leds_num = 4
驱动程序
1.insmod led_drvreg.ko //加载驱动
2../led_app //同时点亮2个led
在注册设备和卸载驱动解释它的思想:
A. led_init编写顺序:
(1)映设虚拟地址,ioremap
(2)注册结构体,告诉内核leddrv_fops
(3)申请设备类class_create
(4)生成设备节点device_create /dev/ledwht #ls /dev/ledwht确实在加载驱动时候生成
B. led_exit编写顺序:
(1)卸载结构体unregister_chrdev
(2)删除设备节点device_destroy
(3)删除设备类class_destroy
(4)释放虚拟地址,ioremap
这个顺序就好比如你开电脑之前必须
1.开电源
2.按下电脑开机按钮
3.打开应用程序
-----------------
关闭电脑的顺序是
1.关闭应用程序
2.找到关机界面,确定关机
3.最后才是关闭电源。
是不是很有道理呢!!!
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|