实验 83驱动程序的动态加载.docx
- 文档编号:4403380
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:15
- 大小:681.08KB
实验 83驱动程序的动态加载.docx
《实验 83驱动程序的动态加载.docx》由会员分享,可在线阅读,更多相关《实验 83驱动程序的动态加载.docx(15页珍藏版)》请在冰豆网上搜索。
实验83驱动程序的动态加载
实验8-3驱动程序加载实验
【实验目的】
Ø掌握驱动程序加载方法。
【实验步骤】
第一步:
利用vi编辑器,编写一个xsb_led.c驱动代码;
1、增加驱动所需的头文件和变量
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineDEVICE_NAME"xsb_Led"
#defineSEG_LED0x10500000
#defineLed_MAJOR60
staticcharLed_Buff=0x0;
unsignedlong*Led_Address;
staticstructclass_simple*led_class;
2、控制LED点亮函数
staticvoidUpdateled(void)
{
writew(Led_Buff,Led_Address);
return;
}
3、实现LED驱动写操作函数
staticssize_tLed_write(structfile*file,constchar*buffer,size_tcount,loff_t*ppos)
{
if(count!
=1)
{
printk(KERN_EMERG"thecountofinputisnotone!
!
");
return0;
}
copy_from_user(&Led_Buff,buffer,1);
Updateled();
return1;
}
4、实现LED驱动的打开、释放函数以及文件操作结构体
staticintLed_open(structinode*inode,structfile*filp)
{
return0;
}
staticintLed_release(structinode*inode,structfile*filp)
{
return0;
}
staticstructfile_operationsLed_fops={
open:
Led_open,
write:
Led_write,
release:
Led_release,
owner:
THIS_MODULE,
};
5、实现LED驱动初始化函数
staticint__initLed_init(void)
{
intret;
interr=0;
Led_Address=ioremap(SEG_LED,4);
ret=register_chrdev(Led_MAJOR,DEVICE_NAME,&Led_fops);
if(ret<0){
printk(DEVICE_NAME"can'tgetmajornumber\n");
returnret;
}
led_class=class_simple_create(THIS_MODULE,DEVICE_NAME);
if(IS_ERR(led_class)){
err=PTR_ERR(led_class);
gotoout_chrdev;
}
class_simple_device_add(led_class,MKDEV(Led_MAJOR,0),NULL,DEVICE_NAME);
gotoOUT;
out_chrdev:
unregister_chrdev(Led_MAJOR,DEVICE_NAME);
OUT:
returnerr;
}
6、实现七段数码管驱动模块退出函数与模块描述
staticvoid__exitLed_exit(void)
{
iounmap(Led_Address);
class_simple_device_remove(MKDEV(Led_MAJOR,0));
class_simple_destroy(led_class);
unregister_chrdev(Led_MAJOR,DEVICE_NAME);
}
module_init(Led_init);
module_exit(Led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dr.Ben.li");
MODULE_DESCRIPTION("ThisisaLeddriverdemo");
第二步:
将xsb_led.c源码文件复制到目标平台linux内核的driver/char目录下;
【图8-3-1】
第三步:
修改driver/char目录下的Makefile文件,增加如下项并保存:
obj-$(CONFIG_XSB_LED)+=xsb_led.o
【图8-3-2】
第四步:
修改driver/char目录下的Kconfig文件,增加如下项并保存:
configXSB_LED
tristate"LedShiftdriverforEELiodBoard"
dependsonMACH_XSBASE270EDR
help
ThisisLedshiftdemodriverforEELiod
【图8-3-3】
第五步:
在目标平台的linux根目录中运行makemenuconfig,在Characterdevices下选中<*>LedShiftdriverforEELiodBoard,使其编译到内核。
【图8-3-4】
第六步:
在目标平台的linux根目录中运行makezImage命令,重新编译内核
【图8-3-5】
第七步:
根据内核下载和烧写方法将新编译好的内核镜像zImage下载到目标平台,并重新启动系统。
【图8-3-6】
第八步:
系统启动后,在目标平台中利用cat/proc/deveces命令查看驱动是否已经加载。
【图8-3-7】
第九步:
在目标平台中利用mknod命令新建一个设备文件
Mknod/dev/xsb_Ledc600
【图8-3-8】
第一十步:
利用vi编辑器,编写一个Led驱动测试代码led_test.c
/************************************************
*************************************************/
#include
#include
//#include
#include
#include
#include
#include
#include
#include
#defineLED_DEV"/dev/xsb_Led"
boolbstop=false;
intfd;
voiddisplay_menu()
{
printf("*****ChoiceMenu*********\n");
printf("[0]OpenDevice\n");
printf("[1]LeftShift\n");
printf("[2]RightShift\n");
printf("[T]StopShift\n");
printf("[C]CloseDevice\n");
printf("[x]ExitTest\n");
printf("***********************\n");
printf("Pleaseinputyourchoise:
");
}
void*Led_Right_Shift(void*data)
{
unsignedcharledvalue=0x01;
unsignedchartmp;
inti=0;
while
(1){
for(i=0;i<8;i++){
if(bstop){
bstop=false;
return;
}
tmp=~ledvalue;
write(fd,&tmp,1);
sleep
(1);
if(i<7)
ledvalue=ledvalue<<1;
else
ledvalue=0x01;
}
}
}
void*Led_Left_Shift(void*data)
{
unsignedcharledvalue=0x80;
unsignedchartmp;
inti=0;
while
(1){
for(i=0;i<8;i++){
if(bstop){
bstop=false;
return;
}
tmp=~ledvalue;
write(fd,&tmp,1);
sleep
(1);
if(i<7)
ledvalue=ledvalue>>1;
else
ledvalue=0x80;
}
}
}
intmain(intargc,char**argv)
{
fd=-1;
pthread_tth_shift=0;
charch=0x00;
display_menu();
void*retval;
while
(1){
ch=getchar();
switch(ch){
case'0':
if(fd>0)
printf("##LedDevicehasbeenopen##%d\n",fd);
else{
fd=open(LED_DEV,O_RDWR);
if(fd<0)
printf("####LEDDeviceopenFail####\n");
else
printf("####LEDDeviceopenSuccess####%d\n",fd);
}
display_menu();
break;
case'1':
if(fd){
if(th_shift){
bstop=true;
pthread_join(th_shift,&retval);
}
bstop=false;
pthread_create(&th_shift,NULL,Led_Right_Shift,NULL);
}
else
printf("Thedeviceisnotopen!
!
");
display_menu();
break;
case'2':
if(fd){
if(th_shift){
bstop=true;
pthread_join(th_shift,&retval);
}
bstop=false;
pthread_create(&th_shift,NULL,Led_Left_Shift,NULL);
}
else
printf("Thedeviceisnotopen!
!
");
display_menu();
break;
case't':
case'T':
bstop=true;
display_menu();
break;
case'c':
case'C':
if(fd)
close(fd);
display_menu();
bstop=false;
break;
case'x':
case'X':
exit
(1);
default:
break;
}
}
return(0);
}
第一十一步:
利用vi编辑器,编写一个用于编译led_test.c的Makefile文件;其中CC=/opt/xscalev1/bin/arm-linux-gcc为交叉编译工具所在的路径位置,INCLUDEDIR=/opt/xscalev1/arm-linux/include为头文件所在的路径,因为程序中采用了线程编程方法,所有必须链接线程库,即-lpthread。
CC=/opt/arm-linux/bin/arm-linux-gcc
INCLUDEDIR=/opt/arm-linux/arm-linux/include
CFLAGS=-I..-I$(INCLUDEDIR)-lpthread
TARGET_TEST=led_test
OBJ_TEST=$(TARGET_TEST)
SOURCE_TEST=$(TARGET_TEST).c
ALL:
$(CC)$(CFLAGS)-o$(OBJ_TEST)$(SOURCE_TEST)
clean:
rm-rf$(OBJ_TEST)
第一十二步:
运行make命令对led_test.c源代码进行编译,用ls命令查看编译后的结果,利用file命令查看seg_test文件的格式,应为ARM格式的ELF文件。
【图8-3-9】
第一十三步:
在Linux操作系统下输入minicom,配置串口参数,然后打开EELiod目标平台电源,平台启动后,按CTRL+A,然后按Z,启动串口命令界面,按S键,选择zmodem传输方式;按回车
【图8-3-10】
第一十四步:
选择PC平台中驱动测试文件led_test,并按回车键。
下载选中的文件,文件下载完毕后按ESC键,退出串口传输,返回目标平台界面。
第一十五步:
在目标平台终端运行Led驱动测试程序led_test,在平台终端将显示驱动测试程序菜单。
【图8-3-11】
第一十六步:
在平台终端显示驱动测试程序菜单输入提示输入数字“0”。
驱动测试程序将通过open函数打开设备文件,同时内核调用驱动程序的xxx_open函数,在平台终端可以查看驱动和测试程序调试输出信息。
【图8-3-12】
第一十七步:
在平台终端显示驱动测试程序菜单输入提示分别输入数字“1”、“2”、查看平台LED的显示情况。
【图8-3-13】
第一十八步:
在Led灯流水点亮时,在平台终端显示驱动测试程序菜单输入“t”或“T”,查看Led的显示情况。
【图8-3-14】
第一十九步:
在平台终端显示驱动测试程序菜单输入“x”或“X”,退出系统测试。
【图8-3-15】
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 83 驱动程序的动态加载 驱动程序 动态 加载