S3C2410——LED燈實驗
一、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文件可執行許可權
實驗現象: