LED驱动动态加载方式(xc2440)
来源:互联网 发布:生物医学数据库官网 编辑:程序博客网 时间:2024/05/18 00:56
上一篇文章,我在ubuntu上创建了一个名为memory的模块,并且通过实验,已经能很好的运行。趁着还有兴趣,而且还有一块闲置的arm9的板子,实验一下在xc2440上搞一个led驱动。以此记录过程:
环境:ubuntu12.04.4 交叉编译器 arm920t-eabi-4.1.2 开发板 XC2440 linux内核版本 2.6.37.4
准备工作,安装在ubuntu上安装交叉编译工具,这个网上很很多例程,在这就不必啰嗦了,安装好交叉编译器,再找一个linux的源码,我找的是2.6.37.4这个版本的,解压到相应的目录,这个目录自己建一个。然后按照内核移植手册一部分配置一下内核,修改Makefile: ARCH ?=arm CROSS_COMPILE ?=arm-linux- 这一系列修改可以参照《xc-2440开发板linux内核移植手册》来完成。如果不配置应该是会出错的,包括什么头文件#include <mach/regs-gpio.h>不存在等等,但是当你在arch/arm/相关目录下查看,会发现这些头文件,我觉得应该是在make menuconfig是选择了默认的2410的配置的原因吧。
然后找一个led的驱动和测试文件,参照http://blog.csdn.net/shiyi_2012/article/details/7451826 这篇文章的代码,参照电路原理图做一些修改:
//led.c 驱动部分
#include<linux/module.h>
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/errno.h>
#include<mach/regs-gpio.h>
#include <mach/hardware.h>
#include<linux/io.h>
#include<asm/uaccess.h>
#define GPIO_LED_MAJOR 97
#define LED_1_ON 1
#define LED_2_ON 2
#define LED_3_ON 3
#define LED_4_ON 4
#define LED_1_OFF 6
#define LED_2_OFF 7
#define LED_3_OFF 8
#define LED_4_OFF 9
#define LED_OFF 5
#define LED1ON 0xFE
#define LED2ON 0xFD
#define LED3ON 0xFB
#define LED4ON 0xF7
#define LED1OFF (~LED1ON)
#define LED2OFF (~LED2ON)
#define LED3OFF (~LED3ON)
#define LED4OFF (~LED4ON)
// LED1 -- GPF0
// LED2 -- GPF1
// LED3 -- GPF2
// LED4 -- GPF3
int GPIO_open(struct inode *inode, struct file *file)
{
printk("Open led successfully!\n\n");
__raw_writel(__raw_readl(S3C2410_GPFCON)&0xFFFFFF55,S3C2410_GPFCON);
__raw_writel((__raw_readl(S3C2410_GPFDAT)|0xFFFF),S3C2410_GPFDAT);
printk("Initialization of LED OK!\n\n");
return 0;
}
int GPIO_release(struct inode *inode, struct file *filp)
{
printk("LED Close successfully!\n\n");
return 0;
}
ssize_t GPIO_read(struct file *filp, char __user *buf, size_t count, loff_t *f_ops)
{
return 0;
}
ssize_t GPIO_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_ops)
{
return count;
}
//执行LED运行模式
int GPIO_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long org)
{
switch(cmd)
{
case LED_1_ON:
{
__raw_writel(__raw_readl(S3C2410_GPFDAT)&LED1ON,S3C2410_GPFDAT);
printk("LED_1 light!\n");
break;
}
case LED_2_ON:
{
__raw_writel(__raw_readl(S3C2410_GPFDAT)&LED2ON,S3C2410_GPFDAT);
printk("LED_2 light!\n");
break;
}
case LED_3_ON:
{
__raw_writel(__raw_readl(S3C2410_GPFDAT)&LED3ON,S3C2410_GPFDAT);
printk("LED_3 light!\n");
break;
}
case LED_4_ON:
{
__raw_writel(__raw_readl(S3C2410_GPFDAT)&LED4ON,S3C2410_GPFDAT);
printk("LED_4 light!\n");
break;
}
case LED_1_OFF:
{
__raw_writel(__raw_readl(S3C2410_GPFDAT)|LED1OFF,S3C2410_GPFDAT);
printk("LED_1 shutdown!\n");
break;
}
case LED_2_OFF:
{
__raw_writel(__raw_readl(S3C2410_GPFDAT)|LED2OFF,S3C2410_GPFDAT);
printk("LED_2 shutdown!\n");
break;
}
case LED_3_OFF:
{
__raw_writel(__raw_readl(S3C2410_GPFDAT)|LED3OFF,S3C2410_GPFDAT);
printk("LED_3 shutdown!\n");
break;
}
case LED_4_OFF:
{
__raw_writel(__raw_readl(S3C2410_GPFDAT)|LED4OFF,S3C2410_GPFDAT);
printk("LED_4 shutdown!\n");
break;
}
case LED_OFF:
{
__raw_writel(__raw_readl(S3C2410_GPFDAT)|0xFFFF,S3C2410_GPFDAT);
printk("LED OFF!\n");
break;
}
default:
{
printk("led control:no cmd run \n");
return -EINVAL;
}
return 0;
}
}
struct file_operations GPIO_LED_ctl_ops={
.owner =THIS_MODULE,
.open =GPIO_open,
.read =GPIO_read,
.write =GPIO_write,
.unlocked_ioctl =GPIO_ioctl,
. release =GPIO_release,
};
static int GPIO_init(void)
{
int ret=-ENODEV;
printk("LED Register...\n\n");
ret=register_chrdev(GPIO_LED_MAJOR,"led",&GPIO_LED_ctl_ops);
if(ret<0)
{
return ret;
}
else
{
}
return ret;
}
static int __init s3c2440_led_init()
{
int ret=-ENODEV;
ret=GPIO_init();
if(ret)
return ret;
return 0;
}
static void s3c2440_led_exit(void)
{
unregister_chrdev(GPIO_LED_MAJOR,"led");
}
module_init(s3c2440_led_init);
module_exit(s3c2440_led_exit);
MODULE_LICENSE("Dual BSD/GPL");
对于驱动部分,由于我们使用的是2.6.37.4版本的内核,有一部分函数有变化,原先的老版本
int (*ioctl)(struct inode*, struct file*, unsigned int, unsigned long);
被改为了
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
因而在实际驱动中,我们需要将原先的写的ioctl函数头给改成下面的unlocked_ioctl,在file_operations结构体的填充中也是一样。
在编译成模块时,我们需要在Makefile文件中指明内核所在路径
参照网上的资料改写的一个Makefile文件:
#kefile2.6
ifneq ($(KERNELRELEASE),)
#kbuild syntax. dependency relationshsip of files and target modules are listed here.
mymodule-objs := led.o
obj-m := led.o
else
PWD := $(shell pwd)
KVER ?= $(shell uname -r)
KDIR := /opt/FriendlyARM/mini2440/linux-2.6.37.4
all:
$(MAKE) -C $(KDIR) M=$(PWD)
clean:
rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions
endif
下面是测试文件:
//led_test.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>
#define LED_1_ON 1
#define LED_2_ON 2
#define LED_3_ON 3
#define LED_4_ON 4
#define LED_1_OFF 6
#define LED_2_OFF 7
#define LED_3_OFF 8
#define LED_4_OFF 9
#define LED_OFF 5
int main()
{
int ret,fd;
int result = 1;
printf("\nstart led_driver test...\n\n");
fd=open("/dev/led",O_RDWR);
if(fd==-1)
{
printf("open device error\n");
return ;
}
while(1)
{
ioctl(fd,0,LED_1_ON);
sleep(2);
ioctl(fd,0,LED_1_OFF);
ioctl(fd,0,LED_2_ON);
sleep(2);
ioctl(fd,0,LED_2_OFF);
ioctl(fd,0,LED_3_ON);
sleep(2);
ioctl(fd,0,LED_3_OFF);
ioctl(fd,0,LED_4_ON);
sleep(2);
ioctl(fd,0,LED_4_OFF);
sleep(2);
}
ret=close(fd);
printf("close led test\n");
return 0;
}
上面的代码是经过反复测试所得确定是正确的,使用make命令生成led.ko 使用arm-linux-gcc -o led_test led_test.c 生成可执行文件led_test 然后就是测试了,使用rz命令将文件下载到开发板,chomd 777 led_test 给文件全部权限,insmod led.ko安装模块,cd /dev 到dev路径创建设备节点,mknod led c 97 0 然后回到根目录,执行./led_test
通过观察,led驱动已经能很好的运行了。
- LED驱动动态加载方式(xc2440)
- LED数码管的驱动方式:静态驱动和动态驱动
- mini2440驱动奇谭——LED驱动与测试(动态加载)
- Tiny 6410 Led 驱动模块加载(五)
- linux2.6.37.4内核在XC2440开发板上移植(十六)USB摄像头驱动移植
- linux2.6.37.4内核在XC2440开发板上移植(八)USB HOST驱动移植
- led驱动(一)
- led驱动模块编译、加载和测试
- Mtk ALPS Led驱动的加载过程
- 编译第一个驱动,加载点亮LED
- Android应用控制LED(动态编译LED驱动)
- 驱动学习5--led动态映射
- 类unix操作系统中,驱动加载方式一般分为:动态加载和静态加载
- led子系统驱动,以及此类驱动(sysfs访问方式)应用程序编写
- 动态加载NT驱动(源码)
- NT驱动加载方式
- 模块化驱动动态加载
- ZwSetSystemInformation 动态加载驱动
- PowerShell中的Json数据转换cmdlets
- window下用cmd命令批量修改后缀名
- c:foreach的基本用法
- SVN使用教程之-分支/标记 合并 subeclipse
- 在我的想象中,有一排机器人
- LED驱动动态加载方式(xc2440)
- Spring学习笔记(一)第一个Spring程序
- css margin的相关属性,问题及应用
- windows下eclipse非插件连接Hadoop集群
- mybatis配置相关问题
- android 开发工具
- 大数除法
- 陈怡暖:黄金无视美元再次跳水,巨量卖单砸开1180支撑
- 示例程序047--用opencv的stitcher类实现图像拼接