S3C2410——LED灯实验
写在最前面:嵌入式实验,ping不通时一定要先看看网线有没有接通,一般接通都是会有黄绿色色闪烁。
一、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 number\n");
//设置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 number\n");break;
}
return 0;
}
2. 调用驱动程序的应用程序
//相关头文件的引用
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
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服务器
cp led.ko /tftpboot/
cp test_led /tftpboot/
利用xshell超级终端,在目标机上接收led.ko和test_led文件,并且加载驱动程序
手动创建led设备节点,并给test_led文件可执行权限
实验现象:
本文来自博客园,作者:静候佳茵,转载请注明原文链接:https://www.cnblogs.com/hitwherznchjy/p/16243133.html