嵌入式报告 08210929文档格式.docx
《嵌入式报告 08210929文档格式.docx》由会员分享,可在线阅读,更多相关《嵌入式报告 08210929文档格式.docx(35页珍藏版)》请在冰豆网上搜索。
![嵌入式报告 08210929文档格式.docx](https://file1.bdocx.com/fileroot1/2023-1/8/cb8b4581-b571-4c60-8349-41577d339822/cb8b4581-b571-4c60-8349-41577d3398221.gif)
就可把remote档案系统挂接在自己的档案系统之下,使得远端的档案在使用上和local的档案没两样。
按照书中实验步骤,我让宿主PC机通过网络挂接(mount)到PXA270-EP目标板的相应文件夹下。
我们可以看到,在Linux下的实验,我们使用超级终端通过串口给PXA270-EP目标板发送指令,而通过网络传送数据。
此次试验是最为重要的一次试验,是以后所有试验的基础,因为宿主PC与PXA270目标板的所有数据传输,相关IO操作,都是以NFS服务为基础的。
5.helloworld的试验,在这一次试验中,我通过NFS试验成功将宿主机挂载到PXA270上,并且第一次正面接触嵌入式Linux的开发,第一次编写嵌入式系统的应用程序,亲身实践一下
按照书上的步骤,一步一步地完成实验,编写、编译并运行HelloWorld程序。
我们在PC上编辑、编译一个应用程序,并且在嵌入式系统上运行和调试它。
这个程序虽然简单,但是它是典型嵌入式程序开发的一个反映。
通过这个实验,可以对嵌入式开发有一个更为直观的认识。
8掌握编译XSCALE系统Bootloader的过程。
BOOTLOADER是嵌入式系统的基本部分,负责了系统的启动与初始化,熟悉理解它的工作原理与使用是进入嵌入式世界的一个前提。
(了解BLOB的原理,可以参考第三章的“3.5.2启动引导BootLoader”部分)编译BOOTLOADER是非常基本的实验,如果要深入掌握嵌入式的开发,一定要能够熟练掌握此实验。
9掌握编译ARM系统内核的过程。
本实验我们编译了Linux内核。
Linux内核是相当复杂的,若您有兴趣的话,你可以有选择性的阅读我们提供给您的Linux源码。
二,嵌入式基本接口试验(驱动试验)
实验12:
在本次试验中,动手实践一个简单的字符型设备驱动程序。
在这一过程中,我了解并学习Linux驱动程序构架,掌握并学习在应用程序中调用驱动。
下面是相关的驱动程序,以及测试程序。
#include<
linux/config.h>
linux/kernel.h>
linux/sched.h>
linux/timer.h>
linux/init.h>
linux/module.h>
asm/hardware.h>
//相关引用的库的声明
//HELLODEVICEMAJOR
#defineSIMPLE_HELLO_MAJOR96
#defineOURS_HELLO_DEBUG
#defineVERSION"
PXA2700EP-hello-V1.00-060530"
voidshowversion(void)
{printk("
*********************************************\n"
);
printk("
\t%s\t\n"
VERSION);
*********************************************\n\n"
}
//-------------------READ-----------------------
//Read入口点.从设备上读数据.对于有缓冲区的I/O操作,一般是从缓冲区里读数据.对字符特别设备文件进行读操作将调用read子程序
ssize_tSIMPLE_HELLO_read(structfile*file,char*buf,size_tcount,loff_t*f_ops)
{#ifdefOURS_HELLO_DEBUG
printk("
SIMPLE_HELLO_read[--kernel--]\n"
#endif
returncount;
//-------------------WRITE-----------------------
//Write入口点.往设备上写数据.对于有缓冲区的I/O设备操作,一般是把数据写入缓冲区里.对字符特别设备文件进行写操作将调用write子程序
ssize_tSIMPLE_HELLO_write(structfile*file,constchar*buf,size_tcount,loff_t*f_ops)
SIMPLE_HELLO_write[--kernel--]\n"
#endifreturncount;
//-------------------IOCTL-----------------------
//ioctl入口点.执行读,写之外的操作,实现对设备的控制
ssize_tSIMPLE_HELLO_ioctl(structinode*inode,structfile*file,unsignedintcmd,longdata)
SIMPLE_HELLO_ioctl[--kernel--]\n"
#endifreturn0;
//-------------------OPEN------------------------
//open入口点.打开设备准备I/O操作.对字符特别设备文件进行打开操作,都会调用设备的open入口点。
open子程序必须对将要进行的I/O操作做好必要的准备工作,如清除缓冲区等.如果设备是独占的,即同一时刻只能有一个程序访问此设备,则open子程序必须设置一些标志以表示设备处于忙状态.
ssize_tSIMPLE_HELLO_open(structinode*inode,structfile*file)
SIMPLE_HELLO_open[--kernel--]\n"
#endifMOD_INC_USE_COUNT;
return0;
//-------------------RELEASE/CLOSE---------------
//Close入口点.关闭一个设备.当最后一次使用设备终结后,调用close子程序.独占设备必须标记设备可再次使用
ssize_tSIMPLE_HELLO_release(structinode*inode,structfile*file)
SIMPLE_HELLO_release[--kernel--]\n"
#endifMOD_DEC_USE_COUNT;
return
structfile_operationsHELLO_ctl_ops={open:
SIMPLE_HELLO_open,read:
SIMPLE_HELLO_read,
write:
SIMPLE_HELLO_write,ioctl:
SIMPLE_HELLO_ioctl,release:
SIMPLE_HELLO_release,
};
//-------------------INIT------------------------
staticint
initHW_HELLO_CTL_init(void)
{intret=-ENODEV;
ret=devfs_register_chrdev(SIMPLE_HELLO_MAJOR,"
hello_ctl"
&
HELLO_ctl_ops);
showversion();
if(ret<
0)
{printk("
pxa270init_modulefailedwith%d\n[--kernel--]"
ret);
returnret;
else
pxa270hello_driverregistersuccess!
!
[--kernel--]\n"
initpxa270_HELLO_CTL_init(void)
{intret=-ENODEV;
#ifdefOURS_HELLO_DEBUG
pxa270_HELLO_CTL_init[--kernel--]\n"
ret=HW_HELLO_CTL_init();
if(ret)
return0;
staticvoid
exitcleanup_HELLO_ctl(void)
cleanup_HELLO_ctl[--kernel--]\n"
devfs_unregister_chrdev(SIMPLE_HELLO_MAJOR,"
);
MODULE_DESCRIPTION("
simplehellodrivermodule"
MODULE_AUTHOR("
liduo"
MODULE_LICENSE("
GPL"
module_init(pxa270_HELLO_CTL_init);
module_exit(cleanup_HELLO_ctl);
实验总结:
通过本实验的操作,编写的测试程序能够正常的对驱动程序进行操作,就表示驱动程序功能正常。
试验十三:
GPIO的使用
编写第一个针对实际硬件的驱动程序,进一步了解驱动程序构架。
凡是操作系统控制外部设备,即使是最简单的硬件电路,也是需要驱动的。
本实验涉及的外部硬件只有电阻,蓝色发光二极管。
我们使用自己编写得驱动程序与应用程序控制GPIO96的电平。
通过LED的亮灭来判断,是否CPU做出了正确的响应
以下是相关驱动程序,测试程序及其相关注释
编写GPIO驱动程序
使用GPIO控制led灯的亮与灭。
先编写对应的驱动程序和makefile文件,然后交叉编译,用串口登录目标机,挂载上之后,便可以进行读写操作。
通过控制CPU的GPIO寄存器,来实现GPIO的电平控制。
控制GPIO的寄存器主要有:
GPDR:
IO方向控制器.
GPCR:
清楚GPIO对应位。
CPSR:
设置GPIO对应位。
补充添加代码:
1。
write函数
57ssize_tSIMPLE_GPIO_LED_write(structfile*file,constchar*buf,size_tcount,loff_t*f_ops)
{
#ifdefOURS_GPIO_LED_DEBUG
printk("
SIMPLE_GPIO_LED_write[--kernel--]\n"
#endif
returncount;
2。
open函数
ssize_tSIMPLE_GPIO_LED_open(structinode*inode,structfile*file)
SIMPLE_GPIO_LED_open[--kernel--]\n"
MOD_INC_USE_COUNT;
3。
ops
//-------------------------------------------------
structfile_operationsGPIO_LED_ctl_ops={open:
SIMPLE_GPIO_LED_open,
read:
SIMPLE_GPIO_LED_read,
write:
SIMPLE_GPIO_LED_write,
ioctl:
SIMPLE_GPIO_LED_ioctl,
release:
SIMPLE_GPIO_LED_release,}
建立操作映射,注册借口函数。
为应用层提供统一的接口。
详细说明:
Write,open,ops的相关补充代码已经填写完毕。
Write,read,open,release只有基本操作和调试信息。
Ioctl函数为GPIO口的控制函数,其代码如下:
ssize_tSIMPLE_GPIO_LED_ioctl(structinode*inode,structfile*file,unsignedintcmd,longdata)
printk("
SIMPLE_GPIO_LED_ioctl[--kernel--]\n"
//调试信息
switch(cmd)//io控制,cmd为输入的命令
{
caseLED_ON:
{GPCR3|=0x1;
break;
}//通过修改寄存器控制GPIO口电平
caseLED_OFF:
{GPSR3|=0x1;
}
default:
{printk("
lcdcontrol:
nocmdrun[--kernel--]\n"
return(-EINVAL);
//非法命令}
}
return0;
structfile_operationsGPIO_LED_ctl_ops
下面的部分包括初始化函数,卸载函数
初始化函数如下:
staticint__initpxa270_GPIO_LED_CTL_init(void)
intret=-ENODEV;
//初始化失败将返回次错误信息
#ifdefOURS_GPIO_LED_DEBUG
pxa270_GPIO_LED_CTL_init[--kernel--]\n"
//调用HW_GPIO_LED_CTL_init函数完成初始化
ret=HW_GPIO_LED_CTL_init();
if(ret)
returnret;
该函数通过调用HW_GPIO_LED_CTL_init函数实现初始化,HW_GPIO_LED_CTL_init函数相关注释如下:
staticint__initHW_GPIO_LED_CTL_init(void)
printk("
hhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n\n"
showversion();
//显示版本信息
//initGPIO
//初始化相关寄存器数值,继而控制初始化输出
GPDR3|=0x00000001;
//设置输出端口模式
GPSR3|=0x00000001;
//关闭led灯
//调试信息,显示寄存器信息
GPLR3=%x\n"
GPLR3);
GPDR3=%x\n"
GPDR3);
//注册设备
ret=devfs_register_chrdev(SIMPLE_GPIO_LED_MAJOR//主设备号,"
gpio_led_ctl"
GPIO_LED_ctl_ops//函数映射结构体);
if(ret<
pxa270:
init_modulefailedwith%d\n[--kernel--]"
returnret;
else
printk("
pxa270gpio_led_driverregistersuccess!
清除卸载函数为cleanup_GPIO_LED_ctl,其代码实现如下:
staticvoid__exitcleanup_GPIO_LED_ctl(void)
cleanup_GPIO_LED_ctl[--kernel--]\n"
//注销主设备号,释放设备
devfs_unregister_chrdev(SIMPLE_GPIO_LED_MAJOR,"
测试函数:
通过调用ioctl函数实现对led灯的控制。
intmain(void)
intfd;
intret;
char*i;
printf("
\nstartgpio_led_drivertest\n\n"
fd=open(DEVICE_NAME,O_RDWR);
//系统通过ops调用SIMPLE_GPIO_LED_open函数打开设备
fd=%d\n"
fd);
if(fd==-1)
opendevice%serror\n"
DEVICE_NAME);
//通过调用SIMPLE_GPIO_LED_ioctl函数控制led灯
//主循环
while
(1)
{ioctl(fd,LED_OFF);
sleep
(1);
//修改sleep时间即可改变led灯点亮的时间,如sleep(7)即灭7秒
ioctl(fd,LED_ON);
//sleep(5)亮5秒
}
//close
ret=close(fd);
//
printf("
ret=%d\n"
ret);
closegpio_led_drivertest\n"
}//endmain
实验十三是通过操作CPU的GPIO端口来控制LED的亮灭,通过该实验基本掌握了驱动模块的结构和一些函数的实现,如ioctl函数。
十四中断试验
与中断有关的函数说明:
(1)request_int函数:
函数原型:
request_int(unsignedintirq,void(handler*)(int,void*,structpt_regs*),
unsignedlongirg_flags,constchar*devname,void*dev_id);
该函数有5个参数:
(a)irq:
外设使用的中断号。
(b)handler中断服务程序的函数入口
(c)irg_flag:
设备驱动程序指定的中断请求类型标志,它可以是一下三个值的或:
SA_SHIRQ,SA_INTERRUPT和SA_SAMPLE_RANDOM
(d)devname指针,设备名字字符串
(e)dev_id:
指向全局唯一的设备标识ID,这是一个void类型的指针,可提供设备驱动程序的自行解释
(2)free_irq函数:
free_irq(unsignedintirq,void*dev_id)
中断驱动模块的基本框架和GPIO的驱动模块基本相同,同样是通过module_init和module_exit来分别映射初始化和卸载模块。
具体实现如下:
module_init(pxa270_HELLO_CTL_init);
module_exit(cleanup_HELLO_ctl);
和GPIO驱动相同,加载模块时,系统调用pxa270_HELLO_CTL_init函数初始化模块;
卸载模块时,调用cleanup_HELLO_ctl函数来卸载模块,并释放资源。
中断驱动的初始化与GPIO模块略有不同,除了要注册主设备好之外,还要注册中断向量和中断处理函数。
pxa270_HELLO_CTL_init通过调用HW_HELLO_CTL_init函数完成模块初始化。
pxa27