收藏 分享(赏)

2440嵌入式软件_硬件常识new.doc

上传人:dzzj200808 文档编号:2235523 上传时间:2018-09-06 格式:DOC 页数:22 大小:835.50KB
下载 相关 举报
2440嵌入式软件_硬件常识new.doc_第1页
第1页 / 共22页
2440嵌入式软件_硬件常识new.doc_第2页
第2页 / 共22页
2440嵌入式软件_硬件常识new.doc_第3页
第3页 / 共22页
2440嵌入式软件_硬件常识new.doc_第4页
第4页 / 共22页
2440嵌入式软件_硬件常识new.doc_第5页
第5页 / 共22页
点击查看更多>>
资源描述

1、嵌入式软件开发人员,硬件常识底层的驱动或内核开发人员通常要跟硬件紧密的配合,协同完成工作.硬件电路的设计很大程度上决定驱动代码的代码的编写.一个熟练的底层开发人员具备硬件开发知识本节内容. 硬件开发流程 硬件识图 软件控制硬件方法 嵌入式 C 语言硬件开发知识 大致清楚硬件的设计和生产流程. 清楚自已工作中常用的硬件器件的工作原理. 要有看懂硬件原理图的能力.主要涉及影响到编程的关键的连线和管脚的一定要看懂. 要看懂硬件(主要是能编程控制的集成电路 ,简称 IC)的编程资料 ,一般是称为DataSheet 的 PDF 文档.主要各个寄存器的设置,和常见任务的处理流程软件相关能力 要知道如何用编

2、程语言(主要是 C,和少量的汇编)去控制硬件. 还要熟悉底层软件与操作系统的接口. 象同一款硬件,原始的控制代码是基本上一样的,但是各个操作系统对驱动与OS 的接口,完全不一样.Windows 系列的驱动接口远比 Linux 复杂得多.各个操作系统也提供了不同底层函数接口用于开发,这些都需要熟练掌握的. 具有调试底层软件的能力,除了常用的软件调试手段,(如单步 DEBUG,查看输出信息.)有时可能需要动用软件, 和硬件检测设备来调试 如网络调试,可能需要抓包软件,基于硬件的流量测试仪 基于硬件的电路的仪器,如万用电表,显波器和逻辑分析仪 基于无线的设备,可能需要无线信号发生器或基站模拟设备在底

3、层软件开发领域,还有一些非标准 CPU 的分支开发领域,由于采用接近于 CPU 的复杂结构,因此必须用的编程语言去开发,但又不是普通的 gcc 那样的开发环境.而是自己独立的开发环境.很多嵌入式工程师需要常握其中一种工具 常用数据处理,如音频,加密,视频影像处理的 DSP,都会有自已独立的开发环境,有的是接近汇编级的语法代码,更高级是类似于 C 的编程语言.常见的 DSP 开发环境有TI 的 CCP. 在网络流量很大的地方,如核心路由器,大型的防火墙,网关,等,这一些设备有时用软件已经无法处理.往往采用基于网络处理器的的方案,网络处理器会在硬件直接处理网络包,这些网络处理器也有独立的开发环境用

4、于开发.如 Intel 的 IXP 系列. FPGA,CPLD (VHDL)用类似于 Basic 或 C 语言的开发语言去设计硬件,如 MaxPlus II labView 虚拟仪器.硬件产品设计流程与软件不同,一个硬件产品的从最基本的器件到最终产品的出产,是一个全球化高度合作的结果.牵涉一个完整的产业链的方方面面.因此必须需要高度工程化的管理和生产技术.否则不可能生产出合格产品.以一台手机生产而言.它的技术标准和研发可能是在欧美的大公司或大学的研究机制进行.如 Nokia 和爱立信,高通等来进行研发的.当技术成熟后,可能在美国的 IC 设计公司(如 TI)设计出可以满足实际产品的集成电路,这

5、个集成电路的生产,出厂测试等流程可能是在台湾新竹的台积电,联电的 IC 生产工厂代工.单独的 IC 并不能形成产品,必须要焊接在电路板上,和其它电件组成完整的电路.这是一个风险很高的设计过程.以前要由最终的产商完成这样的工作,这样会花费很长的时间和资金,并且有可能失败.现在流行的趋势是由专业的设计公司负责完成硬件电路和底层软件的设计,甚至是应用程序的开发,这大大降低了生产厂家的门槛.象手机设计里最有名的是 MTK(联发科技), 它提供底层的 IC 到硬件电路方案 ,+软件方案的全套设计.这样很多小厂也能直接生产手机.号称是黑手机之父,这几年的大量的手机上市,它功不可没.也造就它成为台湾股市的股

6、王.在低端 MP3,MP4 领域里,采用相同策略是位于珠海的 炬力,它也推出 MP3 和 MP4 播放器从 IC 到硬件设计方案,软件的全套设计方案.造成现在 MP3,MP4 市场大规模爆发.如果是从元器件开始设计一个电子产品.第一阶段是硬件工程师要根据参考方案和文档,设计出一个硬件原理图来.主要用来验证电路产否能正常正确,确定硬件的连线等工作.类似于产品硬件设计模型.这一项工作一般是由一个公司最有经验的工程师来完成.原理图都是一个逻辑表示,比如元器件用示意图表示,连线也不会跟最终产品的走线一模一样.IC 是高度集成的精密器件,不可能象电气设备一样,直接拉线就行.通常会在一个缚有一层导电金属层

7、的绝缘板用化学方法”刻”一根一根的导线.然后再焊接上去.这种板就称为 PCB( Printer Circuit Board).这种方法有很多优点,节约空间,防止干扰,焊接点小,并且牢固.集成度高,因此现代的电子元件互联完全采用 PCB 板来制作.因此硬件设计第二阶段就要是把原理图设计成供生产的 PCB 图.类似于建筑施工图,里面的设计布局将会跟实际产品开发一规一模.PCB 也是取决于设计经险,但很多是重复劳动,在很多小的公司往往采用外包的方式让专业的 PCB 公司来代为设计,深圳就有大量公司或工作室来代人完成 PCB 设计 .原理图设计,和 PCB 设计都需要专用软件来完成 .现在有设计软件从

8、几十 W 到几 W 的软件都是,象常用的 Prototel ,PowerLogic/PowerPCB 是比较流行的硬件设计.可以完成二阶段设计.高端设计软件有 Cadence.当完成 PCB 设计后,一方面准备制作 PCB 板了.由于 PCB 的制作设备非常昂贵.一般是由专门 PCB 生产厂家来代工 .深圳是中国以及世界上最集中 PCB 产业地,拥有大量 PCB 制作厂家.另一方面由 PCB 图导出 BOM(元器件清单) 交由采购部门进行采购 .现代的 IC 的管脚已经越来越复杂,采用手工焊接效率低,失败高,往往需要专门焊接厂进行全自动的焊接.深圳拥有大量焊接工厂.往往是 PCB 制版厂业务之

9、一.当一个产品完成后,就要设计吸引人的产品外壳,这称为结构设计.比较简单的是用金属冲压件.如果电脑机箱,机柜之类.优点设计成本低,可以快速实现.缺点就是一般只能是带直角的设计.外形过于简单. 现在大部分电子产品采用塑料外壳.优点可以做出非常复杂的外形.并且可以采用不同材质进行组合.缺点是设计复杂,并且要用设计专用模具来生产.现在结构设计软件有 普遍采用 Pro/E 或 UG 来进行设计.也有人使用 AutoCAD 来设计.现在结构设计一般也是外包给专业的设计公司进行设计.很多产商为了节约成本,往往采用模具厂预先做的好模具,这个称为” 公模”.欧美市场对环保有极为严格的要求,如果产品要销往欧美市

10、场,往往需要使用无铅的焊锡,油漆.电磁辐射也有强制要求.以有其它的准入门槛.如欧盟的 CE 认证,美国的 UL 认证,FCC 认证等,这一些都是强制标准,必须先在先由认证的代理机构认证后.才能在上述市场销售.这是必须一个环节.电路图的识图能力常见电路图有三大类框图(BLOCK DIAGRAM),原理图和PCB图,时序图框图用于描述系统结构,一般用于文档描述.原理图用于系统原理设计.同时进行底层软件编程时往往需要多次查阅原理图的设计.PCB 图用于实际生产.软件编程一般不需要查看PCB 图.底层软件人员往往需要了解是时序图(Timing),用于反映多个信号源(或管脚)之间信号的相互关系。因为一个

11、硬件完成一项工作必须是多个管脚协同工作。而且往往有时间顺序上的要求。而时序图就是反应这种时间上的信号之间相互关系的图形,大量于IC的设计文档,在实例运行中,往往也可以用显波器之类设备测量出这种波形关系。用于协助软件人员调试错误。S3C2440的原理框图QQ2440部分原理图一个S3C2410开发板的 PCB图信号时序图(Timing)SPI总线时序常用时序图NAND Flash 控制时序图,有规则的波形(HCLK)一般用于表示时钟信号,用于不同信号计时。上例中,表示在第二个时钟周期时,CLE/ALE的必须由低平切换为高电平。在第三个时钟周 期,new由高电平变为低电平。用双线表示波形,即DAT

12、A,表示高低电平不确定,必须取决于当时应用的情况。比如在这个例子,DATA在有效的时钟周期,传输是不同命令或地址。一个复杂的时序图内存控制器的时序图软件控制硬件方法作为一个嵌入式软件开发人员,必须熟悉如何控制硬件.首先从技术要确定项目开发采用哪种 CPU.这取决项目人员技术背景,产品以前经验以技术特点等.一般公司尽可能采用同一种 CPU 来开发不同产品.这样可以最大可能节约成本,并且技术风险比较小.当确定的 CPU 后,研发人员就要研究的 CPU 相关文件.指令集和测试程序.这一些都要在项目开始前完成.硬件 IC 的手机通常是 PDF 格式的.称为 DataSheet.CPU 的 datash

13、eet 是相当于一本厚厚的技术词典.如 S3C2440 的 datasheet 有 596 页.如果要控制比较复杂的外部设备,通常还要去阅读相应的手册.因此在开发前,最好尽可能阅读尽可能多的手册.以 S3C2440 CPU 为例.首先要了解一下 CPU 的框图,了解这一款 CPU 的大致部件.从这个框图可以看到,这一款 CPU 具备的基本硬件包括内存,LCD,串行端口.电源等.这几个也是嵌入式系统中最常见到的几项装置.另外这个 CPU 还提供了许多的 GPIO(General Purpose I/O)管脚,让设计者可以根据自已的需求来控制这一些外围设备,这是一个很典型的一种做法.如果这些外围还

14、是不够的话,就要自已加控控制芯片,拉到地址线(address line)及总线(bus line)上,通过这些线来控制外围,像是 SDRAM 或是 Flash 就是通过地址线与总线来存取数据.有三个概念要分清楚,存储器,I/O 端口,寄存器.寄存器是指 CPU 和外设内部的存储单元,数量有限,但速度快,分通用寄存器和特殊功能寄存器(比如 pc,sp 等) 。不同 CPU 寄存器宽度是不一样的.8 位单片机表示地址线和数据为 8 位大小.寄存器宽度也是 8 位,在 C 程序中正好可以用一个 char 数据类型来操作.主流 32 位 CPU 的寄存器就是 32 位宽度.正好用一个 32 位,在程序

15、中可以用一个 unsigned int 来操作.CPU 的寄存器或地址位的宽度称为 WORD(字 )通常说的存储器都是独立于 CPU 之外的,比如内存,硬盘,光盘等.CPU 本身几乎每一种外设都是通过读写设备上的寄存器来进行操作的。外设寄存器也称为“I/O 端口 ”,通常包括:控制寄存器、状态寄存器和数据寄存器三大类,而且一个外设的寄存器通常被连续地编址。CPU 对外设 IO 端口物理地址的编址方式 有两种:一种是I/O 映射方式(I/Omapped) ,另一种是存储空间映射方式(Memorymapped) 。而具体采用哪一种则取决于 CPU 的体系结构。有些体系结构的 CPU(如,Power

16、PC 、m68k 等)通常只实现一个物理地址空间(RAM) 。在这种情况下,外设 I/O 端口的物理地址就被映射到 CPU 的单一物理地址空间中,而成为存储空间的一部分。此时,CPU 可以象访问一个内存单元那样访问外设 I/O 端口,而不需要 设立专门的外设 I/O 指令。这就是所谓的“存储空间映射方式”(Memorymapped ) 。ARM 体系的 CPU 均采用这一模式.而另外一些体系结构的 CPU(典型地如 X86)则为外设专门实现了一个单独地地址空间,称为“I/O 地址空间”或者 “I/O 端口空间” 。这是一个 与 CPU 的 RAM 物理地址空间不同的地址空间,所有外设的 I/O

17、 端口均在这一空间中进行编址。CPU 通过设立专门的I/O 指令(如 X86 的 IN 和 OUT 指 令)来访问这一空间中的地址单元(也即 I/O 端口) 。这就是所谓的“I/O 映射方式 ”(I/O mapped) 。与 RAM 物理地址空间相比,I/O 地址空间通常都比较小,如 x86 CPU 的 I/O 空间就只有 64KB(00xffff) 。这是“I/O 映射方式”的一个主要缺点。而且必须要专门的汇编语言才能处理.Linux 即在 X86 运行,也在 ARM 之类运行.为了简化操作 ,Linux 在所以 CPU 上都采用I/O 端口概念.如果是象 ARM 这样内存映射.也被模拟成端

18、口.在非操作系统模式下.一般直接采用内存取读模式.在 ARM 下,所有外设的寄存器都被映射到一个 4G 空间.并且是有固定的映射地址.(注意要与操作系统下的映射 2G 地址空间分开,那是操作系统给每个进程模拟的空间,I/O 地址实际映射物理地址空间)以下是在 S3C 2440 的 Nand/Nor 在设备空间映射地址空间所有 S3C2440 寄存器地址映射表写在手册 55 页(1-32)如下例就是内存控制器相关的寄存器地址设置一般的 PC 机和 ARM 板都带有外接电池供电的 RTC(REAL TIME CLOCK 实时时钟)芯片,即便是切断的外接电源,RTC 电路记录的时间也会按真实时间流逝

19、而做相应变化 .假设现在要使用 RTC 电路.即从 RTC 电路存储的时间信息读取出来 .首先根据地址表找出 RTC 电路寄存器相关地址 .(S3C2440 芯片手册 P66)其中存储年月日小时分钟,秒的的寄存器分别是 BCDSEC,BCDMIN,BCDHOUR,BCDDATE,BCDDAY,BCDMON,BCDYEAR.地址从0x570000770x5700008B 地址 .在 C 语言中为,方便程序编写 ,往往把寄存器定义为宏,这样当 CPU 微调的寄存器定义,程序不需要重写.参见 2440addr.h 的定义/ RTC#ifdef _BIG_ENDIAN#define rRTCCON (

20、*(volatile unsigned char *)0x57000043) /RTC control#define rTICNT (*(volatile unsigned char *)0x57000047) /Tick time count#define rRTCALM (*(volatile unsigned char *)0x57000053) /RTC alarm control#define rALMSEC (*(volatile unsigned char *)0x57000057) /Alarm second#define rALMMIN (*(volatile unsigne

21、d char *)0x5700005b) /Alarm minute#define rALMHOUR (*(volatile unsigned char *)0x5700005f) /Alarm Hour#define rALMDATE (*(volatile unsigned char *)0x57000063) /Alarm date /edited by junon#define rALMMON (*(volatile unsigned char *)0x57000067) /Alarm month#define rALMYEAR (*(volatile unsigned char *)

22、0x5700006b) /Alarm year#define rRTCRST (*(volatile unsigned char *)0x5700006f) /RTC round reset#define rBCDSEC (*(volatile unsigned char *)0x57000073) /BCD second#define rBCDMIN (*(volatile unsigned char *)0x57000077) /BCD minute#define rBCDHOUR (*(volatile unsigned char *)0x5700007b) /BCD hour#defi

23、ne rBCDDATE (*(volatile unsigned char *)0x5700007f) /BCD date /edited by junon#define rBCDDAY (*(volatile unsigned char *)0x57000083) /BCD day /edited by junon#define rBCDMON (*(volatile unsigned char *)0x57000087) /BCD month#define rBCDYEAR (*(volatile unsigned char *)0x5700008b) /BCD year#else /Li

24、ttle Endian#define rRTCCON (*(volatile unsigned char *)0x57000040) /RTC control#define rTICNT (*(volatile unsigned char *)0x57000044) /Tick time count#define rRTCALM (*(volatile unsigned char *)0x57000050) /RTC alarm control#define rALMSEC (*(volatile unsigned char *)0x57000054) /Alarm second#define

25、 rALMMIN (*(volatile unsigned char *)0x57000058) /Alarm minute#define rALMHOUR (*(volatile unsigned char *)0x5700005c) /Alarm Hour#define rALMDATE (*(volatile unsigned char *)0x57000060) /Alarm date / edited by junon#define rALMMON (*(volatile unsigned char *)0x57000064) /Alarm month#define rALMYEAR

26、 (*(volatile unsigned char *)0x57000068) /Alarm year#define rRTCRST (*(volatile unsigned char *)0x5700006c) /RTC round reset#define rBCDSEC (*(volatile unsigned char *)0x57000070) /BCD second#define rBCDMIN (*(volatile unsigned char *)0x57000074) /BCD minute#define rBCDHOUR (*(volatile unsigned char

27、 *)0x57000078) /BCD hour#define rBCDDATE (*(volatile unsigned char *)0x5700007c) /BCD date /edited by junon#define rBCDDAY (*(volatile unsigned char *)0x57000080) /BCD day /edited by junon#define rBCDMON (*(volatile unsigned char *)0x57000084) /BCD month#define rBCDYEAR (*(volatile unsigned char *)0

28、x57000088) /BCD year#endif /RTC 其中 volatile 是 C 的保留字,通知编译器,不要自动优化这个地址所对应的变量值为0,因为寄存器的值往往是有含义的,并且是由硬件自动来设置的.强制设为 0 可能会带来错误. #define rRTCCON (*(volatile unsigned char *)0x57000043) /RTC control 表示取地址 0x57000043 对应内存的地址 volatile unsigned char *, volatile unsigned short *, volatile unsigned int * 表示处理对应

29、地址的宽度/范围,分别是 1,2,4 Byte,在寄存器地址强制转换成哪一种类型,取决于这一寄存器的有效位,如 rRTCCON 只用到 4 位,转换成一个 char * 即可 所有有寄存器用 unsigned 来强制因为寄存器里所有位都是有效的数据位.而有符号会把最高位看成符号位.这样经常容易产生错误, 用 unsigned 另外要还要考虑到有符号右移位操作符号位不动,即算术右移.在底层编程往往是错误的.接着可以参考 CPU 手册的寄存器详细定义(457 页),其中描述了每一位的格式 .接着按程序初始化一个固定的年月日void RTC_Time_Set( void )rRTCCON = 1 ;

30、 /RTC read and write enablerBCDYEAR = 0x05 ; /年rBCDMON = 0x06 ; /月rBCDDATE = 0x19 ; /日rBCDDAY = 0x02 ; /星期rBCDHOUR = 0x15 ; /小时rBCDMIN = 0x21 ; /分rBCDSEC = 0x30 ; /秒/1 取反,表示 0x11111110 ,与上 rRTCCON 表示把最低 0 位置 0,其余位不变rRTCCON /RTC read and write disable/置 1 采用或操作/rRTCCON |= 1; 读取时间电路void RTC_Display(vo

31、id) U16 year ;U8 month, day ; / weekU8 hour, minute, second ;RTC_Time_Set() ;Uart_Printf( “RTC TIME Display, press ESC key to exit !n“ ) ;while( Uart_GetKey() != ESC_KEY )rRTCCON = 1 ; /RTC read and write enableyear = 0x2000+rBCDYEAR ; /年month = rBCDMON ; /月day = rBCDDATE ; /日/ week = rBCDDAY ; /星期h

32、our = rBCDHOUR ; /小时minute = rBCDMIN ; /分second = rBCDSEC ; /秒rRTCCON /RTC read and write disableUart_Printf( “RTC time : %04x-%02x-%02x %02x:%02x:%02xn“, year, month, day, hour, minute, second );Delay( 900 ) ;嵌入式 C 语言寄存器定义解释参见寄存器定义#ifdef _BIG_ENDIAN#define rBCDSEC (*(volatile unsigned char *)0x5700

33、0070)#else从上述定义中,请思考,如下问题 为什么要分字节序符定义? volatile 表示什么含意 ? 为什么要用无符号的数字? 宏定义的最前面*表示什么含意? 为什么要分字节序符定义?寄存器的地址位于一个线性空间上.但是不同字节序下,同一寄存器的地址会发生变化.这可参见 CPU 的手册,为了隐藏这个细节,所以定义两套.另外,我们已经 32 位寄存器的各个位的固定的.不同的 CPU 字节序有不同结果,这样进行对位操作时.同一个寄存值在不同字节序下,会产生不同位排列.因此为防止字节序对寄存器进行干扰.后面的 ADS 的 C 代码一般会直接采用大端字节序.在 Linux 下很多时候会采用

34、移位来排除字节序的干扰. volatile 表示什么含意?volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。volatile 区分 C 程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS 等等打交道,所有这些都要求用到 volatile 变量。不懂得 volatile 的内容将会带来灾难。当要求使用 volatile 声明的变量的值时,系统总是重新从它所在的内存读取数据,即使它前面的指

35、令刚刚从该处读取过数据。而且读取的数据立刻被保存。如果一个变量没有 volatile,编译器会自动进行优化 ,比如说自动清 0.如果这个整数是一个多线程,或硬件地址.这样可能会带来意想不到结果.Volatile 的应用场合 存储器映射的硬件寄存器通常也要加 volatile 说明,因为每次对它的读写都可能由不同意义,如并行设备的硬件寄存器(如:状态寄存器) 中断服务程序中修改的供其它程序检测的全局变量需要加 volatile,如一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 多任务环境下各任务间共享的数据,如多线程应用中被几个任务共享的变量 为什么要

36、用无符号的数字?我们知道,数字有两种移位,一种是算术移位,一种逻辑移位.其中前者在有符号位的情况下,会对符号位做特殊处理.而且寄存器对应就是原始位,最高位也有特定的含意.这种情况下,指定为无符号位数是了防止编译器对最高位采用特殊算术移位.从而违反了设计者的本意. 宏定义的最前面*表示什么含意?表示取指针的内容,类似于 char *p= *p=A,但这里不是一个变量,而且是一个常量地址.但效果是一样的,相当于取对应地址的内容.或者这个地址赋值寄存器操作因为每个寄存器都 32 位宽,因此在程序中可把寄存器的值看成一个无符号整数,对寄存器的取值看成是取一个整数值,而对寄存器设置看成是对一个整数变量赋

37、值. 置某一位为 01 置第一位为 0/1 取反,表示 0x11111110 ,与上 rRTCCON 表示把最低 0 位置 0,其余位不变rRTCCON /RTC read and write disable2.置第三位为 0/0x0100 取反。再与上相应的寄存器地址rRTCCON 3假设置 12-13 bit 的为 0 ,则二进制展开为 11000000000000,换算为 0x3000rADCDAT0 4.置采用左移,或右移来置位,以置 14bit 为 0 例rADCDAT0 以初始化一个 Nand Flash 为例.#define TACLS 0x01rNFCONF = (TACLS1

38、2)|(TWRPH08)|(TWRPH14)|(00);rNFCONT = (013)|(012)|(010)|(09)|(08)|(16)|(15)|(14)|(11)|(10);而这两个寄存器的详细取值可以查看P224 页现在把 rNFCONF 值折成如下值 TACLS 14:12 CLE /set GPB0 as tout0, pwm outputrGPBCON |= 2; /其中 0x03 的二进制表示 00000011,取反就是 11111100.与上(&)它,表示把低 1,低 2 位置0. (P284 页)查询手册rGPBCON &= 3 表示把 GPB0 端口设为 00,即设为 input 端口.再次把执行 rGPBCON |= 2 即把 GPB0 设为 0x2 = 00000010 ,即 TOUT0 的端口.

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报