一、S3C2410输入/输出的原理
Linux主要有字符设备、块设备和网络设备3类驱动程序,我们一般编写的驱动都是字符设备驱动程序。
二、程序部分
编写程序控制3个LED灯,代码分为2个部分:控制LED的驱动程序、调用驱动程序的应用程序
1. 控制LED的驱动程序
(1) 常量和结构体的定义:
//定义设备名字,分配设备号时使用
#define DEVICE_NAME 'UP-LED'
//定义次设备号
#define LEDRAW_MINOR 0
//定义端口C配置寄存器
#define GPCCON (*(volatile unsigned int *)S3C2410_GPCCON)
//定义端口C数据寄存器
#define GPCDAT (*(volatile unsigned int *)S3C2410_GPCDAT)
//定义字符设备结构体
struct cdev *mycdev;
//定义设备号变量,由主设备号和次设备号组成
dev_t devno;
//文件操作结构体定义使用设备的文件操作
static struct file_operations led_fops = {
owner: THIS_MODULE,
ioctl: led_ioctl, //只定义ioctl一个
};
(2) 驱动加载时的代码:
//定义加载驱动时执行的函数
module_init(led_init);
static int __init led_init(void)
{
int result,err;
//分配字符设备号
result=alloc_chrdev_region(&devno,LEDRAW_MINOR,1,DEVICE_NAME);
if(result < 0)
printk(KERN_ERR 'can't get device number n');
else
printk('get device numbern');
//设置GPC5、GPC6、GPC7为输出状态
GPCCON=(GPCCON|0x5400)&0xffff57ff;
//分配字符设备结构体
mycdev = cdev_alloc();
//初始化结构体,关联文件操作
cdev_init(mycdev,&led_fops);
//将字符设备驱动注册到内核
err=cdev_add(mycdev,devno,1);
if (err < 0)
printk(KERN_ERR 'can't add led device');
return 0;
}
(3) 定义控制LED的文件操作:
static int led_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{ switch(cmd){
case 1:
if(arg==1) GPCDAT=GPCDAT&0xffffffdf;//第一个led亮
if(arg==0) GPCDAT=GPCDAT|0x20; //第一个led灭
break;
case 2:
if(arg==1) GPCDAT=GPCDAT&0xffffffbf;//第二个led亮
if(arg==0) GPCDAT=GPCDAT|0x40; //第二个led灭
break;
case 3:
if(arg==1) GPCDAT=GPCDAT&0xffffff7f;//第三个led亮
if(arg==0) GPCDAT=GPCDAT|0x80; //第三个led灭
break;
default:
printk('error cmd numbern');break;
}
return 0;
}
2. 调用驱动程序的应用程序
//相关头文件的引用
#include #include #include #include int main(int argc, char **argv) { //相关常量变量定义 int on; int led_number; int fd; //读入命令行参数 sscanf(argv[1], “%d”, &led_number); sscanf(argv[2],'%d', &on); //打开设备文件 fd = open('/dev/leds', 0); if (fd < 0) { perror('open device /dev/leds'); exit(1); } //根据参数操作设备 ioctl(fd, led_number, on); usleep(1000); //关闭设备文件 close(fd); return 0; } 3. makefile文件 ARGET = test_led CROSS_COMPILE = arm-linux CC = $(CROSS_COMPILE)gcc ifeq ($(KERNELRELEASE),) KERNELDIR ?= /root/kernel/linux-2.6.24.4 PWD := $(shell pwd) all: $(TARGET) modules $(TARGET): $(CC) -o $(TARGET) $(TARGET).c modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: rm -rf *.o *~ *.ko Module.symvers *.mod.c $(TARGET) .PHONY:modules clean else obj-m := led.o endif 在主机(虚拟机)上进行交叉编译: 根据makefile编译得到可执行文件test_led。 在主机上输入下面两行代码,将下面的两个文件上传到tftp服务器 利用xshell超级终端,在目标机上接收led.ko和test_led文件,并且加载驱动程序 手动创建led设备节点,并给test_led文件可执行权限三、实验过程
cp led.ko /tftpboot/
cp test_led /tftpboot/
实验现象:
上一篇:s3c2410 MMU
下一篇:s3c6410裸机程序(1)