嵌入式大作业. 下载本文

2015嵌入式大作业

一、叙述JTAG接口在嵌入式开发中的作用。

JTAG是一种国际标准测试协议主要用于芯片内部测试,JTAG接口的主要作用如下所述:

? 它最初用来对电路和芯片进行边界扫描测定,它的基本原理是在器件内部定义一个测试是访问口(Test Access Port),通过JTAG专用的测试工具对器件内部节点进行测试。通过电路的边界扫描测试技术,用具有边界扫描功能的芯片构成的印制板电路,可通过相应的测试设备检测芯片功能,检测电路连接的正确性同时检测它是否有预定的逻辑功能,从而对这块印制电路进行故障检测和故障定位。

? JTAG接口可以对目标板进行测试,还可以对目标板系统的存储单元编程,经常通过JTAG接口直接烧写嵌入式系统Flash存储器。 ? JTAG的引脚定义

1. TCK为TAP提供一个独立基本的时钟信号,TAP的所有操作都是通过这个时钟信号来驱动的。

2. TMS用来控制TAP状态机的转换,通过TMS新号可以控制TAP在不同的状态间转换,TMS信号在TCK信号的上升沿有效。

3. TDI是数据输入的接口,所有输入到特定寄存器的数据都要通过TDI一位一位串行输出。

4. TDO数据输出的接口所有从特定寄存器输出的数据都要通过TDO一位一位串行输出。

5. TRST可以用来对TAP Controller进行复位,该信号线可选,TMS也可以对其进行复位。

6. VTREF接口信号电平参考电压一般直接接V(supply),这个可以用来确定ARM的JTAG的接口逻辑电平。 7. RTCK可选项,由目标端反馈给仿真器的时钟信号,用来同步TCK信号的产生,不使用时直接接地。

8. System Reset可选项,与目标板上的系统复位信号相连,可以直接对目标系统复位,同时可以检测目标系统的复位情况,为了防止误触发应在目标端加上适当的上位电阻。

9. USER IN用户自定义输入,可以接到一个IO口上,用来接收上位机的控制。

10. USER OUT 用户自定义输出,可以接到一个IO口上,用来向上位机反馈一个状态。

二、叙述嵌入式平台的搭建过程,以linux为例。 1) 一:建立宿主机开发环境

建立交叉编译的环境即在宿主机上安装与开发板相应的编译器及库函数,以便能够在宿主机上应用开发工具编译在目标板上运行的Linux引导程序,内核,文件系统和应用程序

交叉编译:在特殊的环境下,把嵌入式程序代码编译成不同的CPU所对应的机器代码。

开发时使用宿主机上的交叉编译,汇编及链接工具形成可执行的二进制代码(该代码只能在开发板上执行),然后下载到开发板上运行

2) 下载和安装arm-Linux-gcc编译工具链 下载最新的arm-Linux-gcc并解压至当前目录下

在系统配置文件profile中设置环境变量 方法:直接在profile文件中加入搜索路径 立即使新的环境变量生效:运行source命令,检查是否将路径加入到path,测试是否安装成功,

编译程序,测试交叉工具链

3) 配置超级终端minicom minicom是宿主机与目标板进行通信的终端:在宿主机Linux终端中输入:minicom-s或输入minicom然后按ctrl+A+O对超级终端minicom进行配置,再选择串口并配置串口,最后保存即可

4) 建立数据共享服务:NFS服务是Linux系统中经常使用的数据文件共享服务

5) 编译嵌入式系统内核:内核配置,建立依存关系,建立内核

6) 制作文件系统

三、给出现今有哪些用于嵌入式开发的芯片名称,他们分是哪

些公司的产品?体系结构是什么?

1) 基于32位RISC微处理器芯片的ARM7系列,ARM9系列,ARM9E系列,ARM10E系列都是ARM公司的产品,arm9以上的体系结构是哈佛总线体系结构以下的是冯。诺依曼体系。

2) TI公司的DSP处理器内核是哈佛总线体系结构。 3) PowerPC公司的芯片,基于RISC结构,是哈佛总线体系结构。

4) MIPS公司的芯片,基于RISC结构,是哈佛总线体系结构。 四、现今较流行的嵌入式操作系统有哪些?

① VxWork ② Linux ③ μC/OS-Ⅱ ④ windows CE ⑤ Android

五、PXA270嵌入式开发板的接口有哪些?

全双工异步串行口和硬件流控制串行口,10M标准以太网接口10M/100M标准以太网接口,USB接口,红外通讯口,音频接口,存储卡口,视频和触摸屏接口摄像头接口,RTC时钟接口,调试接口,下载接口,电源接口。 六、请写出Nor Flash和 Nand Flash的区别。

Flash是一种非易失闪存,它具有和ROM一样的掉电后数据

不会丢失的特性。它主要分为Nor Flash和 Nand Flash。他们的主要区别如下所示:

Nor Flash 接口时序同SRAM,容易使用 Nand Flash 地址/数据线复用,数据位较窄 读取速度较快 读取速度较慢 檫除速度慢,以64-128KB的块为檫除速度快,以8-32KB的块单位 为单位 写入速度慢(因为一般要檫除) 写入速度快 随机存取速度较快,支持XIP顺序读取速度较快,随机存取(eXecute In Place,芯片内执速度慢,适用于数据存储(如行),适用于代码存储。在嵌入式大容量的多媒体应用)。在嵌系统中,常用于存放引导程序、入式系统中,常用于存放用户根文件等 单片容量较小为1-32MB 文件系统等 单片容量较大为8-128MB,提高了单元密度 最大檫写次数为10万次 最大檫写次数为100万次 七、冯。诺依曼架构与哈佛架构的区别。

他们的主要区别是计算机的存储结构和总线连接形式不同。 在冯·诺依曼的结构中,存储器内部的数据存储空间和程序存储空间是合在一起的,他们共享存储器总线,即数据和指令在同一条总线上通过时分复用的方式进行传输,这种结构

在高速运行时,不能达到同时取指令和取操作数的目的从而形成传输过程的瓶颈。

在哈佛总线体系结构的芯片内部,数据存储空间和程序存储空间是分开的,所以哈佛总线体系在指令执行时可以同时存取指令(来自程序空间)和取操作数(来自数据空间),因此具有更高的执行效率,修正的哈佛总线结构还可以在程序空间和数据空间之间相互传送数据。(目前大多数DSP和ARM9以上的嵌入式系统微处理器内核都采用哈佛总线体系结构而ARM7采用的则是冯·诺依曼结构) 八、单周期3级流水的情况下,第10个指令周期时,第几条指令执行结束? 三级流水读取指令过程: ⑴ 取指从存储器装载一条指令 ⑵ 译码识别将要被执行的指令 ⑶ 执行处理指令并将结果写会寄存器

故ARM正在执行第1条指令的同时对第2条指令进行译码,并将第3条指令从存储器中取出。所以,ARM7流水线只有在取第10条指令时,第7条指令才算完成执行。

九、下面是linux下的一个简单的设备驱动程序,写出linux设备驱动常用的数据结构,同时阅读下面代码,请给出测试程序中的每条语句加以注释。 设备驱动程序Keypad.c的源代码:

#include //最基本的文件,支持动态添加和卸载模块。Hello World驱动要这一个文件就可以了 #include //包含了文件操作相关struct的定义,例如大名鼎鼎的struct file_operations #include //初始化头文件 #include //轮询文件

#include //对一些特殊类型的定义,例如dev_t, off_t, pid_t.其实这些类型大部分都是unsigned int型通过一连串的typedef变过来的,只是为了方便阅读。 #include //可以在芯片上产生周期性的中断 #include //延时头文件

#include //与处理器相关的硬件 #include //延时头文件

#include //与处理器相关的入口 #define LEDnKEY_MAJOR 251

#define KEYPAD_NAME \#define KEYPAD_VERSION \#define EXT_KEY_CS EXT_PORT2 //宏定义 #define EXT_LED_CS EXT_PORT3//宏定义 #define LED_SHOW 10//宏定义

/*EXT_KEY_CS 为向外部LED进行数值设定,它定义在其它头文件里*/

void led_off_on() { int i;

EXT_LED_CS = 0xff; for(i =0 ; i<8;++i) {

EXT_LED_CS = ~((1 << i) & 0xff);/*点亮相应LED灯*/

udelay(30000);//调用udelay函数来延迟 }

EXT_LED_CS = 0xff; }

/*应用程序用open来打开设备文件,实际上调用驱动的lednkey_open()函数*/

int lednkey_open(struct inode *inode, struct file *filp)//打开设备文件 {

MOD_INC_USE_COUNT;//模块自身通过

MOD_INC_USE_COUNT,宏来管理自己被使用的计数。 return (0); /* success */ }

int lednkey_release(struct inode *inode, struct file *filp) //释放设备文件 {

led_off_on(); MOD_DEC_USE_COUNT; return (0); }

ssize_t lednkey_read(struct file *filp, char *Putbuf, size_t length, loff_t *f_pos)//按键读取函数 {

unsigned short BottonStatus; unsigned char Bottontmp = 0; int i;

BottonStatus = ( EXT_KEY_CS & 0xff ); /*按键状态*/

for(i = 0 ; i < 8; ++i) {

if( ((BottonStatus >> i) & 1) == 0 ) Bottontmp = (i+1); }/*判断哪个按键按下*/

copy_to_user( Putbuf, &Bottontmp, length);/*将数据从内核态拷贝到用户态,这是由定义在

里的特殊函数实现在不同的空间传输任意字节的数据*/ return length; }

ssize_t lednkey_write(struct file *filp, const char *Getbuf, size_t length, loff_t *f_pos) {

int num;

unsigned char UsrWantLed;

copy_from_user( &UsrWantLed, Getbuf, length);/*将数据从用户态拷贝到核心态*/

num = ( (UsrWantLed) & 0xff );/*确定哪一位要进行设定*/

EXT_LED_CS = ~(1 << (num-1));//点亮相应LED灯 return (0); }

int lednkey_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,unsigned long

arg)//lednkey_ioctl 接口函数,主要用于获取或者改变正在运行的设备参数

{

switch(cmd) {

case LED_SHOW: {

if(arg)

led_off_on(); break; } }

return 0; }

/*以下这些驱动函数是与用户的应用程序里对设备文件操作的函数相对应的*/

struct file_operations lednkey_fops = { open: lednkey_open, read: lednkey_read, write: lednkey_write, ioctl: lednkey_ioctl, release: lednkey_release, };

static int _init xhyper250_keypad_init(void) //初始

化设备函数,在函数名之前加上这个属性之后,系统会在初始化完成之后丢弃初始化函数,收回它所占用的内存,以减小内核所占用的内存空间,它只对内建的驱动起作用 {

int result;

result = register_chrdev(LEDnKEY_MAJOR, \&lednkey_fops);//向操作系统注册一个主号为251,设备名为\,并传递设备驱动程序的指针为lednkey_fops(全局变量) ,其中register_chrdev ( )是内核提供的函数,作用是完成注册新的字符设备

printf(\KEYPAD_VERSION); led_off_on(); return 0; }

static void _exit xhyper250_keypad_exit(void)/*向操作系统卸载设备函数*/ {

unregister_chrdev( LEDnKEY_MAJOR, \

led_off_on(); }

module_init(xhyper250_keypad_init); //显式声明初始化设备函数

module_exit(xhyper250_keypad_exit); //显式声明卸载设备函数*/

测试文件的源代码如下: #include #include #include #include #include #include

#define LED_SHOW 10//宏定义 int fd;

static char *dev_name = \

int main(int argc, char **argv) {

int data = 0, pre_data;

fd = open( dev_name , O_RDWR );//使用函数open打

开设备keypad if( !(fd >=0) ) {

printf(\ exit(-1);

}//打开失败,显示出错信息

printf(\show led - Exit Ctrl-C \\n\打开成功,提示用户输入

ioctl(fd,LED_SHOW,1);//循环显示LED,看LED是否正常

while(1) { do {

pre_data = data;

read( fd, (char * )&data, sizeof(data) ); data = (data & 0xff); }while(data == 0);

if( pre_data == 0) {