1、嵌入式报告 08210929嵌入式实验报告 姓名:刘晓松 学号:08210929 班级:2008211202 专业:电子信息科学与技术一 实验目的 通过宿主 PC 端与 PXA270-EP 目标板连接并且进行相关实验,了解相关嵌入式开发环境的搭建,以及相关相关底层驱动程序的编写与设置。实验内容一嵌入式基本实验1 基本实验 linux开发环境的搭建,通讯配置通过本实验的操作,我将宿主 PC 端与 PXA270-EP 目标板正确的连接起来。并且参照本教程给出的步骤,一步一步地完成 RedHat 9.0 操作系统的安装。此次试验属于所有试验的基础部分,通过实际操作,我了解各种接口的链接,linux的
2、安装过程,为以后的各种试验打下了坚实的基础。2.minicom与超级终端的建立通过本实验的操作,我建立起了宿主 PC 机与 PXA270 目标板的通信环境。在此次试验中,我并没有使用minicom,而是使用了windows的超级终端,在这一过程,我了解到了超级终端作为电脑与各种硬件平台的通信作用,通过配置相关参数,我渐渐了解到了串口通信,并且逐步建立起了宿主PC与PXA270目标板的通信环境。3.实验五 在此次试验中,我了解并设置了TFTP服务。TFTP 的全称是 Trivial File Transfer Protocol,即简单文件传输协议。使用此服务传送 文件时没有数据校验、密码验证,非
3、常适合小型文件的传输。在通过 TFTP 传送文件时, 需要服务端和客户端,对于我们嵌入式系统来讲,服务端就是我们的宿主机,客户端就是那个PXA270的系统板。通过本实验的操作,我就利用已经启动好的 tftp 服务来完成宿主 PC 机与PXA270-EP 目标机之间的文件传输了。4.实验六,在此次试验中,我了解并掌握了NFS服务相关操作。NFS(Network File System)指网络文件系统,是 Linux 系统中经常使用的一种服务,NFS 是一个 RPC service,很像 windows 中的文件共享服务。它的设计是为了在不同的系统间使用, 所 以它的通讯协议设计与主机及作业系统无
4、关。当使用者想用远端档案时只要用mount就可把 remote 档案系统挂接在自己的档案系统之下,使得远端的档案在使用上和 local 的档案没两样。按照书中实验步骤,我让宿主 PC 机通过网络挂接(mount)到 PXA270-EP 目标板的相应文件夹下。我们可以看到,在 Linux 下的实验,我们使用 超级终端 通 过串口给 PXA270-EP 目标板发送指令,而通过网络传送数据。 此次试验是最为重要的一次试验,是以后所有试验的基础,因为宿主PC与PXA270目标板的所有数据传输,相关IO操作,都是以NFS服务为基础的。5.helloworld的试验,在这一次试验中,我通过NFS试验成功将
5、宿主机挂载到PXA270上,并且第一次正面接触嵌入式 Linux 的开发,第一次编写嵌入式系统的应用程序,亲身实践一下按照书上的步骤,一步一步地完成实验,编写、编译并运行 HelloWorld 程序。我们在 PC 上编辑、编译一个应用程序,并且在嵌入式系统上运行和调 试它。这个程序虽然简单,但是它是典型嵌入式程序开发的一个反映。通过这个实验,可以对 嵌入式开发有一个更为直观的认识。8掌握编译 XSCALE 系统 Bootloader 的过程。BOOTLOADER 是嵌入式系统的基本部分,负责了系统的启动与初始化,熟悉理解它的工 作原理与使用是进入嵌入式世界的一个前提。(了解 BLOB 的原理,
6、可以参考第三章的“3.5.2 启 动引导 Boot Loader”部分)编译 BOOTLOADER 是非常基本的实验,如果要深入掌握嵌入式的 开发,一定要能够熟练掌握此实验。9掌握编译 ARM 系统内核的过程。本实验我们编译了 Linux 内核。Linux 内核是相当复杂的,若您有兴趣的话,你可以有选择性的阅读我们提供给您的 Linux 源码。二,嵌入式基本接口试验 (驱动试验)实验12:在本次试验中,动手实践一个简单的字符型设备驱动程序。在这一过程中,我了解并学习 Linux 驱动程序构架,掌握并学习在应用程序中调用驱动。下面是相关的驱动程序,以及测试程序。#include #include
7、 #include #include #include #include #include /相关引用的库的声明/ HELLO DEVICE MAJOR#define SIMPLE_HELLO_MAJOR 96#define OURS_HELLO_DEBUG#define VERSION PXA2700EP-hello-V1.00-060530 void showversion(void) printk(*n);printk(t %s tn, VERSION);printk(*nn);/ - READ -/ Read 入口点.从设备上读数据.对于有缓冲区的 I/O 操作,一般是从缓冲区里读数据
8、.对字符特别设备文件进行读操作将调用 read 子程序ssize_t SIMPLE_HELLO_read (struct file * file ,char * buf, size_t count, loff_t * f_ops) #ifdef OURS_HELLO_DEBUGprintk (SIMPLE_HELLO_read -kernel-n);#endifreturn count;/ - WRITE -/ Write 入口点.往设备上写数据.对于有缓冲区的 I/O 设备操作,一般是把数据写入缓冲区里.对字符特别设备文件进行写操作将调用 write 子程序ssize_t SIMPLE_HE
9、LLO_write (struct file * file ,const char * buf, size_t count, loff_t * f_ops) #ifdef OURS_HELLO_DEBUGprintk (SIMPLE_HELLO_write -kernel-n);#endif return count;/ - IOCTL -/ ioctl 入口点.执行读,写之外的操作,实现对设备的控制ssize_t SIMPLE_HELLO_ioctl (struct inode * inode ,struct file * file, unsigned int cmd, long data)
10、 #ifdef OURS_HELLO_DEBUGprintk (SIMPLE_HELLO_ioctl -kernel-n);#endif return 0;/ - OPEN -/ open 入口点.打开设备准备 I/O 操作.对字符特别设备文件进行打开操作,都会调用设备 的 open 入口点。open 子程序必须对将要进行的 I/O 操作做好必要的准备工作,如清除缓冲区等.如 果设备是独占的,即同一时刻只能有一个程序访问此设备,则 open 子程序必须设置一些标志以表示设备处于忙状态.ssize_t SIMPLE_HELLO_open (struct inode * inode ,struct
11、 file * file) #ifdef OURS_HELLO_DEBUGprintk (SIMPLE_HELLO_open -kernel-n);#endif MOD_INC_USE_COUNT; return 0;/ - RELEASE/CLOSE -/ Close 入口点.关闭一个设备.当最后一次使用设备终结后,调用 close 子程序.独占设备必 须标记设备可再次使用ssize_t SIMPLE_HELLO_release (struct inode * inode ,struct file * file) #ifdef OURS_HELLO_DEBUGprintk (SIMPLE_H
12、ELLO_release -kernel-n);#endif MOD_DEC_USE_COUNT; returnstruct file_operations HELLO_ctl_ops = open: SIMPLE_HELLO_open, read: SIMPLE_HELLO_read,write: SIMPLE_HELLO_write, ioctl: SIMPLE_HELLO_ioctl, release: SIMPLE_HELLO_release,;/ - INIT -static intinit HW_HELLO_CTL_init(void) int ret = -ENODEV;ret
13、= devfs_register_chrdev(SIMPLE_HELLO_MAJOR, hello_ctl, &HELLO_ctl_ops);showversion();if( ret 0 ) printk ( pxa270 init_module failed with %dn -kernel-, ret);return ret;else printk( pxa270 hello_driver register success! -kernel-n);return ret;static intinit pxa270_HELLO_CTL_init(void) int ret = -ENODEV
14、;#ifdef OURS_HELLO_DEBUGprintk (pxa270_HELLO_CTL_init -kernel-n);#endifret = HW_HELLO_CTL_init();if (ret)return ret;return 0;static voidexit cleanup_HELLO_ctl(void) #ifdef OURS_HELLO_DEBUGprintk (cleanup_HELLO_ctl -kernel-n);#endifdevfs_unregister_chrdev (SIMPLE_HELLO_MAJOR, hello_ctl );MODULE_DESCR
15、IPTION(simple hello driver module); MODULE_AUTHOR(liduo); MODULE_LICENSE(GPL); module_init(pxa270_HELLO_CTL_init); module_exit(cleanup_HELLO_ctl);实验总结:通过本实验的操作,编写的测试程序能够正常的对驱动程序进行操作,就表示驱动程 序功能正常。试验十三:GPIO的使用编写第一个针对实际硬件的驱动程序,进一步了解驱动程序构架。凡是操作系统控制外部设备,即使是最简单的硬件电路,也是需要驱动的。本实验涉及的 外部硬件只有电阻,蓝色发光二极管。我们使用自己编
16、写得驱动程序与应用程序控制 GPIO96 的电平。通过 LED 的亮灭来判断,是否 CPU 做出了正确的响应以下是相关驱动程序,测试程序及其相关注释编写GPIO驱动程序 使用GPIO控制led灯的亮与灭。 先编写对应的驱动程序和makefile文件,然后交叉编译,用串口登录目标机,挂载上之后,便可以进行读写操作。 通过控制CPU的GPIO寄存器,来实现GPIO的电平控制。 控制GPIO的寄存器主要有:GPDR:IO方向控制器.GPCR:清楚GPIO对应位。CPSR:设置GPIO对应位。补充添加代码:1。write函数/ - WRITE - 57 ssize_t SIMPLE_GPIO_LED_
17、write (struct file * file ,const char * buf, size_t count, loff_t * f_ops) #ifdef OURS_GPIO_LED_DEBUG printk (SIMPLE_GPIO_LED_write -kernel-n); #endif return count;2。open函数/ - OPEN -ssize_t SIMPLE_GPIO_LED_open (struct inode * inode ,struct file * file) #ifdef OURS_GPIO_LED_DEBUG printk (SIMPLE_GPIO
18、_LED_open -kernel-n); #endif MOD_INC_USE_COUNT; return 0;3。ops/ -struct file_operations GPIO_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,op
19、s的相关补充代码已经填写完毕。Write,read,open,release只有基本操作和调试信息。Ioctl函数为GPIO口的控制函数,其代码如下:ssize_t SIMPLE_GPIO_LED_ioctl (struct inode * inode ,struct file * file, unsigned int cmd, long data) #ifdef OURS_GPIO_LED_DEBUG printk (SIMPLE_GPIO_LED_ioctl -kernel-n); /调试信息 #endif switch (cmd) /io控制,cmd为输入的命令 case LED_ON
20、: GPCR3 |= 0x1;break;/通过修改寄存器控制GPIO口电平 case LED_OFF: GPSR3 |= 0x1;break; default : printk (lcd control : no cmd run -kernel- n); return (-EINVAL); /非法命令 return 0; struct file_operations GPIO_LED_ctl_ops建立操作映射,注册借口函数。为应用层提供统一的接口。下面的部分包括初始化函数,卸载函数初始化函数如下:static int _init pxa270_GPIO_LED_CTL_init(void)
21、 int ret = -ENODEV; /初始化失败将返回次错误信息 /调试信息 #ifdef OURS_GPIO_LED_DEBUG printk (pxa270_GPIO_LED_CTL_init -kernel-n); #endif/调用HW_GPIO_LED_CTL_init函数完成初始化ret = HW_GPIO_LED_CTL_init(); if (ret) return ret; return 0;该函数通过调用HW_GPIO_LED_CTL_init函数实现初始化,HW_GPIO_LED_CTL_init函数相关注释如下:static int _init HW_GPIO_LE
22、D_CTL_init(void) int ret = -ENODEV; printk(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhnn); showversion(); /显示版本信息 / init GPIO /初始化相关寄存器数值,继而控制初始化输出 GPDR3 |= 0x00000001; / 设置输出端口模式 GPSR3 |= 0x00000001; / 关闭led灯 /调试信息,显示寄存器信息 #ifdef OURS_GPIO_LED_DEBUG printk ( GPLR3=%x n,GPLR3); printk ( GPDR3=%x n,GPDR3); #endif
23、/注册设备 ret = devfs_register_chrdev(SIMPLE_GPIO_LED_MAJOR/主设备号 ,gpio_led_ctl, &GPIO_LED_ctl_ops/函数映射结构体); if( ret 0 ) printk ( pxa270: init_module failed with %dn -kernel-, ret); return ret; else printk( pxa270 gpio_led_driver register success! -kernel-n); return ret;清除卸载函数为cleanup_GPIO_LED_ctl,其代码实现如
24、下:static void _exit cleanup_GPIO_LED_ctl(void) #ifdef OURS_GPIO_LED_DEBUG printk (cleanup_GPIO_LED_ctl -kernel-n); #endif /注销主设备号,释放设备 devfs_unregister_chrdev (SIMPLE_GPIO_LED_MAJOR, gpio_led_ctl ); 测试函数:通过调用ioctl函数实现对led灯的控制。int main(void) int fd; int ret; char *i; printf(nstart gpio_led_driver tes
25、tnn); fd = open(DEVICE_NAME, O_RDWR); /系统通过ops调用SIMPLE_GPIO_LED_open函数打开设备 printf(fd = %dn,fd); if (fd = -1) printf(open device %s errorn,DEVICE_NAME); else /通过调用SIMPLE_GPIO_LED_ioctl函数控制led灯 /主循环 while(1) ioctl(fd,LED_OFF); sleep(1); / 修改sleep时间即可改变led灯点亮的时间,如sleep(7)即灭7秒 ioctl(fd,LED_ON); sleep(1)
26、;/ sleep(5) 亮5秒 / close ret = close(fd); / printf (ret=%dn,ret); printf (close gpio_led_driver testn); return 0;/ end main实验十三是通过操作 CPU 的 GPIO 端口来控制 LED 的亮灭,通过该实验基本掌握了驱动模块的结构和一些函数的实现,如ioctl函数。十四 中断试验与中断有关的函数说明:(1)request_int函数:函数原型:request_int(unsigned int irq,void (handler *)(int,void*,struct pt_re
27、gs *), unsigned long irg_flags,const char * 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(unsigned i
28、nt irq, 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
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1