arm+驱动要点

合集下载

ARM11嵌入式系统Linux下LCD的驱动设计

ARM11嵌入式系统Linux下LCD的驱动设计

kfree(ld);
return ret;
}
}
printk(KERN_INFO "lcd: registered successfully\n");
return 0;
}
}
2、寄存器设置:在驱动程序中,需要对LCD屏幕的硬件接口进行相应的寄存 器设置,以配置屏幕的参数。以下是一个示例代码,用于设置LCD屏幕的分辨率 和颜色深度:
015 cpp
016 {
017
int ret;
ARM11嵌入式系统Linux下LCD驱 动设计
ARM11嵌入式系统Linux下LCD驱动设计
随着嵌入式系统的广泛应用,液晶显示(LCD)已成为其重要的输出设备之一。 在ARM11嵌入式系统中,为了能够正常地使用LCD,需要设计一个相应的LCD驱动 程序。本次演示将介绍LCD驱动程序的设计需求、思路和具体实现方法,以及测 试与结果分析。
需求分析
4、易用性:要求驱动程序具有简单的接口,方便应用程序开发人员进行屏幕 绘制和控制。
设计思路
设计思路
为了满足上述需求,LCD驱动程序的设计应遵循以下思路:
设计思路
1、硬件接口设计:根据不同的LCD屏幕型号,设计相应的硬件接口。通常情 况下,LCD屏幕与嵌入式处理器的连接方式包括GPIO、SPI、I2C等,需要根据具 体情况选择适合的接口方式。
bpp = pdata->bpp;
bpp = pdata->bpp;
/* calculate the frame buffer address */
bpp = pdata->bpp;
fbaddr = (unsigned long)fb->fix.

基于ARM的LINUX网卡驱动程序的开发与设计

基于ARM的LINUX网卡驱动程序的开发与设计

密摘要Linux技术是当前计算机技术中最大的一个热点,在我国以及全世界得到了迅猛的发展,被广泛的应用于嵌入式系统、服务器、网络系统、安全等领域。

从而使得掌握在Linux环境下的开发技术,成为了计算机行业中引人注目的焦点。

以Linux为代表的自由操作系统的优点之一,是它们的内部是开放的。

Linux内核保留有大量的复杂代码,通常设备驱动提供了一个门路,使硬件特殊的一部分响应定义好的内部编程接口,它们完全隐藏了设备工作的细节。

用户的活动通过一套标准化来进行,设备驱动就是将这些调用映射到作用于实际硬件和设备相关的操作上。

论文首先介绍了Linux下设备驱动程序设计的基本知识,其中包括对Linux的发展历程、内核、特性的概述,Linux设备的分类及编写驱动程序的一些基本概念等,以及模块的加载和卸载。

其次介绍了ARM驱动程序开发的硬件环境和软件环境。

阐述了该驱动程序在开发时的需求分析。

第三对Linux环境下网卡驱动程序的设计与实现作了理论上的探讨,重点从网卡驱动模块的加载、网络设备的初始化、设备打开与关闭、数据的发送与接收、信息统计、网卡驱动模块的卸载等方面按步骤的进行了详细的讨论。

通过组建在Linux操作系统下的TCP/IP网络,来分配IP地址以及区分网络号和主机号的子网掩码,通过配置DHCP服务器,实现动态地为主机配置IP参数,解决手工配置存在的问题。

最后介绍了在驱动程序开发设计过程中所遇到的问题和困难以及是如何去克服这些困难的,并提出了今后的努力方向。

关键词:Linux;模块;网络;驱动;寄存器I Abstract Linux technology is a hotspot among computer technology nowadays, and it developes at high speed not only in our country but also in the whole world, and it has applied widely in embedded system, server, network system, security area and so on. So it makes that grasping the development technology under the Linux environment is m ore and more noticeable in computer industry. One of more and more noticeable in computer industry. One of the many advantages of free operating systems, as typified by Linux, is that their internals are open for all to view. The Linux kernel remains large and complex body of code. User activities are performed by means of a set of standardized calls that are independent of the specific driver; mapping those calls to device-specific operations that act on real hardware is then the role of the device driver. This This thesis thesis thesis firstly firstly firstly introduces introduces introduces the the the fundamental fundamental fundamental knowledge knowledge knowledge about about about design design design of of linux device driver, which generally includes the development procedure, kernel, and and characteristic characteristic characteristic of of of linux. linux. linux. Meanwhile, Meanwhile, Meanwhile, the the the categorization categorization categorization of of of linux linux linux device, device, elemental terminology of exploiting network interface card driver, and loading and unloading the driver module are also mentioned in this thesis. Secondly, this thesis also presents both the the hardware hardware hardware and and and software software software environment of the environment of the d river driver development, development, and and and the the the requirement requirement requirement specification specification specification of of of driver driver driver development development development are are elaborated here. Thirdly, combined with the driver of ARM, this thesis discusses the the design design design and and and realization realization realization of of of the the the network network network interface interface interface card card card driver driver driver in in in theory, theory, especially especially makes makes makes more more more detailed detailed detailed discussions discussions discussions step step step by by by step, step, step, such such such as as as loading loading loading the the driver module, initialization of the device, starting and stopping of the device, transmission transmission and and and receiving of data, receiving of data, i nformation information information statistics, statistics, statistics, unloading the unloading the driver module, etc. Allocating IP addresses and subnet masks differentiating network and host, through construction of TCP/IP network in Linux. Configuring host's IP IP arguments arguments arguments dynamically dynamically dynamically to to to well well well solve solve solve the the the problem problem problem of of of manual manual manual configuration, configuration, through configuration of DHCP server. Finally, this thesis lists all the problems and and difficulties difficulties difficulties met met met during the during the whole process of designing driver, a nd how to and how to conquer them and advanced direction of future study are also recounted. Keywords: linux; module; network; driver; register录目 录摘要..................................................................................................................................... I Abstract ..................................................................................................................................... II 绪论 .............................................................................................................................. 1第1章绪论1.1 研究背景研究背景 ..................................................................................................................... 11.2 国内外研究现状、目的及意义国内外研究现状、目的及意义 ................................................................................. 11.3 本文主要工作本文主要工作 ............................................................................................................. 2第2章Linux下设备驱动程序设计的基本知识 ................................................................... 42.1 Linux概述 ................................................................................................................... 42.1.1 Linux内核简介 ................................................................................................ 42.1.2 Linux的特性 .................................................................................................... 62.2 Linux设备驱动程序概述 ........................................................................................... 72.2.1 Linux设备驱动程序分类 ................................................................................ 82.2.2 编写网络驱动程序的一些基本概念编写网络驱动程序的一些基本概念 .............................................................. 9第3章Linux网卡驱动程序设计的理论探讨 ..................................................................... 103.1 Linux下网卡驱动程序设计的数据结构和基本方法 ............................................. 103.1.1 网卡驱动程序设计要用到的数据结构网卡驱动程序设计要用到的数据结构 ....................................................... 103.1.2 网卡驱动程序的基本方法网卡驱动程序的基本方法 ............................................................................ 133.1.3 套接字缓冲区介绍套接字缓冲区介绍 ........................................................................................ 143.2 驱动模块的加载和卸载驱动模块的加载和卸载 ........................................................................................... 17系统分析 .................................................................................................................... 19第4章系统分析4.1 S3C2410 ARM 开发板介绍开发板介绍 ..................................................................................... 19开发板介绍4.2 需求分析以及MII接口接口 ........................................................................................... 194.3 寄存器的访问方式寄存器的访问方式 ................................................................................................... 21第5章网卡驱动的具体实现网卡驱动的具体实现 ................................................................................................ 225.1 驱动程序的设计驱动程序的设计 ....................................................................................................... 225.2 网卡驱动实现网卡驱动实现 ........................................................................................................... 245.2.1 模块的加载及设备初始化模块的加载及设备初始化 ............................................................................ 245.2.2 设备成员及函数的初始化设备成员及函数的初始化 ............................................................................ 265.2.3 设备注册、打开、关闭设备注册、打开、关闭 ............................................................................... 305.2.4 数据的接受和发送数据的接受和发送 ........................................................................................ 325.2.5 参数设置及数据统计参数设置及数据统计 .................................................................................... 345.2.6 网卡数据信息统计网卡数据信息统计 ........................................................................................ 36第6章结论结论 ............................................................................................................................ 37参考文献............................................................................................................................ 38致谢...................................................................................................................................... 39沈阳工业大学本科生毕业设计沈阳工业大学本科生毕业设计1 第1章 绪论1.1 1.1 研究背景研究背景Linux 目前是计算机技术的一大热点,最近几年在我国得到迅猛发展,被广泛应用在嵌入式系统、服务器和桌面应用等领域。

arm的知识点总结

arm的知识点总结

arm的知识点总结ARM处理器架构的特点有很多,包括:1. 精简指令集:ARM处理器使用精简的指令集,使其在相同的时钟周期内执行更多的指令。

这有助于提高处理器性能和效率。

2. 低功耗设计:ARM处理器具有低功耗设计,使其在电池供电的移动设备中表现出色。

它在相同性能水平下消耗的能量更少,可延长设备的续航时间。

3. 易扩展性:ARM架构具有很强的可扩展性,可以从简单的嵌入式系统到复杂的服务器系统等不同领域应用。

4. 多样化产品线:ARM公司提供多种不同的处理器核心,包括Cortex-A、Cortex-R和Cortex-M系列,能够满足不同应用领域的需求。

5. 兼容性:ARM架构保持了向后兼容性,旧版本的软件可以在新版本的处理器上运行,这使得升级系统更加容易。

ARM处理器的应用领域非常广泛,主要包括以下几个方面:1. 移动设备:包括智能手机、平板电脑、便携式游戏机等。

ARM处理器在移动设备的低功耗和高性能需求下表现优异。

2. 智能家居:包括智能音箱、智能家电、智能监控等。

ARM处理器在小型嵌入式设备中的低功耗和高性能要求下发挥作用。

3. 工业控制:包括自动化生产线、机器人控制、传感器网络等。

ARM处理器在工业环境下的可靠性和低功耗表现得较好。

4. 汽车电子:包括车载娱乐系统、车载导航系统、车载通信系统等。

ARM处理器在汽车电子设备中的高性能和低功耗要求下表现出色。

5. 服务器与数据中心:ARM处理器在云计算、大数据分析等方面逐渐发展起来,其低功耗和高核心密度使其成为一种有潜力的替代方案。

在ARM处理器架构中,最常见的是Cortex系列处理器核心。

Cortex系列核心包括Cortex-A、Cortex-R和Cortex-M,它们分别面向不同的应用领域:1. Cortex-A系列:面向高性能应用,如智能手机、平板电脑、智能电视等。

它具有复杂的流水线设计和乱序执行功能,能够提供出色的性能。

2. Cortex-R系列:面向实时应用,如汽车电子系统、工业控制系统、网络设备等。

基于ARM的嵌入式系统开发要点一

基于ARM的嵌入式系统开发要点一

基于ARM 的嵌入式系统开发要点(一)——嵌入式程序开发进程ARM 系列微处置器作为全世界 16/32RISC 处置器市场的领先者,在许多领域内取得了成功的应用。

最近几年来 ,ARM 在 国内的应用也取得了飞速的进展,愈来愈多的公司和工程师在基于ARM 的平台上面开发自己的产品。

与传统的4/8位单片机相较 ,ARM 的性能和处置能力固然是遥遥领先的 ,但与之相应,ARM 的系统设计复杂和 难度,较之传统的设计方式也大大提升了。

本文旨在通过讨论系统程序设计中的几个大体方面,来讲明基于ARM 的嵌入式系统开发的一些特点,并提出和解决了一些常见问题。

文章分成几个相对独立的章节刊载。

第一部份讨论了基于ARM 的嵌入式程序开发和移植进程中的一些大体概念。

1. 嵌入式程序开发进程不同于通用运算机和工作站上的软件开发工程,一个嵌入式程序的开发进程具有很多特点和不确信性。

其中最重要的一点是软件跟硬件的紧密耦合特性。

这是两类简化的嵌入式系统层次结构图。

由于嵌入式系统的灵活性和多样性,上面图中各个层次之间缺乏统一的标准,几乎每一个独立的系统都不一样。

如此就给上层的软件设计人员带来了极大的困难。

第一,在软件设计进程中过量地考虑硬件,给开发和调试都带来了很多不便,第二,若是所有的软件工作都需要在硬件平台就绪以后进行,自然就延长了整个系统的开发周期。

这些都是因该从方式上加以改良和幸免的问题。

为了解决那个问题,工程和设计人员提出了许多计谋,第一在应用于驱动(或API)着一层,能够设计成相对统一的一些接口函数,这关于具体的某一个开发平台或在某个公司内部,是完全做取得的。

如此一来,就大大提高了应用软件设计的标准化程度,方便了应用程序在跨平台之间的复用和移植。

关于驱动/硬件抽象这一层,因为直接驱动硬件,其标准化变得超级困难乃至不太可能。

可是为了简化程序的调试和缩短开发周期,咱们能够在特定的EDA工具环境下面进行开发,通事后再进行移植到硬件平台的工作。

带触摸屏的ARM开发板驱动基于AS3992芯片的RFM-x系.

带触摸屏的ARM开发板驱动基于AS3992芯片的RFM-x系.

带触摸屏的ARM开发板驱动基于AS3992芯片的RFM-x系列RFID读写模块凡夫RFM-x模块是高集成度的RFID读写模块,软件功能强大,有关EPC协议的电子标签的所有操作以及标签防碰撞算法都已封包在软件中了,用户应用层软件无需深入了解RFM-x模块与电子标签之间的具体通信协议,驱动模块的软件很简单,只要掌握几个基本指令,就能开发出应用层软件。

我设计的这个演示程序运行在STM32F107平台上,ARM主程序是一个图形菜单界面,其中有一个RFID图标。

点击“RFID”图标,进入RFID扫描界面,点击“开始”,开始扫描并显示标签。

点选其中一个标签号,反显,再次点击,可以进入写标签界面。

进入写标签界面,输入新标签号,点“确定”就OK了。

还有一个RFID设置的界面。

后附ARM开发板直接驱动RFM-x模块的相关程序和函数节选。

在STM32F107开发板上调试运行通过。

演示程序已经支持4.3’LCD触摸屏、8GMicroSD卡、EEPROM、2M的Flash SST25VF016B,支持两个串口、一个SPI,还有按键、LED,有实时时钟等,软件功能有文本浏览、图片浏览、画板,以及RFID读写。

需要完整程序的可以联系我,QQ:542968281。

============================================================ ========= 5.3.1 头文件/*COMMANDS */#define OUT_INVENTORY_ID 0x31#define IN_INVENTORY_ID 0x32#define OUT_SELECT_TAG_ID 0x33#define IN_SELECT_TAG_ID 0x34#define OUT_WRITE_TO_TAG_ID 0x35#define IN_WRITE_TO_TAG_ID 0x36#define OUT_READ_FROM_TAG_ID 0x37#define IN_READ_FROM_TAG_ID 0x38#define OUT_WRITE_REG_ID 0x1A#define IN_WRITE_REG_ID 0x1B#define OUT_READ_REG_ID 0x1C#define IN_READ_REG_ID 0x1D#define OUT_INVENTORY_IDSize 0x02#define IN_INVENTORY_IDSize 0x3f#define OUT_WRITE_TO_TAG_IDSize 0x3f#define IN_WRITE_TO_TAG_IDSize 0x03#define OUT_READ_FROM_TAG_IDSize 0x07 #define IN_READ_FROM_TAG_IDSize 0x3f #define OUT_WRITE_REG_IDSize 0x05#define IN_WRITE_REG_IDSize 0x02#define OUT_READ_REG_IDSize 0x02#define IN_READ_REG_IDSize 0x055.3.2 节选主程序中盘点标签的例程//发inventory Tag命令if((RFID_START&0xC0==0xC0{LED3=1;USART1_TX_BUF[0]=OUT_INVENTORY_ID;USART1_TX_BUF[1]=OUT_INVENTORY_IDSize+1;USART1_TX_BUF[2]=0x01;USART1_SEND(USART1_TX_BUF;USART1_RX_STA=0; //意外掉包时清零timer=0;RFID_START&=0x80; //清除循环计数bit[5:0],清bit6为usart1忙状态 } else{if((RFID_START&0xC0==0x80{timer++;if(timer>65534{RFID_START++; //意外掉包时循环计数bit[5:0],溢出进位到bit6,inventory可以再次发送timer=0;#ifdef debugprintf("\nRFID_START:%x\n",RFID_START;#endif}}}5.3.3 Select标签的函数//Select Tag//sel---Select Tag的Tag_Buffer[]指针void Select_tag(u8 sel{u8 i,j;u32 temp;USART1_TX_BUF[0]=OUT_SELECT_TAG_ID;USART1_TX_BUF[2]=0x0C;USART1_TX_BUF[1]=USART1_TX_BUF[2]+3;for(i=3;i>0;i--{temp=Tag_Buffer[3*sel-i];for(j=0;j<4;j++{//temp=temp>>j;//USART1_TX_BUF[3+j]&=0x00;USART1_TX_BUF[3+j+4*(3-i]=temp>>8*(3-j;#ifdef debugprintf("\nSelect Tag:%x\n",USART1_TX_BUF[3+j+4*(3-i]; #endif }}USART1_SEND(USART1_TX_BUF;}5.3.4 Write标签的函数//Write Tag//data---Write Tag的数据void Write_tag(u32 *data{u8 i,j;USART1_TX_BUF[0]=OUT_WRITE_TO_TAG_ID;USART1_TX_BUF[2]=0x01;//EPCUSART1_TX_BUF[3]=0x02;//EPC addressUSART1_TX_BUF[4]=0x00;//Pass WordUSART1_TX_BUF[5]=0x00;//Pass WordUSART1_TX_BUF[6]=0x00;//Pass WordUSART1_TX_BUF[7]=0x00;//Pass WordUSART1_TX_BUF[8]=0x06;//EPC Word lengthUSART1_TX_BUF[1]=2*USART1_TX_BUF[8]+9;//EPC Word length for(i=0;i<3;i++{for(j=0;j<4;j++{USART1_TX_BUF[9+j+4*i]=data[i]>>8*(3-j;#ifdef debugprintf("\nWrite Tag:%x\n",USART1_TX_BUF[9+j+4*i]; #endif}}USART1_SEND(USART1_TX_BUF;}5.3.5 调整模块的输出功率和灵敏度的函数void Save_RFID_Set(u8 PA_val,u8 Sensi_val{u8 len,temp=0;u8 data0,data1,data2;/*-----------保存功率设置-------------*///读Modulator Control Register[23:0]USART1_TX_BUF[0]=OUT_READ_REG_ID;USART1_TX_BUF[1]=OUT_READ_REG_IDSize+1;USART1_TX_BUF[2]=0x15; USART1_SEND(USART1_TX_BUF; while(!(USART1_RX_STA&0x8000{delay_ms(5;temp++;if (temp>20break;}if(USART1_RX_STA&0x8000{len=USART1_RX_STA&0x0FFF;len++; //得到此次接收到的数据长度#ifdef debugprintf("\nlen=%x\n",len;#endifif((len==6&&(USART1_RX_BUF[5]==0x00{data0=USART1_RX_BUF[2];data1=USART1_RX_BUF[3];data2=USART1_RX_BUF[4];}else{LCD_Fill(0,260,240,280,LGRAY;//填充灰色Show_Str(10,260,"获取功率失败!",16,0x01; //叠加模式,非自动换行 } USART1_RX_STA=0;}else{LCD_Fill(0,260,240,280,LGRAY;//填充灰色Show_Str(10,260,"获取功率超时!",16,0x01; //叠加模式,非自动换行}//改变功率data0 = (data0&0xE0|PA_table[27-PA_val];//写Modulator Control Register[23:0]USART1_TX_BUF[0]=OUT_WRITE_REG_ID;USART1_TX_BUF[1]=OUT_WRITE_REG_IDSize+1;USART1_TX_BUF[2]=0x15;USART1_TX_BUF[3]=data0;USART1_TX_BUF[4]=data1;USART1_TX_BUF[5]=data2;USART1_SEND(USART1_TX_BUF;while(!(USART1_RX_STA&0x8000{delay_ms(5;temp++;if (temp>20break;}if(USART1_RX_STA&0x8000{len=USART1_RX_STA&0x0FFF;len++; //得到此次接收到的数据长度#ifdef debugprintf("\nlen=%x\n",len;#endifif((len==3&&(USART1_RX_BUF[2]==0x00;else{LCD_Fill(0,260,240,280,LGRAY;//填充灰色Show_Str(10,260,"设置功率失败!",16,0x01; //叠加模式,非自动换行 } USART1_RX_STA=0;}else{LCD_Fill(0,260,240,280,LGRAY;//填充灰色Show_Str(10,260,"设置功率超时!",16,0x01; //叠加模式,非自动换行 } /*-----------保存灵敏度设置-------------*///读Register0x0A[7:0]data0 = Read_RFIDModule(0x0A;//改变灵敏度data0 = (data0&0x04|Sensitivity_table[Sensi_val][1];//写Register0x0A[7:0]Write_RFIDModule(0x0A,data0;//读Register0x05[7:0]data0 = Read_RFIDModule(0x05;//改变灵敏度data0 = (data0&0x7F|Sensitivity_table[Sensi_val][0];//写Register0x05[7:0]Write_RFIDModule(0x05,data0;/*-----------保存Q值设置-------------*/LCD_Fill(0,260,240,280,LGRAY;//填充灰色Show_Str(10,260,"初始化完成!",16,0x01; //叠加模式,非自动换行}5.3.6 读模块寄存器的函数u8 Read_RFIDModule(u8 addr{u8 len,temp=0;u8 data0;USART1_TX_BUF[0]=OUT_READ_REG_ID;USART1_TX_BUF[1]=OUT_READ_REG_IDSize+1;USART1_TX_BUF[2]=addr; USART1_SEND(USART1_TX_BUF;while(!(USART1_RX_STA&0x8000{delay_ms(5;temp++;if (temp>20break;} if(USART1_RX_STA&0x8000 { len=USART1_RX_STA&0x0FFF; len++; //得到此次接收到的数据长度 if((len==6&&(USART1_RX_BUF[5]==0x00{ data0=USART1_RX_BUF[2]; USART1_RX_STA=0; return data0; } else{LCD_Fill(0,260,240,280,LGRAY;Show_Str(10,260,"获取失败!",16,0x01;USART1_RX_STA=0;return 0xff;} //叠加模式,非自动换行 } else{LCD_Fill(0,260,240,280,LGRAY;Show_Str(10,260,"获取超时!",16,0x01;return 0xff;} //叠加模式,非自动换行 } 5.3.7 写模块寄存器的函数 void Write_RFIDModule(u8 addr,u8 data { u8 len,temp=0; USART1_TX_BUF[0]=OUT_WRITE_REG_ID;USART1_TX_BUF[1]=OUT_WRITE_REG_IDSize-1; USART1_TX_BUF[2]=addr; USART1_TX_BUF[3]=data; USART1_SEND(USART1_TX_BUF;while(!(USART1_RX_STA&0x8000 { delay_ms(5; temp++;if (temp>20break; } if(USART1_RX_STA&0x8000{ len=USART1_RX_STA&0x0FFF; len++; //得到此次接收到的数据长度if((len==3&&(USART1_RX_BUF[2]==0x00; else{LCD_Fill(0,260,240,280,LGRAY;Show_Str(10,260,"设置失败!",16,0x01;} // 叠加模式,非自动换行 USART1_RX_STA=0; } else{LCD_Fill(0,260,240,280,LGRAY;Show_Str(10,260,"设置超时!",16,0x01;} //叠加模式, 非自动换行 } 5.3.8 串口接收中断服务函数 //串口 1 中断服务程序 u8USART1_RX_BUF[3060]; //接收状态 //bit15,接收完成标志 //bit14,接收到 0x0d//bit11~0,接收到的有效字节数目,最多 3060,0xBF4 u16 USART1_RX_STA=0; //接收状态标记 //接收缓冲,最大 3060 个字节. void USART1_IRQHandler(void { u8 res; if(USART1->SR&(1<<5//接收到数据 { res=USART1->DR;USART1_RX_BUF[USART1_RX_STA&0x0FFF]=res; switch(USART1_RX_BUF[0] {case IN_CHECK_ON_LINE_ID: //返回两字节包处理if((USART1_RX_STA&0x0FFF==1 { //USART1_RX_STA|=0x8000;; 接收完成标志USART1_RX_STA=0; return; } break; case IN_FIRM_HARDW_ID: caseIN_READ_REG_ID: case IN_WRITE_REG_ID: case IN_SELECT_TAG_ID: caseIN_WRITE_TO_TAG_ID: //返回变长字节包处理 //返回六字节包处理 //返回三字节包处理 //返回三字节包处理 //返回四字节包处理 //收到两字节命令,if((USART1_RX_STA&0x0FFF>1{ if((USART1_RX_STA&0x0FFF==(USART1_RX_BUF[1]-1 //接收完成{ USART1_RX_STA|=0x8000; return; } } break; case IN_INVENTORY_ID: //返回变长字节包或四字节包处理 //接收完成标志 if((USART1_RX_STA&0x0FFF>16{ if((USART1_RX_STA&0x0FFF==(USART1_RX_BUF[1]*USA RT1_RX_BUF[2]-1//接收完成 { USART1_RX_STA|=0x8000; return; } }if((USART1_RX_STA&0x0FFF==0x03 && (USART1_RX_BUF[2]==0{ USART1_RX_STA|=0x8000; 无标签,接收完成标志 return; //收到 4 字节命令, //接收完成标志} break; default: USART1_RX_STA=0; return; } USART1_RX_STA++;if((USART1_RX_STA&0x0FFF>3059USART1_RX_STA|=0x8000;//接收数据错误,重新开始接收 }return; } 需要完整程序的可以联系我,QQ:542968281。

ARM知识点讲解.

ARM知识点讲解.

ARM知识点讲解.1、ARM处理器工作模式有几种?各种工作模式下分别有什么特点?答:ARM 处理器有7种工作模式,这7种模式及其特点是:快速中断模式(fiq)支持高速数据传输或通道处理,外部中断fiq信号有效且CPSR的F=0进入。

中断模式(irq)用于通用中断处理,外部中断irq信号有效CPSR的I=0进入。

管理员模式(svc)- 操作系统的保护模式,复位、软件中断进入。

主要用于SWI(软件中断)和OS(操作系统)。

这个模式有额外的特权,允许你进一步控制计算机。

中止模式(abt)- 支持虚拟内存和/或内存保护预取指令中止/数据中止进入未定义模式(und)- 支持硬件协处理器的软件仿真(浮点、向量运算)未定义指令进入系统模式(sys)- 支持操作系统的特殊用户模式(运行操作系统任务)用户模式(usr)正常的程序执行模式,此模式应用程序不能访问受操作系统保护的资源,不能改变模式,除非异常发生。

2、ARM处理器总共有多少个寄存器,这些寄存器按其在用户编程中的功能是如何划分的?这些寄存器在使用中各有何特殊之处?答:ARM微处理器共有37个32位寄存器,其中31个为通用寄存器,6个为状态寄存器。

31个通用寄存器根据其编程特点可分为如下几种类型:1、不分组寄存器R0-R7 为所有模式共享2、分组寄存器R8-R12R8_fiq-R12_fiq:FIQ模式下的寄存器R8-R12:其它模式共享3、分组寄存器R13-R14分为6组,用户、系统一组,其他每种模式一组。

R13_通常用作堆栈指针SP,R14_通常用作子程序链接寄存器,当进入子程序时,常用来保存PC的返回值其中,mode为以下几种模式之一:usr、fiq、irq、svc、abt、und。

4、程序寄存器R15(PC)所有模式共享6个状态寄存器:一个CPSR当前程序状态寄存器,保存当前程序状态。

五个程序状态备份寄存器SPSR(svc,abt,und,irq,frq),只有在异常模式下,才能被访问;各异常模式都拥有属于自己的SPSR,当发生异常时,SPSR用来保存CPSR的值,从异常退出时则可由SPSR 来恢复CPSR。

源码开放学ARM网卡驱动实验

源码开放学ARM网卡驱动实验Linux 网卡驱动实验标准Board Linux启动 & uBuntu Linux 连接•pc linux ( 192.168.0.200 )•board linux ( 192.168.0.201 )ifconfig sudo ifconfig eth0 192.168.0.xxx测试网络连接对ping可以连通uboot 启动 & uBuntu Linux 连接1.开发板上的跳线 S2 拨到 SDBOOT 那边,通过 SD 卡启动2.启动之后进入 uboot 选项,修改环境变量3.[FriendlyLEG-TINY210]# printenv4.baudrate=1152005.bootdelay=36.ethact=dm90007.ethaddr=00:01:02:03:04:058.gatewayip=192.168.0.19.ipaddr=192.168.0.201mask=255.255.255.011.serverip=192.168.0.20012.stderr=serial13.stdin=serial14.stdout=serial15.16.[FriendlyLEG-TINY210]# setenv ipaddr 192.168.0.20117.[FriendlyLEG-TINY210]# setenv serverip 192.168.0.20018.[FriendlyLEG-TINY210]# saveenv19.Saving Environment to NAND...20.Erasing Nand...21.Erasing at 0x40000 -- 100% complete.22.Writing to Nand... done[FriendlyLEG-TINY210]#23.重启开发板,验证是否设置成功?看到 is alive 表示成功FriendlyLEG-TINY210# ping 192.168.0.200dm9000 i/o: 0x88001000, id: 0x90000a46 DM9000: running in 16 bit modeMAC: 00:01:02:03:04:05operating at 100M full duplex modeUsing dm9000 devicehost 192.168.0.200 is aliveFriendlyLEG-TINY210#uboot 和 uBuntu 之间的 tftp 连接ubuntu下搭建tftp server1.Install tftpd and related packages.2.$ sudo apt-get install xinetd tftpd tftp3.Create /etc/xinetd.d/tftp and put this entry:4.service tftp5.{6.protocol = udp7.port = 698.socket_type = dgram9.wait = yeser = nobody11.server = /usr/sbin/in.tftpd12.server_args = /tftpboot13.disable = no}14.Make /tftpboot directory15.$ sudo mkdir /tftpboot16.$ sudo chmod -R 777 /tftpboot17.$ sudo chown -R nobody /tftpboot18.Start tftpd through xinetd19.$ sudo /etc/init.d/xinetd restart20.test tftp in localhost21.$ cp something /tftpboot22.$ tftp localhost23.24.$ get something25.Received 4315348 bytes in 0.4 seconds26.27.$ tftp> quit$ ls something28.test tftp in board $ tftp 21000000 zImageuboot 和 uBuntu 之间的 uImage 内核下载测试设置 uboot 参数# setenv bootargs root=/dev/mtdblock4 console=ttySAC0,115200 init=/linuxrc lcd=S70# setenv ipaddr 192.168.0.201# setenv serverip 192.168.0.200# saveenv# printenv制作 uImage 内核文件# tftp 21000000 uImage# bootm 21000000获得 mkimageDM9000 驱动代码实现平台设备的注册 platform_devicearch/arm/mach-s5pv210/mach-mini210.c平台驱动的注册 platform_driverdrivers/net/dm9000.c头文件的包含drivers/net/dm9000.h include/linux/dm9000.h几个重要的文件•.config•make menuconfig 的配置选项保存在这个文件中•CONFIG_DM9000 = m•include/generated/autoconf.h•make 执行时会通过脚本分析 .config 文件,生成 autoconf.h 参与内核编译#define CONFIG_DM9000 1•driver/net/makefile•obj-$(CONFIG_DM9000) = dm9000.oMakefileobj-m := dm9000.oKDIR := /home/limingth/tiny210/src/linux-2.6.35.7modules: make -C $(KDIR) SUBDIRS=$(PWD) $@ ls -l dm9000.koclean: -rm .o.kostep by step•install tftpd•sudo apt-get install tftpd•install inetd•sudo apt-get install openbsd-inetdserver dir /srv/tftpsudo vi /etc/inetd.conf#:BOOT: TFTP service is provided primarily for booting. Most sites# run this only on machines acting as "boot servers."#tftp dgram udp wait nobody/usr/sbin/tcpd /usr/sbin/in.tftpd /srv/tftp tftp dgram udp wait nobody/usr/sbin/tcpd /usr/sbin/in.tftpd/home/limingth/tiny210sudo /etc/init.d/openbsd-inetd restart•download Image•limingth@ubuntu:~$ tftp 127.0.0.1•tftp> get zImage2•tftp> quit•change u-boot bootargs操作步骤FriendlyLEG-TINY210# setenv bootargs root=/dev/mtdblock4 console=ttySAC0,115200 init=/linuxrc lcd=S70 FriendlyLEG-TINY210# printenv baudrate=115200 bootargs=root=/dev/mtdblock4 console=ttySAC0,115200 init=/linuxrc lcd=S70 bootdelay=3 ethact=dm9000 ethaddr=08:0a:0a:0a:0a:0a gatewayip=192.168.0.1 ip=192.168.0.201 ipaddr=192.168.0.201 netmask=255.255.255.0 serverip=192.168.0.200 stderr=serial stdin=serial stdout=serial Environment size: 315/16380 bytes* 启动命令tftp 21000000 uImage bootm 21000000修改内核源码按以下方法修改内核以适应uboot,详参见liukun321的文章/liukun321/article/details/7383669,忽略此步骤将会出现加载kernel时卡死在Uncompressing Linux… done, booting the kernel….arch/arm/mach-s5pv210/include/mach/memory.h 文件26,27行内容,将Maximum of 256MiB in one bank的限制改为Maximum of 512MiB in one bank 作如下修改:#defineSECTION_SIZE_BITS 29#defineNODE_MEM_SIZE_BITS 29生成 uImagelimingth@ubuntu:~/tiny210/src$ ./mkimageUsage: ./mkimage -l image-l ==> list image header information./mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image-A ==> set architecture to 'arch'-O ==> set operating system to 'os'-T ==> set image type to 'type'-C ==> set compression type 'comp'-a ==> set load address to 'addr' (hex)-e ==> set entry point to 'ep' (hex)-n ==> set image name to 'name'-d ==> use image data from 'datafile'-x ==> set XIP (execute in place)./mkimage [-D dtc_options] -f fit-image.its fit-image./mkimage -V ==> print version information and exitlimingth@ubuntu:~/tiny210/src$ ./mkimage -A arm -O linux -T kernel -C none -a 21000000 -e 21000040 -n "linux-2.6.28" -d zImage2 myuImageImage Name: linux-2.6.28Created: Wed Aug 29 13:32:34 2012Image Type: ARM Linux Kernel Image (uncompressed)Data Size: 4288476 Bytes = 4187.96 kB = 4.09 MBLoad Address: 21000000Entry Point: 21000040/include/generated/mach-types.h./arch/arm/include/asm/mach-types.hlimingth@ubuntu:~/tiny210/src/linux-2.6.35.7$ vi arch/arm/include/asm/mach-types.hlimingth@ubuntu:~/tiny210/src/linux-2.6.35.7$ vi include/generated/mach-types.hin line 2950#define MACH_TYPE_MINI210 3466DM9000 驱动代码实现#include <linux/module.h>#include <linux/ioport.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/init.h>#include <linux/skbuff.h>#include <linux/spinlock.h>#include <linux/crc32.h>#include <linux/mii.h>#include <linux/ethtool.h>#include <linux/dm9000.h>#include <linux/delay.h>#include <linux/platform_device.h>#include <linux/irq.h>#include <linux/slab.h>#include <asm/delay.h>#include <asm/irq.h>#include <asm/io.h>#include "dm9000.h"MODULE_AUTHOR("AKAE");MODULE_DESCRIPTION("Sample DM9000 driver");MODULE_LICENSE("Dual BSD/GPL");#define DEVICE_NAME "dm9000"/*board_info结构体,用来保存芯片相关的一些私有信息*/typedef struct board_info {void __iomem *io_addr; /*映射到Linux内存空间的地址口虚拟地址*/void __iomem *io_data; /*映射到Linux内存空间的数据口虚拟地址*/u16 irq; /*IRQ*/u16 tx_pkt_cnt; /*待发送数据包数量,最多只能有两个*/u16 queue_pkt_len; /*待发送数据包长度*/u8 imr_all; /*用于给DM9000_IMR赋值的一个变量*/struct resource *addr_res; /*地址口地址*/struct resource *data_res; /*数据口地址*/struct resource *irq_res; /*IRQ*/struct mutex addr_lock; /*互斥信号两*/spinlock_t l ock; /*自旋锁*/} board_info_t;/*Read a byte from I/O port*/static u8 ior(board_info_t * db, int reg){writeb(reg, db->io_addr);return readb(db->io_data);}/*Write a byte to I/O port*/static void iow(board_info_t * db, int reg, int value){writeb(reg, db->io_addr); /*将寄存器地址写入映射进内存的i\o内存空间,通过地址找到相应的寄存器*/writeb(value, db->io_data); /*将数据写入寄存器*/}/*调用时机:当网卡有数据需要发送的时候,该函数被调用*//*第二个包的发送将在dm9000_tx_done中实现,这是因为当第一个数据发送完之后会产生一个中断,则会调用dm9000_tx_done对应的函数*/static int dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev){unsigned long flags;board_info_t *db = netdev_priv(dev);/*获得自旋锁并禁止中断,中断状态保存在flags中*/spin_lock_irqsave(&db->lock, flags);/*将io_addr写入寄存器MWCMD(写数据到DM9000内的发送SRAM中),进行这个操作后,向io_data写入的数据会传输到dm9000内部TX_SRAM中*/writeb(DM9000_MWCMD, db->io_addr);writesw(db->io_data, skb->data, (skb->len+1) >> 1);/*待发送的数据包数量(tx_pkt_cnt)加1*/db->tx_pkt_cnt++;/* TX control: First packet immediately send, second packet queue */if (db->tx_pkt_cnt == 1) {iow(db, DM9000_TXPLL, skb->len);iow(db, DM9000_TXPLH, skb->len >> 8);iow(db, DM9000_TCR, TCR_TXREQ);} else {/* Second packet */db->queue_pkt_len = skb->len;}/*释放自旋锁,并恢复中断之前的状态*/spin_unlock_irqrestore(&db->lock, flags);/*每个数据包写入网卡SRAM后都要释放skb*/dev_kfree_skb(skb);return NETDEV_TX_OK;}static void dm9000_tx_done(struct net_device *dev,board_info_t *db){/*读取dm9000寄存器NSR(NetworkStatus Register)获取发送的状态,存在变量tx_status中*/int tx_status = ior(db, DM9000_NSR);/*若有数据包发送完成,则进入*/if (tx_status & (NSR_TX2END | NSR_TX1END)) {/*待发送的数据包数量(tx_pkt_cnt)减1*/db->tx_pkt_cnt--;/*已发送的数据包数量(stats.tx_packets)加1*/dev->stats.tx_packets++;/*检查变量tx_pkt_cnt是否大于0(如果大于0,表明还有数据包要发送),则再次发送*/if (db->tx_pkt_cnt > 0){/*将要发送的数据包的长度写入DM9000的两个发送数据包长度寄存器中*/iow(db, DM9000_TXPLL, db->queue_pkt_len);iow(db, DM9000_TXPLH, db->queue_pkt_len >> 8);/*提出发送请求,发送完成后该位自动清零*/iow(db, DM9000_TCR, TCR_TXREQ);}}}/*该结构体封装了dm9000接收的数据包的头信息*/struct dm9000_rxhdr {u8 RxPktReady;u8 RxStatus;__le16 RxLen;} __attribute__((__packed__));/*告诉编译器取消结构在编译过程中的优化*/static void dm9000_rx(struct net_device *dev){board_info_t *db = netdev_priv(dev);struct dm9000_rxhdr rxhdr;struct sk_buff *skb;u8 rxbyte, *rdptr;int RxLen; /*接收数据包的长度*//* Check packet ready or not */do {/* 读取寄存器MRCMDX,MRCMDX寄存器地址保存在了db->io_addr中,下面要读取MRCMDX寄存器的值只需要读取db->io_data即可*/ior(db, DM9000_MRCMDX);/*读取MRCMDX寄存器的值,rxbyte为8位,因为MRCMDX 寄存器存储的值就是8位*/rxbyte = readb(db->io_data);/*DM9000_PKT_RDY定义为0x01,而rxbyte为我们读取的第一个字节,其值只能是0x00(表示还没接收)或0x01(表示已经接收)*/if (!(rxbyte & DM9000_PKT_RDY))return;/*将MRCMD寄存器地址写入db->io_addr*/writeb(DM9000_MRCMD, db->io_addr);/*一次性从MRCMD寄存器(即RX_SRAM)中读入四个字节的内容到rxhdr变量,*/readsw(db->io_data, &rxhdr, (sizeof(rxhdr)+1) >> 1);/*获取接收数据包的长度*/RxLen = le16_to_cpu(rxhdr.RxLen);skb = dev_alloc_skb(RxLen + 4);skb_reserve(skb, 2);rdptr = (u8 *) skb_put(skb, RxLen - 4);/*读取数据放入rdptr所在位置,rdptr位置为skb_tail,所以这句话就是读取RX_SRAM内容到skb*/readsw(db->io_data, rdptr, (RxLen+1) >> 1);dev->stats.rx_bytes += RxLen;/*函数eth_type_trans用于从以太网数据包中提取网络协议内容,并把它放入skb结构的相应位置*/skb->protocol = eth_type_trans(skb, dev);/*调用netif_rx将数据交给协议栈*/netif_rx(skb);} while (rxbyte & DM9000_PKT_RDY);}/*网卡有三种类型的中断:新报文到达中断,报文发送完成中断,出错中断*/static irqreturn_t dm9000_interrupt(int irq, void *dev_id){struct net_device *dev = dev_id;board_info_t *db = netdev_priv(dev);int int_status;unsigned long flags;u8 reg_save;/*获得自旋锁并禁止中断,中断状态保存在flags中*/spin_lock_irqsave(&db->lock, flags);/*保存中断前的状态*/reg_save = readb(db->io_addr);/* 禁用DM9000中断*/iow(db, DM9000_IMR, IMR_PAR);/*中断状态寄存器,当一个中断到来时,该寄存器存放着中断类型。

ARM嵌入式系统复习重点

1、嵌入式系统的定义:嵌入式系统是以应用为中心,以计算机技术为基础,软件、硬件可剪裁,适应应用系统对功能、可靠性、成本、体积和功耗严格要求的专用计算机系统。

2、OS 操作系统RTOS实时操作系统3、嵌入式系统具有哪些特点:(1)专用、软硬件可剪裁配置。

(2)低功耗、高可靠性、高稳定性。

(3)软件代码短小精悍。

(4)代码可固化(5)实时性(6)弱交互性(7)嵌入式系统软件开发通常需要专门的开发工具和开发环境。

(8)要求开发、设计人员有较高的技能。

4、嵌入式系统的组成结构:(1)硬件层,包括嵌入式微处理器、存储器(SDRAM、ROM、Flash等)、通用设备接口和I/O接口(A/D、D/A、I/O等)。

(2)中间层,将系统上层软件与底层硬件分开,使系统的底层驱动程序与硬件无关。

(3)软件层,由实时多任务操作系统(RTOS)、文件系统、图形用户接口(GUI)、网络系统及通用组件模块组成。

RTOS是嵌入式应用软件的基础和开发平台。

{嵌入式操作系统(EOS)负责嵌入系统的全部软硬件资源的分配、任务调度,控制、协调并发活动。

嵌入式文件系统主要提供文件存储、检索、更新等功能。

图形用户接口(GUI)极大的方便了非专业用户的使用,人们不再需要死记硬背大量的命令,取而代之的是可用通过窗口、菜单、按键等方式来方便的进行操作。

}(4)功能层,用来实现对被控对象的控制功能。

5、嵌入式系统硬件初始化:可以分为3个主要环节,按照自底向上、从硬件到软件的次序依次为:片级初始化、板级初始化、系统初始化。

1、目前嵌入式处理器以32位为主,其中以ARM处理器应用最为广泛。

2、采用RISC架构的ARM微处理器一般具有如下特点(1)体积小、低功耗、低成本、高性能。

(2)支持Thumb(16位)/ARM(32位)双指令集,能很好的兼容8/16位器件。

(3)大量使用寄存器,指令执行速度更快。

(4)大多数数据操作都在寄存器中完成。

(5)寻址方式灵活简单,执行效率高。

基于ARM的嵌入式程序开发要点

基于ARM的嵌入式程序开发要点ARM-CHINA-040415A基于ARM的嵌入式系统程序开发要点(一)——嵌入式程序开发过程ARM 系列微处理器作为全球16/32位RISC处理器市场的领先者,在许多领域内得到了成功的应用.近年来,ARM在国内的应用也得到了飞速的发展,越来越多的公司和工程师在基于ARM的平台上面开发自己的产品.与传统的4/8位单片机相比,ARM的性能和处理能力当然是遥遥领先的,但与之相应,ARM的系统设计复杂度和难度,较之传统的设计方法也大大提升了. 本文旨在通过讨论系统程序设计中的几个基本方面,来说明基于ARM的嵌入式系统程序开发的一些特点,并提出和解决了一些常见的问题.文章分成几个相对独立的章节刊载.第一部分讨论基于ARM的嵌入式程序开发和移植过程中的一些基本概念.1.嵌入式程序开发过程不同于通用计算机和工作站上的软件开发工程,一个嵌入式程序的开发过程具有很多特点和不确定性.其中最重要的一点是软件跟硬件的紧密耦合特性. (不带操作系统支持) (带操作系统支持)图-1:两类不同的嵌入式系统结构模型这是两类简化的嵌入式系统层次结构图.由于嵌入式系统的灵活性和多样性,上面图中各个层次之间缺乏统一的标准,几乎每一个独立的系统都不一样. 这样就给上层的软件设计人员带来了极大地困难.第一,在软件设计过程中过多地考虑硬件,给开发和调试都带来了很多不便;第二,如果所有的软件工作都需要在硬件平台就绪之后进行,自然就延长了整个的系统开发周期.这些都是应该从方法上加以改进和避免的问题.为了解决这个问题,工程和设计人员提出了许多对策.首先在应用与驱动(或API)这一层接口,可以设计成相对统一的一些接口函数,这对于具体的某一个开发平台或在某个公司内部,是完全做得到的.这样一来,就大大提高了应用层应用(Application)驱动/板级支持包(Driver/BSP)硬件(Hardware)应用(Application)硬件抽象层(HAL)硬件(Hardware)操作系统(OS)标准接口函数(API)基于ARM的嵌入式程序开发要点ARM-CHINA-040415A软件设计的标准化程度,方便了应用程序在跨平台之间的复用和移植.对于驱动/硬件抽象这一层,因为直接驱动硬件,其标准化变得非常困难甚至不太可能.但是为了简化程序的调试和缩短开发周期,我们可以在特定的EDA 工具环境下面进行开发,通过后再进行移植到硬件平台的工作.这样既可以保证程序逻辑设计的正确性,同时使得软件开发可平行甚至超前于硬件开发进程.我们把脱离于硬件的嵌入式软件开发阶段称之为"PC软件"的开发,可以用下面的图来示意一个嵌入式系统程序的开发过程."PC软件"开发移植,测试产品发布图-2:嵌入式系统产品的开发过程在"PC软件"开发阶段,可以用软件仿真,即指令集模拟的方法,来对用户程序进行验证.在ARM公司的开发工具中,ADS 内嵌的ARMulator和RealView 开发工具中的ISS,都提供了这项功能.在模拟环境下,用户可以设置ARM处理器的型号,时钟频率等,同时还可以配置存储器访问接口的时序参数.程序在模拟环境下运行,不但能够进行程序的运行流程和逻辑测试,还能够统计系统运行的时钟周期数,存储器访问周期数,处理器运行时的流水线状态(有效周期,等待周期,连续和非连续访问周期)等信息.这些宝贵的信息是在硬件调试阶段都无法取得的,对于程序的性能评估非常有价值.为了更加完整和真实地模拟一个目标系统,ARMulator和ISS还提供了一个开放的API编程环境.用户可以用标准C来描述各种各样的硬件模块,连同工具提供的内核模块一起,组成一个完整的"软"硬件环境.在这个环境下面开发的软件,可以更大程度地接近最终的目标.利用这种先进的EDA工具环境,极大地方便了程序开发人员进行嵌入式开发的工作.当完成一个"PC软件"的开发之后,只要进行正确的移植,一个真正的嵌入式软件就开发成功了.而移植过程是相对比较容易形成一套规范的流程的,其中三个最重要的方面是:考虑硬件对库函数的支持移植移植开发/实验/测试平台最终产品基于ARM的嵌入式程序开发要点ARM-CHINA-040415A符合目标系统上的存储器资源分布应用程序运行环境的初始化2.开发工具环境里面的库函数如果用户程序里调用了跟目标相关的一些库函数,则在应用前需要裁剪这些函数以适合在目标上允许的要求.主要需要考虑以下三类函数:访问静态数据的函数访问目标存储器的函数使用semihosting(半主机)机制实现的函数这里所指的C库函数,除了ISO C标准里面定义的函数以外,还包括由编译工具提供的另外一些扩展函数和编译辅助函数.2.1 裁剪访问静态数据的函数库函数里面的静态数据,基本上都是在头文件里面加以定义的.比如CTYPE类库函数,其返回值都是通过预定义好的CTYPE属性表来获得的.比如,想要改变isalpha() 函数的缺省判断,则需要修改对应CTYPE属性表里对字符属性的定义.2.2 裁减访问目标存储器的函数有一类动态内存管理函数,如malloc() 等,其本身是独立于目标系统而运行的;但是它所使用的存储器空间需要根据目标来确定.所以malloc() 函数本身并不需要裁剪或移植,但那些设置动态内存区(地址和空间)的函数则是跟目标系统的存储器分布直接相关的,需要进行移植.例如堆栈的初始化函数__user_initial_stackheap(),是用来设置堆(heap)和栈(stack)地址的函数,显然针对每一个具体的目标平台,该函数都需要根据具体的目标存储器资源进行正确移植.下面是对示例函数__user_initial_stackheap() 进行移植的一个例子:__value_in_regs struct __initial_stackheap __user_initial_stackheap( unsigned R0, unsigned SP, unsigned R2, unsigned SL){struct __initial_stackheap config;config.heap_base = (unsigned int) 0x;// config.stack_base = SP; // optionalreturn config;}基于ARM的嵌入式程序开发要点ARM-CHINA-040415A请注意上面的函数体并不完全遵循标准C的关键字和语法规范,使用了ARM公司编译器(ADS 或RealView Compilation tool) 里的C语言扩展特性.关于编译器特定的C语言扩展,请参考相关的编译器说明,这里简单介绍函数__user_initial_stackheap() 的功能,它主要是返回堆和栈的基地址.上面的程序中只对堆(heap) 的基地址进行了设置(设成了0x),也就是说用户把0x开始的存储器地址用作了动态内存分配区(heap区).具体地址的确定是要由用户根据自己的目标系统和应用情况来确定的,至少要满足以下条件: 0x开始的地址空间有效且可写(是RAM)该存储器空间不与其它功能区冲突(比如代码区,数据区,stack区等)因为__user_initial_stackheap() 函数的全部执行效果就是返回一些数值,所以只要符合接口的调用标准,直接用汇编来实现看起来更加直观一些: EXPORT __user_initial_stackheap__user_initial_stackheapLDR r0,0xMOV pc,lr如果不对这个函数进行移植,编译过程中将使用缺省的设置,这个设置适用于ARM公司的Integrator系列平台.(注意:ARM的编译/连接工具链也提供了绕过库函数来设置运行时存储器模型的方法,请参阅ARM公司其他的相关文档.)2.3 裁剪使用semihosting(半主机)机制实现的函数库函数里有一大部分函数是涉及到输入/输出流设备的,比如文件操作函数需要访问磁盘I/O,打印函数需要访问字符输出设备等.在嵌入式调试环境下,所有的标准C库函数都是有效且有其缺省行为的,很多目标系统硬件不能支持的操作,都通过调试工具来完成了.比如printf() 函数,缺省的输出设备是调试器。

实验四_ARM键盘显示电路驱动程序设计

键盘显示电路驱动程序设计实验目的1、了解ARMC语言程序的结构特点2、了解ARMC语言程序的编写方法3、掌握用ARM编写HD7279控制程序方法实验仪器设备及软件ARM实验箱,计算机,ADS程序开发软件实验原理HD7279A专用键盘显示电路,真正的单片LED数码管显示和键盘接口芯片,无需外围电路,只需要外接少量的电阻等,即可构成完善的显示、键盘接口电路。

而与CPU的接口采用SPI串行接口方式,使用方便。

可方便的构成64按键,8位数码显示电路(共阴极结构)HD7279A内部含有译码器,可直接受BCD码或16进制数据或七段显示码数据。

此外, 还具有多种控制指令,如消隐,闪烁,左移,右移,段寻址等。

具有片选信号,可方便地实现多于8位的显示或多于64键的键盘接口。

HD7279的纯指令:1、复位指令(A4H)当HD7279A收到该指令后,将所有显示清除,所有设置的字符消隐、闪烁等属性也被一起清除。

执行后,芯片的状态与上电时一样。

2、测试指令(BFH)该指令使所有的LED全部点亮,并处于闪烁状态,主要用于测试(检查LED是否坏)3、左移指令(A1H)使所有显示左移一位,消隐及闪烁属性不移位,最右边一位为空(暗)。

如:HD7279带数据的指令:1、下载数据按方式0译码命令由两字节构成,前半部为指令。

a2,a1,a0为位地址,D3-D0为数据,译码值如图所示。

aO DP?<X X d3d2di dO 10000□1DP DP=1DP=O 2、下载数据按方式1译码指令格式与指令1相同,译码表如下所示。

3此命令控制各数码管的闪烁情况。

D8-D1中的位为1时,对应位闪烁。

上电默认不闪烁。

5、消隐控制98HD8-D1控制数码管的消隐状态。

为 1时,数码管消隐,为0时,正常显示。

输入的数据至少有一位为0。

输入全为0时,命令将被忽略。

6、读键盘命令该指令从HD7279中读出当前按键编码。

编码范围是0-3FH 。

当HD7279收到读指令时, 此时按键无效,将返回 0FFH 。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

ARM 复习要点  SOC的System是指什么意思?  Real time该如何正确解释?  ARMV3,ARMV4版本各增强了那些特性?  ARM9与ARM7相比有哪些特点?  RISC机器的特点有那些

 ARM哪两种状态?如何进行状态的切换?  ARM处理器有那7种模式?系统复位的时候处于那种模式?  寄存器安什么标准分组的?R15,R14,R13的特殊用途是什么?  程序状态寄存器最低8位 的含义是什么?  ARM体系结构支持哪些异常?与处理器的模式有何关系?异常向量的入口地址是多少?  ARM微处理器对异常是如何响应和返回的?

 ARM有那七种寻址方式?为什么说ARM指令的寻址方式比较少?(因为存储加载指令的寻址方式最多,也只有四种寻址方式。)  符合什么样的规律的常数,可以作为mov指令的立即数?它是怎么样保存在指令中的?  如何禁止或者使能FIQ或IRQ?写出对应的汇编代码(通过对CPSR寄存器进行操作)  在汇编代码中align表示对齐的意思,请问align 5表示按多少字节对齐?

 CP15管理的是ARM的存储单元,管理那几个部分?(cache,mmu,write buffer)  Cache为什么能够提高系统的性能?(局部性原理,程序具有局部性特征)  Cache的主要属性包含哪些?(大小,行大小,相联特性,写策略,置换函数等)  Cache的工作原理,用图式表示。  Mmu的作用是什么?(虚拟地址到物理地址的转换,内存保护)  Mmu的组成部分(TLB,页表浮动逻辑,访问逻辑)  Mmu的工作原理,用图式表示。

 掌握bootloader的基本作用。(系统启动,和操作系统的加载)  掌握bootloader的启动流程.(异常向量表,关闭看门狗,中断等,参考vboot的执行代码)  掌握如何禁用或者使能mmu、cache的方法。(操作cp15的c1寄存器)  Linux内核的配置,包括system type,驱动,文件系统的类型等。以及如何对内核进行交叉编译。  理解linux内核下编程的特点。(linux kernel development第一,二章)  能够设置nfs作为开发板的根文件系统  能够手动搭建自己的跟文件系统目录. 1. Proc, sys, tmp, var只需要建立空目录 2. Bin,sbin,linuxrc来自与busybox的生成。 3. Lib来自于交叉编译工具的目录 4. Dev的设备节点可以手动创建。Mknod 5. Etc下的配置文件。 在Linux操作系统下有3类主要的设备文件类型:块设备、字符设备和网络设备。这种分类方法可以将控制输入/输出设备的驱动程序与其他操作系统软件分离开来。

字符设备与块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般紧接着发生。块设备则不然,它利用一块系统内存作为缓冲区,若用户进程

对设备的请求能满足用户的要求,就返回请求的数据;否则,就调用请求函数来进行实际的I/O操作。块设备主要是针对磁盘等慢速设备设计的,以免耗费过多的

CPU时间用来等待。网络设备可以通过BSD套接口访问数据。 每个设备文件都有其文件属性(c/b),表示是字符设备还是块设备。另外每个文件都有2个设备号,第一个是主设备号,标识驱动程序;第二个是从设备号,标识使用同一个设备驱动程序的、不同的硬件设备。设备文件的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问驱动程序。

系统调用时操作系统内核与应用程序之间的接口,设备驱动程序是操作系统内核与机器硬件之间的接口。设备驱动程序是内核的一部分,它完成以下功能:

●对设备初始化和释放 ●把数据从内核传送到硬件和从硬件读取数据 ●读取应用程序传送给设备文件的数据和回送应用程序请求的数据 ●检测和处理设备出现的错误 MTD(Memory Technology Device)设备是闪存芯片、小型闪存卡、记忆棒之类的设备,它们在嵌入式设备中的使用正在不断增加。MTD驱动程序是在Linux下专门为嵌入式环境开发的新的一类驱动程序。相对于常规块设备驱动程序,使用MTD驱动程序的优点在于他们能更好的支持、管理给予闪存设备,有基于扇区的擦除和读/写操作的更好的接口。

驱动程序结构 Linux的设备驱动程序可以分为3个主要组成部分: 1. 自动配置和初始化子程序,负责监测所要驱动的硬件设备是否存在和能否正常工作。如果该设备正常,则对这个设备及其相关的设备驱动程序需要的软件状态进行初始化。这部分驱动程序仅在初始化时被调用一次。

2.服务于I/O请求的子程序,又称为驱动程序的上半部分。调用这部分程序是由于系统调用的结果。这部分程序在执行时,系统仍认为是与进行调用的进程属于同一

个进程,只是由用户态变成了核心态,具有进行此系统调用的用户程序的运行环境,因而可以在其中调用sleep()等与进行运行环境有关的函数。

3.中断服务子程序,又称为驱动程序的下半部分。在Linux系统中,并不是直接从中断向量表中调用设备驱动程序的中断服务子程序,而是由Linux系统来接 收硬件中断,再由系统调用中断服务子程序。中断可以在任何一个进程运行时产生,因而在中断服务程序被调用时,不能依赖于任何进程的状态,也就不能调用任何

与进程运行环境有关的函数。因为设备驱动程序一般支持同一类型的若干设备,所以一般在系统调用中断服务子程序时,都带有一个或多个参数,以唯一标识请求服

务的设备。 在系统内部,I/O设备的存/取通过一组固定的入口点来进行,这组入口点是由每个设备的驱动程序提供的。具体到Linux系统,设备驱动程序所提供的这组入口点由一个文件操作结构来向系统进行说明。file_operation结构定义于linux/fs.h文件中。

struct file_operation{ int (*lseek)(struct inode *inode, struct file *filp, off_t off, int pos); int (*read)(struct inode *inode, struct file *filp, char *buf, int count); int (*write)(struct inode *inode, struct file *filp, const char *buf, int count); int (*readdir)(struct inode *inode, struct file *filp, struct dirent *dirent, int count); int (*select)(struct inode *inode, struct file *filp, int sel_type, select_table *wait); int (*ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned int arg); int (*mmap)(void…………); int (*open)(struct inode *inode, struct file *filp); int (*release)(struct inode *inode, struct file *filp); int (*fasync)(struct inode *inode, struct file *filp); }; file_operation结构中的成员几乎全部是函数指针,所以实质上就是函数跳转表。每个进程对设备的操作都会根据major、minor设备号,转换成对file_operation结构的访问。

常用的操作包括以下几种: ●lseek, 移动文件指针的位置,只能用于可以随机存取的设备。 ●read, 进行读操作,参数buf为存放读取结果的缓冲区,count为所要读取的数据长度。返回值为负表示读取操作发生错误;否则,返回实际读取的字节数。对于字符型,要求读取的字节数和返回的实际读取字节数都必须是inode-i_blksize的倍数。

●write, 进行写操作,与read类似 ●readdir, 取得下一个目录入口点,只有与文件系统相关的设备程序才使用。 ●select, 进行选择操作。如果驱动程序没有提供select入口,select操作会认为设备已经准备好进行任何I/O操作。

●ioctl, 进行读、写以外的其他操作,参数cmd为自定义的命令 ●mmap, 用于把设备的内容映射到地址空间,一般只有块设备驱动程序使用 ●open, 打开设备准备进行I/O操作。返回0表示打开成功,返回负数表示失败。如果驱动程序没有提供open入口,则只要/dev/driver文件存在就认为打开成功。

●release, 即close操作。 在用户自己的驱动程序中,首先要根据驱动程序的功能,完成file_operation结构中函数实现。不需要的函数接口可以直接在file_operation结构中初始化为NULL。file_operation变量会在驱动程序初始化时注册到系统内部。当操作系统对设备操作时,会调用驱动程序注册的file_operation结构中的函数指针。

Linux对中断的处理 在Linux系统里,对中断的处理是属于系统核心部分,因而如果设别与系统之间以中断方式进行数据交换,就必须把该设备的驱动程序作为系统核心的一部分。设备驱动程序通过调用request_irq函数来申请中断,通过free_irq来释放中断。它们被定义为:

int request_irq(unsigned int irq, void (*handler)(int irq, void dev_id, struct pt_regs *regs), unsigned long flags, const char *device, void *dev_id); void free_irq(unsigned int irq, void *dev_id); 参数irq表示所要申请的硬件中断号;handler为向系统登记的中断处理子程序,中断产生时由系统来调用,调用时所带参数irq为中断号;dev_id

为申请时告诉系统的设备标识;regs为中断发生时的寄存器内容;device为设备名,将会出现在/proc/interrupts文件里;flag是

申请时的选项,它决定中断处理程序的一些特性,其中最重要的是中断处理程序是快速处理程序还是慢速处理程序。快速处理程序运行时,所有中断都被屏蔽,而慢

相关文档
最新文档