led 驱动

1. 程序思路:

通过ioctrl 来将应用程序的命令传递到驱动中的 struct file_operation 中的 unlocked_ioctl 方法中,判断命令进行相应的操作。
在通用的头文件中定义ioctrl的命令

#define LED_ON 	_IO('l',1)
#define LED_OFF _IO('l',2)

我们想在应用程序中这样来操作led

int main(int argc, const char *argv[])
{
	int fd = open("/dev/led", O_RDWR); // 打开设备节点
	if(fd<0) {
		perror("open");
		return -1;
	}
	puts("app open end");

	while(1) {
		ioctl(fd, LED_ON); // 打开灯
		sleep(2);
		ioctl(fd, LED_OFF); // 关闭灯
		sleep(2);
	}

	close(fd);
	puts("app close end");
	return 0;
}

那驱动中我们就要实现字符设备的 struct file_operation的 unlocked_ioctl 方法

static long led_ioctl (struct file *filep, unsigned int cmd, unsigned long argv)
{
	switch(cmd)
	{
		case LED_ON:
			printk("LED_ON\n");
			led_on();
			break;
		case LED_OFF:
			printk("LED_OFF\n");
			led_off();
			break;
		default:
			return -EINVAL;
	}
	return 0;
}

struct file_operations led_fops = {
	.owner=THIS_MODULE,
	.open = led_open,
	.release =led_release,
	.unlocked_ioctl = led_ioctl,
};

当然,对于要操作硬件IO,需要将IO寄存器ioremap地址空间映射到内核空间上来。。
在4412开发板上的实现的led可以控制的驱动代码如下:
驱动: fs4412_led.c

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include "fs4412_led.h"
#include <asm/io.h>

#define LED_MA 250
#define LED_MI 0

#define GPX2CON 0x11000c40
#define GPX2DAT 0x11000c44

MODULE_LICENSE("GPL");

static unsigned int * gpx2con =NULL;
static unsigned int * gpx2dat =NULL;

struct cdev cdev;

dev_t devno=MKDEV(LED_MA, LED_MI);


static void led_on(void)
{
	writel(readl(gpx2dat) |(0x1<<7),gpx2dat); 
	return ;
}
static void led_off(void)
{
	writel(readl(gpx2dat) & (~(0x1<<7)) ,gpx2dat); 
	return ;
}
static	int led_open (struct inode * inodep, struct file *filep)
{
	printk("led_open\n");
	return 0;
}

static int led_release (struct inode *inodep, struct file *filep)
{
	printk("led_release\n");
	return 0;

}

static long led_ioctl (struct file *filep, unsigned int cmd, unsigned long argv)
{
	switch(cmd)
	{
		case LED_ON:
			printk("LED_ON\n");
			led_on();
			break;
		case LED_OFF:
			printk("LED_OFF\n");
			led_off();
			break;
		default:
			return -EINVAL;
	}
	return 0;
}

struct file_operations led_fops = {
	.owner=THIS_MODULE,
	.open = led_open,
	.release =led_release,
	.unlocked_ioctl = led_ioctl,
};

static int led_init(void)
{
	unsigned int ret = 0;
	printk("led_init start \n");
	
	ret = register_chrdev_region(devno, 1, "fs4412_led_device");
	if(ret<0)
	{
		printk("register_chrdev_region error\n");
		return ret;
	}

	cdev.owner = THIS_MODULE;
	cdev_init(&cdev, &led_fops);
	ret = cdev_add(&cdev, devno, 1);
	if(ret < 0)
	{
		printk("cdev_add error\n");
		goto err1;
	}

	gpx2con = ioremap(GPX2CON, 4);
	if(NULL == gpx2con)
	{
		printk("ioremap(GPX2CON) error\n");
		goto err2;
	}

	gpx2dat = ioremap(GPX2DAT, 4);
	if(NULL == gpx2dat)
	{
		printk("ioremap(GPX2DAT) error\n");
		goto err3;
	}

	writel((readl(gpx2con) & (~(0xf<<28))) | (0x1<<28) ,gpx2con); 
	writel(readl(gpx2dat) & (~(0x1<<7)) ,gpx2dat); 

	printk("led_init end \n");
	return 0;

err3:
	iounmap(gpx2con);
err2:
	cdev_del(&cdev);
err1:
	 unregister_chrdev_region(devno,1);
	
	 return ret;
	
}
static void led_exit(void)
{
	printk("led_exit start \n");
	
	iounmap(gpx2dat);
	iounmap(gpx2con);

	cdev_del(&cdev);
	unregister_chrdev_region(devno,1);
	printk("led_exit end \n");
	return ;
}
module_init(led_init);
module_exit(led_exit);

头文件:fs4412_led.h

#ifndef __FS4412_LED_H__
#define __FS4412_LED_H__

#define LED_ON 	_IO('l',1)
#define LED_OFF _IO('l',2)

#endif

Makefile 文件

$(warning KERNELRELEASE=$(KERNELRELEASE))
ifeq ($(KERNELRELEASE),)

KERNELDIR ?= /home/qin/linux-3.14-fs4412/

#KERNELDIR ?= /lib/modules/$(shell uname -r)/build  
PWD := $(shell pwd)

modules:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
	arm-linux-gcc led_test.c -o led_test.out 
	cp fs4412_led.ko  led_test.out /source/rootfs/

clean:
	rm -rf *.out *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules*

.PHONY: modules modules_install clean

else
    obj-m := fs4412_led.o
endif


应用层测试用的代码: led_test.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "fs4412_led.h"

int main(int argc, const char *argv[])
{
	int fd = open("/dev/led", O_RDWR); // 打开设备节点
	if(fd<0) {
		perror("open");
		return -1;
	}
	puts("app open end");

	while(1) {
		ioctl(fd, LED_ON); // 打开灯
		sleep(2);
		ioctl(fd, LED_OFF); // 关闭灯
		sleep(2);
	}

	close(fd);
	puts("app close end");
	return 0;
}

2. 可能出现的问题:

[root@lip ~]# rmmod
rmmod: can’t change directory to ‘/lib/modules’: No such file or directory
[root@lip ~]# mkdir /lib/modules
[root@lip ~]# rmmod led
rmmod: can’t change directory to ‘3.4.112’: No such file or directory
[root@lip ~]# mkdir /lib/modules/3.4.112
[root@lip ~]# rmmod led
led_exit is load

这个问题是删除模块提示 can’t change directory to ‘/lib/modules’: No such file or directory 错误,解决的办法就是 提示不能 改变到 /lib/modules ,是因为没有这个文件夹,我们新建这个文件夹,又提示没有 3.4.112 这个文件夹,我们继续新建这个文件夹,解决。

3. 用到platform总线的 led 驱动:

根据platform的结构,将设备的资源单独放到设备中,在设备中
在模块的入口函数中注册一个platform的设备
在这里插入图片描述
在驱动侧注册驱动结构体
在这里插入图片描述
其中的 platform_driver.driver.name 的名字 跟 platform_device.name 做比对。probe方法中实现

  1. io 资源的映射
  2. 注册字符设备,创建设备节点

remove方法中进行反操作

  1. 设备节点注销
  2. 类注销
  3. 字符设备注销

在这里插入图片描述在这里插入图片描述

HD2010操作说明(HD2010 operating instructions) ⅰ.软件安装(Installed software) 双击光盘HD2010 V2.0目录下的安装文件图标 ,将控制系统安装到个人电脑.如下图2-1 (Open Profile HD2010 V2.0 in the compact disk,Dblclick Installed the HD2010 V2.0 in your personal computer.As shown in Figure 2-1) 图(Figure)2-1 点击确定后进入下一步如图2-2 (Click确定intro- next step.As shown in Figure 2-2 ) 图(Figure)2-2 点击下一步后进入下一步(英文环境)在中文环境直接点击下一步完成安装)如图2-3 2-4 2-5 2-6 2-7 (Click next intro- next step.As shown in Figure 2-3 2-4 2-5 2-6 2-7) 图(Figure)2-3 注意:发送的文件保存在安装目录下的ProjFile文件夹里,点击下一步完成安装 (Announcements:The file what you send saved in the ProjFile in path of Install.And click next to install and finish) 图(Figure)2-4 图(Figure)2-5 图(Figure)2-6 安装最后一步如图2-7 (The final step of install. As shown in Figure 2-7) 图(Figure)2-7 点击完成打开软件主界面如图2-8 (Click finish open main interface of the software. As shown in Figure 2-8) ⅱ.软件设置(Setting software) ⅱ.ⅰ主界面如图2-8(Main interface.As shown in Figure 2-8) 图(Figure)2-8 ⅱ.ⅱ软件属性(Software properties) 1.文件菜单(File menu) a.新建--新建一个新的显示屏(New—Create a new screen) b.打开--打开一个显示屏(Open—Open a exist screen) c.保存--保存建立的文件(Save—Save file) d.另存为--保存副本(Save as—save a copy) e.导出.hds--导出.hds文件,用于u盘读取文件 (Export.hds—Export.hds file,for usb reading) f.退出--退出软件(Exit—Exit the software) 2.设置菜单(Settings menu) a.屏参设置--设置显示屏属性 (Screen settings—Display Screen configuration attributes) b.通信设置--通信端口/方式设置 (Communication settings—Set Communication prot and fashion) c.系统设置--配置系统默认项 (System settings—Set the acquice properties of software) 3.操作菜单(Operate menu) a.发送项目--发送节目(Send project—send the programmes) b.导出到U盘--把节目导入到U盘 (Export to U disk—send the programme to your U disk) c.时间设置--时间校对 (Time setting—get the right time im your computer) d.亮度设置--选择亮度模式 (Luminance setting—Choice the module of Luminance) e.固件更新--固件升级(Update Firmware—Update your controller Firmware) 4.语言菜单(Language menu) a.简体中文(Simplified Chinese) b.繁体中文(Chinese Traditional) c.英语(English) ⅱ.ⅲ节目编辑(Edit
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值