在完成这个驱动代码的时候,中间经历了很多的小问题,具体的总结我都放在了这个地方:
http://www.jyguagua.com/?p=723
针对字符驱动,可以参考LDD3去学习研究,LDD3讲的非常详细,本文只是针对kernel 2.6.32.2环境下对mini 2440的开发板的led驱动做演示:
首先看下leddrive.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
//#include <asm/irq.h>
//#include <asm/arch/regs-gpio.h>
//#include <asm/hardware.h>
#include <asm/io.h>
#include <mach/irqs.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/device.h>
MODULE_LICENSE("GPL");
struct class *led_class;
//struct class_device *led_dev;
/*led IO寄存器定义*/
volatile unsigned long *gpbcon = NULL;
volatile unsigned long *gpbdat = NULL;
volatile unsigned long *gpbup = NULL;
/*主设备号*/
int major;
static int led_open(struct inode *inode, struct file *file)
{
printk("first_drv_open\n");
/*配置GPBCON, GPBDAT, GPBUP寄存器,根据mini2440原理图可知是GPB_IO口*/
*gpbcon &= ~((0x3 << (5*2)) | (0x3 << (6*2)) | (0x3 << (7*2)) | (0x3 << (8*2)));
*gpbcon |= (0x1 << (5*2)) | (0x1 << (6*2)) | (0x1 << (7*2)) | (0x1 << (8*2));
*gpbdat |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
//上拉电阻关闭
*gpbup |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
return 0;
}
static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
printk("first_drv_write1\n");
int val;
//将数据从用户空间拷贝至内核空间
copy_from_user(&val, buf, count);
if (val == 1) {
printk("first_drv_write2\n");
//如果是1的话,就给各端口写入低电平,这样led就点亮,反之则灭,如下一种情况
*gpbdat &= ~((1 << 5) | (1 << 6) | (1 << 7) | (1 << 8));
} else {
printk("first_drv_write3\n");
*gpbdat |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
}
return 0;
}
static struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
};
static int led_init(void)
{
//获取主设备号
major = register_chrdev(0, "led_drv", &led_fops);
//通过class_create以及device_create来在/dev路径下创建设备led
led_class = class_create(THIS_MODULE, "leddrv");
device_create(led_class, NULL, MKDEV(major, 0), NULL, "led");
//内存映射,调用ioremap函数,对应的GPBDAT, GPBUP只是增加单位而已
gpbcon = (volatile unsigned long *)ioremap(0x56000010, 16);
gpbdat = gpbcon + 1;
gpbup = gpbdat + 1;
return 0;
}
static void led_exit(void)
{
//注销设备号
unregister_chrdev(major, "led_drv");
//删除设备
device_destroy(led_class, MKDEV(major, 0));
class_destroy(led_class);
iounmap(gpbcon);
}
module_init(led_init);
module_exit(led_exit);
然后是Makefile:
ifneq ($(KERNELRELEASE),) obj-m := leddrive.o else #KERNELDIR ?= /lib/modules/$(shell uname -r)/build KERNELDIR ?= /usr/src/linux-2.6.32.2 PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules endif
最后是我们的测试代码,测试代码就是读取dev下我们新创建的设备,然后发送参数,使得led点亮,代码ledtest.c如下:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
/* firstdrvtest on
* firstdrvtest off
*/
int main(int argc, char **argv)
{
int fd;
int val = 1;
fd = open("/dev/led", O_RDWR);
if (fd < 0)
{
printf("can't open!\n");
}
if (argc != 2)
{
printf("Usage :\n");
printf("%s <on|off>\n", argv[0]);
return 0;
}
if (strcmp(argv[1], "on") == 0) {
val = 1;
} else {
val = 0;
}
write(fd, &val, 4);
return 0;
}
如上代码编好之后,可以通过如下命令获得leddrive.ko 和测试程序ledtest:
[ypf@localhost linux]#make #获得leddrive.ko [ypf@localhost linux]#arm-linux-gcc -o ledtest ledtest.c #获得测试程序ledtest
运行如下:
[ypf@localhost linux]#insmod leddrive.ko [ypf@localhost linux]#./ledtest on #打开led [ypf@localhost linux]#./ledtest off #关闭led
文章的脚注信息由WordPress的wp-posturl插件自动生成
微信扫一扫,打赏作者吧~![[已解决]nc命令报错 close: Bad file descriptor](http://www.jyguagua.com/wp-content/themes/begin/timthumb.php?src=http://www.jyguagua.com/wp-content/uploads/2022/03/Snipaste_2022-03-18_20-16-48.png&w=280&h=210&zc=1)
![[已解决]SecureCRT/SSH 连接Linux缓慢](http://www.jyguagua.com/wp-content/themes/begin/timthumb.php?src=http://www.jyguagua.com/wp-content/uploads/2020/07/ssh_slow.jpg&w=280&h=210&zc=1)
![[转载]Linux的tickless设置](http://www.jyguagua.com/wp-content/themes/begin/timthumb.php?src=http://www.litrin.net/wp-content/uploads/2018/11/kernel_menuconfig_tickless-1.png&w=280&h=210&zc=1)
![[整理]鲲鹏性能优化十板斧(五)——应用程序性能调优<TaiShan特战队出品>](http://www.jyguagua.com/wp-content/themes/begin/timthumb.php?src=http://www.jyguagua.com/wp-content/uploads/2020/03/1-4.jpg&w=280&h=210&zc=1)