源码开放学ARM,源码开放学ARM@亚嵌李明老师1

软件 0
2012-12-04 1ThisisthePDFfileforthehowtowriteopensourcebookcontents.ItislicensedundertheCreativeCommonsAttribution-NonCommercial-ShareAlike3.0license.Ihopeyouenjoyit,Ihopeithelpsyoulearnthesoftwaredevelopment,andIhopeyou’llcontinuouslywatchthis:/LASO/,willbehappyifyoufollowmyweibo/limingth 前言 学习目标 ARM阶段的学习,构成了嵌入式软件开发工程师知识体系中不可缺少的一个内容。
在这个阶段我们努力培养学员具备以下的素质和能力: *掌握ARM体系结构和汇编语言。
*能够初步学会阅读硬件原理图和芯片数据手册。
*具备为SoC芯片常见外设如UART,NandFlash,Timer等编写驱动程序的能力。
*能够完成Bootloader项目的程序编写和移植工作。
适合对象 本阶段对于学员学习基础的要求如下:*掌握C语言,熟悉指针的用法。
*学过计算机组成原理和数字电路等课程。
*具备一定的英文阅读能力。
*对计算机底层的运行机制和软硬件协同工作具有浓厚的兴趣。
如何写作本书的 对于有志于参与本书编写的学员,可以通过学习以下内容来进一步了解关于如何写书的相关知识。
如何安装GIT * 如何使用GitHub * 如何用markdown写书 */larrycai/write-book-in-markdown 如何生成pdf版本 */larrycai/kaiyuanbook/blob/master/BUILD.md 简介轻量级标记语言Markdown * Github偏爱的Markdown */github-flavored-markdown/ 在线的Markdown编辑浏览器 *http://dillinger.io/ 致谢 在本书的编写过程中,得到了很多热心人士,同时也是技术高手的帮助。
PeterWang(@happycasts)￿开源电子书LGCB的作者,从他这儿我学会了用github搭建这本书的写作方法,Peter还有很多精心录制的学习开源技术的视频,大家一定不要错过。
chunzi￿ProGit的中文译者,正是这本书教会了我如何使用Git,启发了我想要通过协作迭代来写书,后来我发现协作本身比写作更有乐趣。
虽然后来没有采用ProGit的框架,但还是非常感谢chunzi及时回复了我的邮件,相信这本书还会帮助到更多的人。
LarryCai(@larrycaiyu)￿上海爱立信研发中心的软件开发高级专家,从微博上加入“中文开源技术书”之后,身为管理员的larry就一直默默主动帮我解决从markdown到生成pdf格式的各种细节问题,他所维护的mkbok这里强烈推荐噢,以后一定会成为GitHub上写书必备之利器。
tonghuix￿倡导自由开源生活方式的@爱开源未来,正是他的提醒,我最后将本书的名字定为《源码开放学ARM》,以此表示对开源社区文化的尊重和支持,等有机会我会争取在开源硬件上写一本真正开源学习的书。
所有来自这些朋友的热情帮助和技术支持,让我常有如拨云雾而见青天之顿悟,虽然你们中的大多数未有机会得以见面,但对技术传播和分享的共同热爱使我们心灵相通。
在此希望能够一并致谢。
参与 你可以通过关注新浪微博@亚嵌李明老师联系作者或者发邮件给limingthAT告知你希望出现在书中的内容和想要解决的问题。
如果你愿意参与本书的编写,可以通过fork《源码开放学ARM》作出贡献。
本作品采用知识共享署名-非商业性使用-相同方式共享2.5中国大陆许可协议进行许可。
目录 前言 i 目录 iii 1开发环境搭建
1 1.1硬件平台..............................1 1.1.1芯片识别..........................1 1.1.2外设识别..........................2 1.1.3准备工作..........................2 1.1.4硬件平台的验证.......................2 1.2硬件原理图.............................3 1.2.1原理图包含的信息......................3 1.2.2核心板...........................4 1.2.3底板............................4 1.3开发工具链.............................4 1.3.1ADS安装使用说明......................5 1.3.2Linux工具链安装使用说明..................7 1.4基本开发流程............................8 1.4.1Windows平台开发......................8 1.4.2Linux平台开发.......................10 2芯片手册导读 13 2.1内部结构框图............................13 2.1.1S5PV210芯片数据手册目录结构................13 2.1.2S5PV210BlockDiagram芯片内部结构框图...........14 2.1.3芯片手册的一般结构.....................15 2.1.4芯片手册应该怎样阅读?...................15 2.2存储管理和地址映射.........................16 2.2.1存储器件..........................16 2.2.2地址空间..........................16 2.2.3MemoryMap存储映射.....................16 2.3特殊功能寄存器...........................17 2.3.1关于内核,控制器,总线和外设之间的关系...........17 2.3.2特殊功能寄存器的设置....................18 2.4时序图...............................19 2.4.1基本概念..........................19 3GPIO控制器 21 3.1控制器内部结构...........................21 3.2GPIO输出引脚...........................21 3.3GPIO特殊功能寄存器........................22 3.4GPIO驱动代码实现.........................22 3.4.1汇编程序..........................23 3.4.2ARM汇编的延时函数......................23 3.4.3立即数的表示........................23 3.4.4连接开发板.........................23 3.4.5led.c参考代码实现.....................24 3.4.6button.c参考代码实现....................24 3.4.7buzzer.c参考代码实现....................25 4CLOCK时钟管理 27 4.1时钟发生器.............................27 4.1.1时钟源的周期换算关系....................27 4.1.2ClockController时钟控制器(p353-p417)...........27 4.2时钟输出频率............................27 4.2.1时钟输出..........................28 4.3锁相环和分频器...........................28 4.3.1锁相环PLL.........................28 4.3.2分频器Divider.......................28 4.3.3寄存器配置.........................28 4.3.4分析ARMCLK的产生.....................30 4.3.5举例:UART串口时钟PCLK_PSYS的生成过程..........30 4.4时钟驱动代码实现..........................30 4.4.1Clock时钟管理知识点总结..................30 4.4.2代码举例:..........................31 5UART控制器 33 5.1串口的硬件连接(硬件原理图)....................33 5.2串口的管脚功能复用.........................33 5.3串口时序图.............................34 5.4串口控制器结构...........................34 5.4.1串口控制器功能.......................34 5.4.2串口控制器框图.......................34 5.5串口寄存器配置...........................35 5.5.1串口寄存器分类SFR:.....................35 5.5.2查看uboot对串口寄存器的设置................35 5.6串口驱动代码实现..........................36 5.6.1uart.c参考代码实现.....................36 5.6.2uart.h参考代码实现.....................37 6SDRAM控制器 39 6.1SDRAM硬件连接...........................39 6.1.1SDRAM引脚描述.......................39 6.1.2SDRAM内部结构.......................396.1.3从SoC芯片到SDRAM芯片....................406.2SDRAM管脚功能复用.........................406.3SDRAM时序图............................416.4SDRAM控制器结构..........................416.5SDRAM寄存器配置..........................416.6SDRAM驱动代码实现.........................426.6.1课堂修改作业........................52 7NandFlash控制器 53 7.1K9F2G08芯片............................53 7.2NandFlash管脚功能复用.......................53 7.3NandFlashTiming时序.......................53 7.4NandFlash控制器结构........................54 7.5NandFlash寄存器配置........................54 7.5.1NandFlash寄存器分类....................54 7.5.2初始化配置.........................54 7.6NandFlash驱动代码实现.......................55 7.6.1nand.c参考代码实现.....................55 7.6.2nand.h参考代码实现.....................57 7.6.3思考问题:如何访问Flash0地址...............57 8Exception异常处理 59 8.1异常相关基本概念..........................59 8.1.1ARM的工作模式有几种?各是哪些?..............59 8.1.2ARM的寄存器有多少?各是哪些?...............59 8.1.3ARM的异常有几种?各是哪些?................59 8.2异常向量表的实现..........................60 8.2.1ARM的异常向量表是指什么?
有什么特点?...........60 8.3异常处理流程............................60 8.3.1ARM的软中断异常发生后,硬件做何响应?...........60 8.3.2cpu内核跳转到0x8之后,软件需要做哪些工作?........60 8.4软中断异常代码实现.........................61 8.4.1NewProject.........................61 9Interrupt控制器 63 9.1中断相关基本概念..........................63 9.1.1异常和中断的概念区分....................63 9.1.2中断处理的相关概念.....................63 9.2中断处理流程............................64 9.2.1哪些事情硬件做,哪些事情软件做?..............64 9.2.2如何跳转..........................64 9.3中断寄存器配置...........................64 9.3.1中断相关寄存器的设计演变..................65 9.3.2S5PV210中断相关寄存器...................65 9.4硬件中断异常代码实现........................67 9.4.1实验验证结论:.......................67 10PWMTimer定时器 69 10.1定时器工作原理...........................69 10.1.1定时器功能.........................69 10.1.2原理............................69 10.1.3课堂讨论..........................69 10.2定时器寄存器配置..........................70 10.3定时器驱动代码实现.........................71 11Linux驱动开发基础 73 11.1驱动基本概念............................73 11.1.1设备............................73 11.1.2设备驱动..........................74 11.1.3设备文件..........................75 11.2硬件基础知识............................76 11.2.1处理器...........................76 11.2.2存储............................77 11.2.3常见接口和总线.......................78 11.3开发环境搭建............................78 11.3.1准备工作..........................78 11.3.2安装交叉编译器.......................79 11.3.3搭建测试环境........................80 11.4开发调试流程............................81 11.4.1基本流程..........................81 11.4.2课堂小练习.........................85 12Linux内核模块 87 12.1用户空间编写驱动程序........................87 12.1.1错误写法..........................87 12.1.2正确写法..........................88 12.2内核模块程序结构..........................89 12.2.1内核............................89 12.2.2模块的由来.........................90 12.2.3模块的定义.........................90 12.2.4运行在kernel空间......................91 12.2.5不能使用库函数.......................91 12.2.6模块与驱动的关系......................91 12.2.7模块的基本元素.......................91 12.3模块加载和卸载...........................92 12.3.1模块的操作命令.......................92 12.3.2许可协议..........................93 12.3.3命名空间和符号导出.....................94 12.3.4给模块传参数........................94 12.4内核模块驱动代码实现........................94 12.4.1writeled.c.........................94 12.4.2writeaMakefilepile.................95pileandtestit.....................9612.4.4GPIO............................96pile...........................9812.4.6Exercise..........................98 13Linux字符设备驱动 101 13.1字符设备驱动结构..........................101 13.1.1设备分类..........................101 13.1.2字符设备驱动结构......................101 13.2主设备号和次设备号.........................105 13.2.1主次设备号.........................105 13.2.2注册设备..........................106 13.2.3调用范例..........................106 13.2.4设备编号的内部表示.....................107 13.2.5cdev结构体.........................108 13.2.6分配和释放设备号......................109 13.3文件操作和file结构.........................110 13.3.1structfile_operations...................110 13.3.2基本元素..........................111 13.3.3接口含义..........................111 13.3.4structinode_operations...................112 13.3.5用户空间和kernel空间的数据互传...............113 13.4GPIO/UART驱动代码实现.......................113 13.4.1led驱动..........................114 13.4.2课堂练习:串口设备驱动(chardevicedriver).........115 13.4.3uart驱动..........................123 14中断的概念 127 14.1中断的概念.............................127 14.1.1中断与轮询/DMA的关系....................127 14.1.2中断轮询优缺点.......................128 14.1.3DMA与轮询..........................128 14.1.4DMA与中断..........................128 14.2中断相关数据结构..........................128 14.2.1Linux中断数据结构......................128 14.2.2中断号irq的确定......................131 14.3中断处理程序............................132 14.3.1Linux注册函数.......................132 14.3.2/proc接口.........................133 14.3.3中断的处理过程.......................134 14.3.4Examples..........................135 14.4中断的下半部处理..........................136 14.4.1Tasklet(小任务).....................136 14.4.2工作队列..........................139 14.4.3内核定时器.........................142 14.5等待队列..............................14314.5.1声明和调用接口.......................14314.5.2范例代码..........................144 14.6GPIO/UART中断代码实现.......................14514.6.1相关文件..........................14514.6.2中断框架代码........................14514.6.3GPIO中断代码........................14614.6.4UART中断代码........................150 15Linux驱动的并发控制 157 15.1并发与竞态.............................157 15.1.1什么是并发与竞态......................157 15.1.2并发与竞态发生的条件....................157 15.1.3解决并发与竞态的途径....................157 15.2中断屏蔽..............................157 15.2.1中断屏蔽..........................157 15.2.2中断屏蔽使用方法......................157 15.2.3中断屏蔽的注意事项.....................158 15.2.4中断屏蔽方法........................158 15.3原子操作..............................158 15.3.1整形原子操作........................158 15.3.2位原子操作.........................159 15.4自旋锁...............................161 15.4.1自旋锁的定义........................161 15.4.2自旋锁的特点........................161 15.4.3自旋锁使用的注意事项....................161 15.4.4自旋锁的操作函数......................161 15.4.5使用范例..........................162 15.4.6自旋锁的衍生(略).....................162 15.5信号量...............................162 15.5.1信号量的操作........................162 15.5.2信号量的衍生(略).....................163 15.6互斥体...............................163 15.6.1互斥体的操作........................163 15.6.2总结............................164 16Linux网络设备驱动 165 16.1驱动硬件基础............................165 16.1.1DM9000的物理连接......................165 16.1.2DM9000与SoC芯片的连接..................165 16.1.3两个端口￿地址口和数据口..................165 16.1.4端口的读写接口.......................166 16.1.5通过读写接口获取芯片ID...................166 16.2网络数据封装过程..........................166 16.2.1TCP/IP协议栈结构......................166 16.2.2驱动和协议层的关系.....................167 16.3网络设备驱动程序框架........................16716.3.1网络设备驱动程序框架....................167 16.4DM9000驱动代码实现........................17216.5Linux网卡驱动实验.........................172 16.5.1标准BoardLinux启动&uBuntuLinux连接...........17216.5.2uboot启动&uBuntuLinux连接...............17216.5.3uboot和uBuntu之间的tftp连接..............17216.5.4uboot和uBuntu之间的uImage内核下载测试.........17316.5.5DM9000驱动代码实现.....................17316.5.6stepbystep........................17416.6参考速查..............................17616.6.1头文件和函数........................17616.6.2关联操作汇总........................17616.6.3驱动的几种模型.......................177 第1章 开发环境搭建 1.1硬件平台 本课程采用广州友善之臂的Tiny210开发板作为实验开发平台。
关于这个硬件开发板的详细描述和介绍,可以参考阅读下面这个链接的内容。
/tiny210.asp 图1.1:Tiny210广州友善之臂开发板 请通过阅读上述材料之后,回答以下有关开发板硬件平台的问题: 1)开发板采用的主芯片是什么型号,基于什么ARM内核?2)开发板运行程序的主频是多少?使用什么内存?内存有多大?3)开发板上面能够运行哪几种操作系统?它们有什么差别?4)什么叫BSP,开发板的BSP支持哪些外设? 1.1.1芯片识别 board:CPU:MEM: tiny210S5PV210(封装/FBGA)K4T1G08 2第1章开发环境搭建 FLASH:NET:AUDIO:UART: K9F2G08DM9000 WM8960MAX3232 1.1.2外设识别 reset键key键/home/back/menu串口网口USB口SD卡CAMERA接口MIC/HEARPHONEAV口启动跳线:NAND-SDboot可变电阻:ADCLCD接口:外接LCD 1.1.3准备工作 需要参加课程的学员提前准备好以下环境: 1)电源线(5v)2)串口线(双母头)3)开发板(已经烧写了u-boot或者用SD卡可以启动到u-boot下)4)超级终端(hypertrm,115200,无硬件流控,连接开发板有输出)5)如果是用笔记本,通常没有串口,需要自备一根USB转RS232串口的线,并安装相应驱动。
推荐使用Z-Tek力特,驱动比较好装: 如果开发板是刚拿到的,则一般都没有烧写u-boot,可以自己烧写u-boot到开发板SD卡上,这需要准备以下条件: 1)SD卡(自备,2G或者4G都可以)2)SD卡读卡器(自备,连接PC后格式化为FAT32分区,可以显示盘符)烧写SD卡的步骤可以参考随开发板附带的《用户手册》,需要用到SD-Flasher.exe这个工具。
1.1.4硬件平台的验证 在开始学习后继内容之前,通常需要对硬件平台进行以下3个方面的正确性验证: 1)主芯片(通常使用jtag工具,能够读取到cpu的ID)2)串口输出(通常使用超级终端,设置好波特率和流控制,能够和开发板bootloader进行交互)3)下载和烧写(一般通过串口或者usb进行,下载是到SDRAM,烧写是到NandFlash) 串口连接开发板,验证bootloader命令的输入输出: 1)连接开发板2)启动超级终端hypertrm(.exe)3)选择COM1(pc)4)修改波特率为1152005)修改流控制为无(none)(否则影响输入)6)连接之后,重启开发板,及时按回车键,输入help (如果发现有输出但无法输入,留意ScrollLock是否被误按) 1.2节硬件原理图
3 嵌入式开发的硬件平台,是以后我们学习ARM开发课程的实验平台。
目前常见的硬件开发板从ARM7、ARM9、ARM11内核一直到CortexA/R/M系列发展很快,大部分都是采用核心板+底板的结构,如何进一步了解硬件设计的原理,弄懂主芯片和外设之间的作用关系,就需要我们了解硬件设计原理图方面的知识了。
1.2硬件原理图 通常提供硬件平台的厂家,都会随开发板光盘附带硬件原理图。
硬件原理图一般都是以PDF格式提供,这和硬件设计人员通过使用Protel/OrCADCapture这样的硬件原理图设计工具产生的文件不同,但PDF的文档方便查阅,易于打开,对于嵌入式软件开发工程师用于开发已经足够了。
Tiny210-core-board.pdfTiny210-mother-board.pdf推荐使用FoxReader福昕阅读器来打开PDF文档
1.Ctrl+放大Ctrl-缩小
2.Ctrl+F查找
3.Ctrl+Shift+N跳转
4.Ctrl+TAB切换文档 Ctrl滚轮也可以 1.2.1原理图包含的信息 核心板的原理图和底板的原理图,通常分为两个文件存放。
通过查看原理图,能够知道哪些信息? 有哪些芯片芯片有哪些管脚芯片之间的连接关系芯片与外设本身之间的连接关系得到有些芯片管脚的默认连接(接地/接电源/NC(NoConnection)不连接的管脚)电阻电容等分立元件(模拟电路) 4第1章开发环境搭建 1.2.2核心板 核心板一般包含了最小系统,也就是主芯片SoC,内存SDRAM,闪存FLASH,复位电路Reset,调试接口JTAG,时钟CLOCK和电源Power。
请在原理图上分别找到这些器件,并初步熟悉了解它们的芯片型号。
主芯片内存闪存复位电路调试电路时钟发光二极管高清接口 SoC:Mem:Flash:Reset:Jtag:CLOCK:LED:HDMI: S5PV210->584pinK4T1G->1Gb=128MB K9F2G08->2Gbx8bit=256MBMax811TCK/TDI/TDO/TMS/TRST24Mhz(X1)XXTI/XXTOLED1-4miniHDMI(CON8) [S5PV210_UM_REV1.1.pdf][K4T1G164QE_rev11.pdf][K9F2G08.pdf][MAX811T.pdf] 1.2.3底板 底板一般包含了常见外设,例如通用GPIO,串口UART,网卡Net,液晶屏接口LCD,音频接口Audio等。
请在原理图上找到这些器件,并初步熟悉了解它们的芯片型号。
CONN-AB:CONN-C:Power-On/Off:NET:Audio:Buzzer:RTC:I2C-Eeprom:Buttons:SD-CARD:UART:LCD: 30*2*2个=120pin引出(例如串口TxD/RxD)15*2=30pin引出(例如I2C,CAM) S1DM9000AEP()HR91105AWM8960(DA/ADconvert) PWMTimer(beep)Real-TimeClockMACaddress(6bytes)K1-K8(XEINT16-27)Data(4pin)+(4pin) 串口(通用异步收发器)40pin/45pin(DATA-24pin) [DM9000.pdf][WM8960_Rev40.pdf] [MAX3232.pdf][H43-HSD043I9W1.pdf] 以上所有芯片的数据手册,都可以在开发板附带光盘中找到,也可以从/limingth/ARM-Resources链接下载得到。
1.3开发工具链 在ARM开发领域,有两大类开发工具可以选择,一类是基于Windows平台的SDT,ADS,RealViewMDK,DS-5系列,一类是基于Linux平台的GNUCross-Toolchain。
考虑到从简单到复杂的学习路线,我们先介绍Windows平台上的工具链。
一旦我们对工具链背后的开发思路比较了解之后,再来学习Linux上的工具就会比较容易上手。
有关ADS工具和MDK工具的介绍,可以参考阅读百度百科的介绍。
ADS简介MDK简介DS-5(ARMDevelopmentStudio5)是ARM公司最新推出的开发工具套件,采用EclipseIDE,支持对于裸机,RTOS和Linux系统的调试。
1.3节开发工具链
5 DS-5下载页面总体说来,不同的开发工具套件虽然在界面上做了很大改动,但后台使用的命令行工具链基本是一样的。
下面以ADS安装为例,对命令行工具链做一个简单说明。
1.3.1ADS安装使用说明 工具下载/ARM-ToolsADS1.2.zip解压之后运行setup.exe安装 注意: 1)Full安装,不是Typical 2)InstallLicence,在解压后的crack\licence.dat 安装完成之后 安装目录:C:\ProgramFiles\ARM\ADSv1_2\Bin 图形开发环境 IDE.exeaxd.exe ADSIDE - AXDdebugger 命令行开发工具链启动命令行方式 开始->运行->cmd命令打开一个窗口 C:>path是否有C:\ProgramFiles\ARM\ADSv1_2\bin 如果是path问题,需要添加路径到path环境变量我的电脑->鼠标右键属性->高级->环境变量->系统变量下面添加 (注意用分号间隔;原来的不要删除掉,把C:\ProgramFiles\ARM\ADSv1_2\bin添加到最后) C:>是否有这个命令,这一点最重要,如果成功则会输出ARMCCompiler,ADS1.2[Build805] Usage:Mainoptions:xxxxx [options]file1file2...filen .exearmasm.exearmlink.exefromelf.exe- piler(armcpp.exe)/() ASMAssembler/(as) Linker /(ld) Bin-Utils/(objdump/objcopy) 6第1章开发环境搭建 常用编译参数-c只编译,不连接-D(定义)条件编译(-DDEBUG)-U(不定义)条件编译(-DDEBUG)-g增加调试信息-I指定include路径(自己的)-On编译优化级别-S生成汇编-o指定生成文件名 思考问题:交叉编译器的库和链接的库是否一样? 用法举例:hello.c默认会生成 __image.axf(a.out),其中axf文件是ELF格式的可执行文件 -chello.c默认会生成hello.o,此时还需要link之后才能生成axf可执行文件 特殊用法:如果一个C程序,没有main函数,编译会怎么样?(有警告warning,无错误error,能生成可执行文件 axf) C编译器 armasm通常只生成.o的目标文件 用法举例:armasmstart.s默认会生成 start.o,此时还需要link之后才能生成axf可执行文件 asm汇编器 armlink常用链接参数-ro-base指定可执行代码的位置(代码段执行地址)-rw-base数据段执行地址-first指定.o文件放在链接的最开始处-entry指定axd调试工具加载axf文件的入口地址(转成bin之后就丢失了)-scatterfile指定链接脚本(.scf文件/在linux下.lds文件) 用法举例:armlinkhello.o-ohello.axfarmlink-firststart.o-ro-base0x0-entrybeginstart.omain.o-ohello4.axf obj链接器 fromelf常用转换参数-bin生成bin文件,最终烧写到开发板上-c生成txt文本文件,反汇编文件-d打印数据段内容-s打印符号表-t打印字符串表 用法举例:fromelf-binhello.axf-ohello.binfromelf-c-s-dhello.axf-ohello.txt bin-utils二进制转换工具 1.3节开发工具链
7 单独汇编程序的编译链接armasmstart.sarmlinkstart.o-odemo.axf 单独C程序的编译链接-chello.carmlinkhello.o-ohello.axf 汇编和C程序的混合链接armasmstart.s-cmain.carmlink-firststart.o-ro-base0x0-entrybeginstart.omain.o-odemo.axf 综合应用 DDI0100E_ARM_ARM.pdfADS_CompilerGuide_D.pdfADS_AssemblerGuide_B.pdfADS_LinkerGuide_A.pdfADS_DebugTargetGuide_D.pdf -ARM体系结构知识,侧重于内核-编译器使用-汇编器使用 -链接器使用-调试器使用 ARMDocs开发文档 1.3.2Linux工具链安装使用说明 安装工具下载:-4.5.1-v6-vfp-20120301.tgz解压安装: sudotarzxvf-4.5.1-v6-vfp-20120301.tgz-C/ls/opt/FriendlyARM/toolschain/4.5.1/bin/ -> 8第1章开发环境搭建 vi~/.bashrc->exportPATH=$PATH:/opt/FriendlyARM/toolschain/4.5.1/bin/ source~/.bashrcecho$PATH ->/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/FriendlyARM/toolschain/4.5.1/bin/$:noinputfiles 以上步骤完成之后,可以在任意目录下使用来编译程序。
在输入arm-linux-之后使用tab键,还可以看到arm-linux-as,arm-linux-ld,arm-linux-objcopy,arm-linux-objdump等工具也都一并安装完成。
sudoapt-getinstallsudo-s ->Serialportsetup:/dev/ttyS0(forUSBSerialPort:/dev/ttyUSB0)->HardwareFlowControl:No->Savesetupasdfl->Exit 此时重启开发板,可以看到中能够显示从开发板串口输出的字符。
安装 1.4基本开发流程 1.4.1Windows平台开发 ADS汇编语言格式要点TAB开头ARM汇编语言格式要求除了label标号之外,其他包含伪操作和指令的行都应该以一个TAB开头。
AREA名称AREA表示定义代码段/数据段区域的开始,后面跟的名称会进入符号表参与链接。
ENTRY入口表示指定汇编程序的入口,最多只能写一个,也可以不写。
END结束表示汇编程序的结束,必须要写。
;注释分号表示注释,用//或者/**/都不是注释。
label定义符号用于程序跳转时的标号,必须顶格写。
importsymbol用于链接外部的符号名,例如跳转到C语言的主函数。
exportsymbol用于对外输出汇编程序内部的符号名,汇编文件内部的symbol默认对外是不公开的,隐藏的,类似C程序的static修饰。
1.4节基本开发流程
9 C程序注意要点main函数的负面影响链接器会引入很多外部代码,带来跟踪调试的很多问题,同时造成可执行bin文件的体积明显增大。
**“main的用法”**默认main函数真正的入口是”main”,因此直接用“__main”来定义C语言的主函数是比较便利的做法。
替换return0如果主程序没有无限循环,那么最后执行return0的结果是不可预期的,应该用while
(1);无限循环来替代。
volatile修饰符编译器对volatile修饰的变量或者指针,都会避免优化,强制访存。
这对于嵌入式寄存器的读写操作是非常必要的。
unsigned修饰符对于特殊功能寄存器的访问,通常不需要进行算术运算,将它们声明为unsigned无符号整型是通常的做法。
编写Makefileall目标第一个默认的目标,一般都起名为all,make执行时不需要跟目标名,会自动执行默认目标。
clean目标清除中间产生的不必要的文件,例如.o.bak等。
宏变量引入PRJ,SRCS,OBJS,增强项目的可移植性。
匹配替换技巧$(SRC:.c=.o)的用法,灵活替换源文件到目标文件。
依赖关系的传递用依赖关系,对于文件数量较多,编译时间较长的项目非常有好处,可以做到增量编译。
隐含规则%o:%c的用法,如果需要修改编译参数,则需要重新实现该条隐含规则。
makecleanmake 清除原有临时文件重新生成所有文件 make编译项目 #loadb输入命令超级终端菜单->传送->发送文件->选择文件+Kermit协议->点击发送 #go0x21000000之后观察LED1灯亮的现象 测试可执行文件 10第1章开发环境搭建 1.4.2Linux平台开发 以下代码可以从/limingth/ARM-Codes/tree/master/tiny210-linux-codes/1-led-s下载 相关工具可以从/limingth/ARM-Tools/tree/gh-pages/utils下载 .global_start_start: ldrr0,=0x1ldrr1,=0xe0200280strr0,[r1] loop: ldrr0,=0x0ldrr1,=0xe0200284strr0,[r1]bldelay ldrr0,=0x1ldrr1,=0xe0200284strr0,[r1]bldelay bloop delay:go_on: ldrr0,=0x100000 subr0,r0,#1cmpr0,#0bnego_onmovpc,lr led.s汇编程序 all:arm-linux-asled.s-oled.oarm-linux-ldled.o-oled.elfarm-linux-objcopy-Obinaryled.elfled.binarm-linux-objdump-dled.elf>led.lst./mktiny210spl.exeled.binsd-led.bin Makefile 1.4节基本开发流程11 make->ls-l*.bin -rwxr-xr-x1limingthlimingth762012-05-1118:21led.bin-rw-r-r--1limingthlimingth81922012-05-1118:21sd-led.bin make insertsdcarddmesg|grepsdb ->/dev/sdbshouldbefoundsudoddiflag=dsyncoflag=dsyncif=sd-led.binof=/dev/sdbseek=
1 ->记录了16+0的读入记录了16+0的写出8192字节(8.2kB)已复制,0.209805秒,39.0kB/秒 烧写sd-led.bin到SD-Card 1.fdiskSDcardtoaWin95-FAT32partition ifyoujustbuyanewSDcard,herewedoitfromtheverybeginningsudofdisk/dev/sdbCommand(mforhelp):m(help)Command(mforhelp):p(printthepartitiontable)Command(mforhelp):d(deletetheoldpartition)Command(mforhelp):n(addanewpartition)Commandaction eextendedpprimarypartition(1-4)p(forprimary)->Partitionnumber(1-4):1Firstcylinder(1-121,default1):1Lastcylinder,+cylindersor+size{
K,M,G}(1-121,default121):(Enter)Usingdefaultvalue121 Command(mforhelp):tSelectedpartition1Hexcode(typeLtolistcodes):
L Hexcode(typeLtolistcodes):bChangedsystemtypeofpartition1tob(W95FAT32) Command(mforhelp):p DeviceBoot/dev/sdb1 Start1 End BlocksIdSystem 121 971901bW95FAT32 Command(mforhelp):w 12第1章开发环境搭建 Thepartitiontablehasbeenaltered!
Syncingdisks.formatFAT32(ThisisVERYimportantforlateruse!
However,itisnotamustforledblink)2.sudomkfs.vfat/dev/sdb1nowyoucantestifSD-bootcanblinkled13.insertSDcardtoslot(CON10oftiny210)>>switchtoSDBOOTofS2resetandseeifitworks!
补充:如何格式化SD-Card 第2章 芯片手册导读 2.1内部结构框图 如何阅读芯片手册,是很多初学者需要面临和解决的问题,但大部分人都会感到难以入手不知所措。
除了数据手册一般都全部采用英文书写所带来的困难之外,更多的困难还在于不知道如何去阅读相关章节,不知道哪些是真正重要的或者哪些是无关紧要的内容。
我们以S5PV210芯片数据手册为例,给大家讲解一下应该如何阅读芯片手册。
这本手册大约有2000多页,如果能够把握住其中的内容,则阅读其他手册也应该没有障碍。
2.1.1S5PV210芯片数据手册目录结构
一、Overview1.overviewblockdiagram2.memorymapSystemMemoryMapSFRs(SpecialFunctionRegister)0xE0000000-0xFB6FFFFF(max-512M)真实的存储容量:寄存器的个数*4bytes以串口为例:15个*4组=60个*50=3K*4=12K3.ballmappinassignmentsignaldescriptionUART-RxD0/TxD0CTS0/RTS0
二、System1.GPIO2.Clock3.Power4.bootsequence
三、Bus1.AXI/AHB
四、Interrupt1.VectoredInterruptController
五、Memory1.DRAM=>DDRmemeory2.SROM=>SRAM+ROM(NorFlash)
3.OneNand4.Nand 14第2章芯片手册导读
5.CompactFlash六、DMA
1.DMAController七、Timer
1.PWMTimer2.SystemTimer3.WatchdogTimer4.RTC八、Connectivity1.UART2.IIC-bus3.SPI(serialperipheralinterface)
4.USBHost5.USBOTG6.SD/MMC九、Multimedia1.LCD2.CAM3.G3D4.CODEC5.TVOUT6.VIDEO7.MIXER8.IMAGEROTATOR9.JPEG10.G2D十、AUDIO1.IIS2.AC973.PCM4.ADC(TS)
5.KeyPad十
一、Security 2.1.2S5PV210BlockDiagram芯片内部结构框图 PRODUCTOVERVIEWBlockDiagram CPU(运算)(控制)BUS(地址/数据/控制)Controllers(特殊功能寄存器)PinAssignmentDiagram管脚定义SIGNALDESCRIPTIONS信号描述SPECIALREGISTERS(SFRs)SYSTEMMANAGERSystemMemoryMap(系统内存映射) 0x4000000=0x40M=64MSystemManagerRegisters(10+)SFRName+Address+R/W+desc.+ResetValueBit-Field位域Timing时序图Controller控制器 OVERVIEW综述BlockDiagram框图SPECIALREGISTERS特殊功能寄存器Timing时序图 2.1.3芯片手册的一般结构 CORE-Cortex-A8ALU(运算器)Regs(通用寄存器)MMUCACHE BUS片内-地址线32bit片外-地址线取决于BANK的大小 iRAM(SRAM)iROMPeripheralControllers Memorycont.GPIOcont.UARTcont.USBcont.IICcont.SDcont.SPIcont.DMAcont.Interruptcont.G3D,G2DHDMICAMERATVOUTIMAGEROTATORJPEG 2.1.4芯片手册应该怎样阅读? OverviewCHIPBlockDiagram,MemoryMap,PinAssignment,SignalDescriptionSFRs(howmany,addressrange)Controllers(howmany) SystemClock(BUS),PowerBootSequence(启动/引导流程)GPIO DeviceUARTNandFlashMemory(DDR) 2.1节内部结构框图15 16第2章芯片手册导读 DMAInterruptPWMTimerLCD+TSAUDIODM9000SDSecurity 2.2存储管理和地址映射 2.2.1存储器件 对于一个SoC芯片,最重要的认识莫过于了解它所能支持的存储器件和地址空间。
这对于任何一个SoC芯片而言,都应该放在精读内容的首位。
存储器件主要包括以下这些,了解和掌握它们的接口和存储特性,是做嵌入式底层开发人员所必须掌握的理论知识。
1)片内的RAMiRAM-SRAM 2)片外的RAMSRAMSDRAMDDRSDRAM 3)片内的ROMiROM 4)片外的ROMNorFlashNandFlashOneNandFlash 2.2.2地址空间 地址空间主要是指32位地址线0-4G所对应(也可称为映射)的存储器件和访问方法(如何读写)。
0地址片内RAMSFRSDRAM虚地址 -加电后运行的第一条指令-可以无需初始化直接使用的存储-特殊功能寄存器的地址范围-程序通过bootloader命令可以下载到的地址-使能MMU之后的虚拟地址 2.2.3MemoryMap存储映射 存储映射这个概念是本节最重要的知识,以S5PV210芯片为例,了解并掌握它的映射情况。
2.3节特殊功能寄存器17 BootArea:0x0-0x20000000=512MMirroredregiondependingonbootmode DRAM0:DRAM1:SFR:iROM:iRAM: 0x20000000-0x3FFFFFFF:2^29=512M0x40000000-0x7FFFFFFF:=1G 0xE0000000-0xFFFFFFFF:=512M0xD0000000-0xD0010000:=64K 0xD0020000-0xD0038000:=96K(0x18=24*0x1000) 思考问题:根据上述地址映射,对不同地址进行的访问,会引发底层硬件产生何种响应?*(int*)0x00000000:itdepends*(int*)0x21000000:DRAM*(int*)0xE0200280:GPIOSFR*(int*)0xE2900000:UARTSFR 2.3特殊功能寄存器 特殊功能寄存器(SpecialFunctionRegister)是在SoC芯片内部的一个重要组成部分,区别于ARM内核的R0-R15这样的寄存器,这些寄存器本质上和片内的SRAM一样,按地址访问,掉电以后值会丢失,无需初始化直接可以访问这样一些特性。
从逻辑结构上看,所有对特殊功能寄存器(以下简称SFRs)的访问操作的实现,都对应到不同的外设控制器上。
访问指令本质上和对外部存储器的读写一样,都是通过LDR和STR汇编指令来实现的。
2.3.1关于内核,控制器,总线和外设之间的关系 内核:Cortex-A8(CORE) 寄存器Regs(R0-R15,CPSR) 指令集Ins(add/sub,ldr/str) 总线(访存指令) 地址概念: cpu:32bit ldrr0,[r1] (r1:addr) 1)SRAM: 2)SFR: -------------------------- 3)DDR: 4)Deviceinternalmemory: 总线概念: 片内总线 地址线-32bit 由地址寄存器的字节数决定 片外总线 地址线-29bit 由设计cpu时,外接的单个存储器件的最大容量决定 内存控制器 通过把32bit的最大访存范围,分割为若干个bank来进行统一访问 外设控制器概念: 外设=可见(接插件/关联芯片/连接线)+不可见(外设控制器) 外设控制器=寄存器接口<----黑匣子(类似函数库.o)--->外设工作的时序图 总结关系: 都是涉及到裸板驱动(无操作系统/无MMU参与) 18第2章芯片手册导读 本质上除了运算之外,都是变成为对地址的读写C语言的指针,在本阶段,占一个很重要的角色。
2.3.2特殊功能寄存器的设置 所有我们设置的SFR,都应该和外设控制器内部的工作逻辑有关。
因此了解Controller的工作方式和内在逻辑,是我们能够得以正确配置这些寄存器的正确路径。
每一个controllers都有一批自己的寄存器,通过读写操作就可以用来进行软件编程和控制。
全大写,未来用来宏定义的,前面部分是这个Controller的缩写,后面部分就是它的功能)CON-control控制STAT-status状态DAT-data数据MOD-mode模式FIFO-fifo缓冲寄存器CFG-config配置CNT-counter计数TXH-transmitHolder发送缓冲RXH-receiveHolder接收缓冲BRDIV-bauddivisor波特率分频因子 RegisterName 这个地址,是在写代码的时候,所对应操作的寄存器的唯一标识。
名字只是用来帮助记忆的,不是内部标识,也不是用来给编译器的。
RegisterAddress #definePRO_ID (*(volatileunsignedint*)0xE0000000) volatile关键词的作用 写法要点:强制类型转换,1个括号防止优先级结合问题,1个括号unsigned无符号类型,防止右移问题int类型对应4个字节,依据手册决定是否换为char类型 定义举例 2.4节时序图19 2.4时序图 2.4.1基本概念 时序图的基本概念时序图是芯片与芯片之间进行数据通信所需要遵循的一种协议。
通过时序图能够直观的看出,不同的芯片引脚在时间轴上的不同时刻所呈现出来的高低电平的变换,这些引脚中,有的代表地址信息,有的代表数据信息,有的代表控制信息,它们出现的先后顺序是有严格的时间参数规定的,这称为Timing。
芯片手册里的时序图一般都会列出其中关键的时间参数名称,在手册中都可以查到这些时间参数的具体要求。
minmaxtypical -最小值-最大值 -典型值 [TimingTable] 第3章 GPIO控制器 3.1控制器内部结构 GPIOControllerhowmanypinpinnumber,pinname,pinmuxfunctionaldevice<->GPIO(LED1->GPJ2_0)原理图 GPIOSFRsSetmuxfunction控制寄存器GPXCONSetpinvalue数据寄存器GPXDATSetinterruptfunction中断寄存器... 3.2GPIO输出引脚 GeneralPurposeInput/Output(p92-p352) 1)237multi-functionalinput/outputportpins34generalportgroups 2)GPIO<--->peripheralcontroller(signalmux)3)GPIOBlockDiagram APBbus(addr+data)*(int*)0xE0000000=0x1234;RegisterFile(GPIOSFRs)MuxControl(functional)InterruptControl(Interruptcont.)4)PinMuxDescriptionpinname->GPIOnamedefaultfunction 22第3章GPIO控制器 3.3GPIO特殊功能寄存器 GPIOREGISTERDESCRIPTIONaddrrange:0xE020_0000-0xE020_0F80Reg1:GPA0CON:GPA0+CON(control)bit-fieldname:GPA0CON[7]->GPA0_7fieldwidth:[31:28]GPA0_7pinsetting:input:0000output:0001UART_1:0010INT:1111 Reg2:GPA0DAT bit-field:[7:0] wheninput: thepinstate(high-level:1low-level:0) whenoutput:setbit1,outputhigh-level whenfunctional:leavethispintoperipheralcontroller Reg3:GPA0PUDPull-upPull-down00=Pull-up/downdisabled01=Pull-downenabled10=Pull-upenabled11=Reserved Reg4:GPA0_INT_CONSetsthesignalingmethod000=Lowlevel001=Highlevel010=Fallingedgetriggered011=Risingedgetriggered100=Bothedgetriggered101~111=Reserved Reg5:GPA0_INT_MASKEnablesInterrupt/Masked0=EnablesInterrupt1=Masked Reg6:GPA0_INT_PENDInterrupturstatus0=Notur1=urinterrupt 3.4GPIO驱动代码实现 3.4.1汇编程序 TABAREAledCODE,DATAREADONLYlabelinstruction...END 3.4.2ARM汇编的延时函数 主程序中bldelay... delaygo_on ldrr0,=0x10000000 subr0,r0,#1cmpr0,#0bnego_on movpc,lr 3.4.3立即数的表示 mov操作,#后面跟着的数字是立即数,会写入指令中有效位不超过8位,同时通过循环右移偶数位得到100000010=0x1021000000100=0x204 3.4.4连接开发板 启动超级终端hypertrm (.exe) 选择COM1(pc) 修改波特率为115200 修改流控制为无(none)(影响输入) 连接之后,输入help 如果发现有输出但无法输入,留意ScrollLock是否被误按 #loadb输入命令超级终端菜单->传送->发送文件->选择文件+Kermit协议->点击发送#go0x21000000之后观察LED1灯亮啦 3.4节GPIO驱动代码实现23 24第3章GPIO控制器 3.4.5led.c参考代码实现 //led.c#defineGPJ2CON#defineGPJ2DAT (*(volatileunsignedint*)0xE0200280)(*(volatileunsignedint*)0xE0200284) voidled_init(void){ //LED1-4:GPJ2_0,...GPJ2_3//0001000100010001=outputGPJ2CON&=~0xFFFF;GPJ2CON|=0x1111; return;} voidled_on(void){ //setbit0->ledonGPJ2DAT&=~0xF; return;} voidled_off(void){ //setbit1->ledoffGPJ2DAT|=0xF; return;} 3.4.6button.c参考代码实现 //button.c#defineGPH2CON#defineGPH2DAT (*(volatileunsignedint*)0xE0200C40)(*(volatileunsignedint*)0xE0200C44) voidbutton_init(void) { //K1-K4 (seemotherboard) //GPH2_0-GPH2_
3 //GPH2CON[0][3:0]0000=Input //... //GPH2CON[3][15:12]0000=Input GPH2CON&=~0xFFFF; return;} intbutton_is_down(intwhich){ //buttondown->DAT=0intindex=which-1; if((GPH2DAT&(1<buzzeronGPD0DAT|=1<<0; return;} voidbuzzer_off(void){ //setbit0->buzzeroffGPD0DAT&=~(1<<0); return;} 第4章 CLOCK时钟管理 4.1时钟发生器 4.1.1时钟源的周期换算关系 24Mhz输入时钟 10^(-3) 毫秒 1Khz10^
3 1Ghz->1纳秒 100Mhz->10纳秒 10^(-6)1Mhz10^
6 微秒 10^(-9)1Ghz10^
9 纳秒 4.1.2ClockController时钟控制器(p353-p417) CMU:ClockManagementUnit总线频率MSYS:Main(200Mhz-100Mhz)CortexA8CoreDRAMcontrollerDSYS:Display(166Mhz-83Mhz)JPEGPSYS:Peripheral(133Mhz-66Mhz)UARTAC97PWMTimerGPIO ClockGenerator时钟发生器S5PV210Top-LevelClocksXXTI-24Mhz-->(4PLLS'sinput)XrtcXTI-32.768Khz4PLLs(APLL,MPLL,VPLL,EPLL)PhaseLockedLoop锁相环(倍频) 4.2时钟输出频率 28第4章CLOCK时钟管理 4.2.1时钟输出 MSYSclockdomain(H->HighPerformanceP->Peripheral) AHB/APB freq(ARMCLK)=1000Mhz 1000M/1 freq(HCLK_MSYS)=200Mhz ARMCLK/5 freq(PCLK_MSYS)=100Mhz HCLK_M/2 freq(HCLK_IMEM)=100Mhz HCLK_M/2 DSYSclockdomainfreq(HCLK_DSYS)=166Mhzfreq(PCLK_DSYS)=83Mhz HCLK_D/2 PSYSclockdomainfreq(HCLK_PSYS)=133Mhzfreq(PCLK_PSYS)=66Mhzfreq(SCLK_ONENAND)=133M/166Mhz HCKL_P/2 PLLPMSsetting 4.3锁相环和分频器 4.3.1锁相环PLL PLL:Fin->Fout倍频MUX:0/1选择器SRC选择源DIV:/2-16分频器DIV XPLL_CONCLK_SRC CLK_DIV REGISTERDESCRIPTIONOM[0]:cpupinOM[0]=
0,XXTI=24MFin_PLL:24MhzAPLL:APLL_CON:e0100100:0xa07d0301=>1000Mhz 4.3.2分频器Divider Mux_APLL:CLK_SRC0,0xe0100200:10001111[0]=>1Mux_MSYS:CLK_SRC0,0xe0100200:10001111[16]=>0DIV_APLL:CLK_DIV0,0xE0100300:14131440[2:0]=>0=/1DIV_APLL:CLK_DIV0,0xE0100300:14131440[10:8]=>100=/5 4.3.3寄存器配置 [FriendlyLEG-TINY210]#md0xe0100100e0100100:a07d030100000000a29b0c0100000000 ..}............. 4.3节锁相环和分频器29 e0100110:a8500303000000000000000000000000e0100120:a06c0603000000000000000000000000e0100130:00000000000000000000000000000000e0100140:00000000000000000000000000000000e0100150:00000000000000000000000000000000e0100160:00000000000000000000000000000000e0100170:00000000000000000000000000000000e0100180:00000000000000000000000000000000e0100190:00000000000000000000000000000000e01001a0:00000000000000000000000000000000e01001b0:00000000000000000000000000000000e01001c0:00000000000000000000000000000000e01001d0:00000000000000000000000000000000e01001e0:00000000000000000000000000000000e01001f0:00000000000000000000000000000000 ..P...............l............................................................................................................................................................................................................................. [FriendlyLEG-TINY210]#md0xe0100200e0100200:10001111000000000000000000000000e0100210:66667777000000000000000000000000e0100220:00000000000000000000000000000000e0100230:00000000000000000000000000000000e0100240:00000000000000000000000000000000e0100250:00000000000000000000000000000000e0100260:00000000000000000000000000000000e0100270:00000000000000000000000000000000e0100280:ffffffffffffffff0000000000000000e0100290:00000000000000000000000000000000e01002a0:00000000000000000000000000000000e01002b0:00000000000000000000000000000000e01002c0:00000000000000000000000000000000e01002d0:00000000000000000000000000000000e01002e0:00000000000000000000000000000000e01002f0:00000000000000000000000000000000 ................wwff............................................................................................................................................................................................................................................ [FriendlyLEG-TINY210]#md0xe0100300e0100300:14131440000004000000000000000000e0100310:99990000000000000007000000000000e0100320:00000000000000000000000000000000e0100330:00000000000000000000000000000000e0100340:00000000000000000000000000000000e0100350:00000000000000000000000000000000e0100360:00000000000000000000000000000000e0100370:00000000000000000000000000000000e0100380:00000000000000000000000000000000e0100390:00000000000000000000000000000000e01003a0:00000000000000000000000000000000e01003b0:00000000000000000000000000000000e01003c0:00000000000000000000000000000000e01003d0:00000000000000000000000000000000e01003e0:00000000000000000000000000000000e01003f0:00000000000000000000000000000000 @............................................................................................................................................................................................................................................................... 30第4章CLOCK时钟管理 4.3.4分析ARMCLK的产生 Q1:OM[0]=
0,SRC->XXTI(24Mhz) 由硬件连线决定 Q2:APLLCON(24M->1000M) 0xE0100100=>0xa07d0301 Fout=Fin*MDIV/(PDIV*2^SDIV-1) =24M*0x7d/(3*2^0) =24M*125/(3*1)=1000M Q3:CLK_SRC0 0xE0100200=>0x10001111 bit[0]=
1 MUXPLL=
1,Fout_APLL Q4:CLK_SRC0 0xE0100200=>0x10001111 bit[16]=
0 Fout_APLL=1G Q5:CLK_DIV0 Address=0xE0100300=>0x14131440 APLL_RATIO[2:0] n=0+
1 ARMCLK=Fout_APLL/n=1G/1=1Ghz 4.3.5举例:UART串口时钟PCLK_PSYS的生成过程 Mux_PSYS:CLK_SRC0,0xe0100200:10001111[24]=>0Fout_mpll MPLL:MPLL_CON:0xa29b0c01=>667Mhz(p358)Equationtocalculatetheoutputfrequency:FOUT=MDIVXFIN/(PDIVX2^SDIV)Fout=(0x29b)*24M/(12*2^1)=667Mhz Mux_MPLL:CLK_SRC0,0xe0100200:10001111[4]=>1Fout_mpll DIV_HCLKP:CLK_DIV0,0xE0100300:14131440[27:24]=>0100=/5->667/5=133MhzDIV_PCLKP:CLK_DIV0,0xE0100300:14131440[30:28]=>001=/2->133/2=66Mhz 4.4时钟驱动代码实现 4.4.1Clock时钟管理知识点总结 时钟管理单元CMUMSYSDomainMSYS(CortexA8,DRAM)DSYSDomainDSYS(JPEG,IIC_HDMI)PSYSDomainPSYS(JTAG,NandFlash,USB,IIS,AC97,IIC,PWMTimer,RTC) 几点结论:ARMCLK进行分频可以得到HCLK_MSYS,PCLK_MSYS不同domain域之间,输出频率的关系PCLK=HCLK/2 时钟发生器ClockGenerator锁相环PLL(Phase-LockedLoop)APLL,MPLL,EPLL,VPLL 4.4节时钟驱动代码实现31 倍频公式Fout=Fin*M/(P*2^S)Fout_mpll/Fin_mpll 分频器Divider 1-2-4-8-16分频divider Div_out=Div_in/(DIVN+1) DIV_PCLKP DIV_HCLKP 二路选通器MuxOM时钟源选择 输入时钟 X1:XXTI/XXTO24Mhz X2:XusbXTI24Mhz X3:XhdmiXTI24Mhz X4:XrtcXTI32.768khz 24Mhz 12Mhz 常用输入频率 输出时钟ARMCLKHCLKM/PCLKMHCLKD/PCLKDHCLKP/PCLKP记住100Mhz=10ns (1Ghz)(200Mhz/100Mhz)(166Mhz/83Mhz)(133Mhz/66Mhz) Clock时钟特殊功能寄存器PLL_CON-APLL_CONCLK_SRCCLK_DIVn 经验总结PLLSel决定用或者不用PLL锁相环的输出时钟串口的时钟输入,采用MPLL的输出,但是也可以用APLL的输出时钟输出的图表,可以从后往前分析24Mhz时钟的选择是因为iROM是采用24Mhz时钟(P354) 搜索芯片手册的时候,通过在图标的名字,DIV_HCKLPDIVHCLKP,HCLKP时钟的输出都可以通过软件来控制,输出主频越高,耗电量越高 4.4.2代码举例: 1)设置ARMCLK分频因子从1到
8,把1Ghz调整为128Mhz 2)设置DIV_PCLKP分频因子从2到
4,把PCLK从66M调整为33M修改超级终端把波特率改为57600来测试PCLK的设置是否成功 第5章 UART控制器 5.1串口的硬件连接(硬件原理图) COM0接口DB9九针公头pin2:RSRXD0pin3:RSTXD0pin5:GND通过TxD发送字符(以字节为单位5-8bits)通过RxD接收字符(以字节为单位5-8bits) RS232电平:-15v->+15v(+15v-逻辑
0,-15v-逻辑1)TTL电平:0->+5v(0-逻辑0,5v-逻辑1)逻辑电平的转换:MAX3232(美信芯片) 查看MAX3232芯片+核心板原理图可得RSTXD0<-XuTxD0--TINY1BB7--XuTXD0/GPA0_1RSRXD0->XuRxD0--TINY1BB8--XuRXD0/GPA0_
0 结论:GPA0管理了UART的Txd/Rxd两个引脚 5.2串口的管脚功能复用 参考S5PV210芯片手册 GPA0MuxFunction查看GPA0[0]GPA0[1],确认了UART的复用功能查看GPA0CON寄存器,了解如何设置(0010)GPA0CON:地址0xe0200000 [FriendlyLEG-TINY210]#md0xe0200000e0200000:22222222000000ab0000555500000000e0200010:00000000000000000000555500000000 """"....UU..............UU...... [FriendlyLEG-TINY210]#mw0xe02000000x22222202 结论:RXD影响接收,TXD影响发送 34第5章UART控制器RTS和CTS对发送和接收暂时无影响(无流控制) 5.3串口时序图 图5.1:UARTTiming Timing:空闲状态high-level起始位startbit-1bit数据位databit-8bit奇偶校验odd/evenParity(无)停止位bit-1bit 5.4串口控制器结构 5.4.1串口控制器功能 UARTController(p853-p882) 类似是一个函数,需要了解它的->输入,输出,如何实现
1.输出:Timing(串行通信实现时序图)SerialI/OFrameTimingDiagram(NormalUART)
2.输入:SFR(串口控制器的寄存器)REGISTERDESCRIPTION->p8643.实现:BlockDiagram(结构框图)BlockDiagramofUART->p854 ->p860 5.4.2串口控制器框图 BlockDiagram: PeripheralBus外设总线*(int*)SFR_ADDR=value; ControllUnit控制单元ControlRegs(数据位,停止位,奇偶校验位,时钟源选择,工作模式等) Baud-RateGengenrator波特率发生器ClockSource时钟源(PCLK=66M) Transmitter发送器Transmitshifter发送移位器Transmitbuffer发送队列FIFO缓冲器 Receiver接收器Receivershifter接收移位器Receiverbuffer接收队列FIFO缓冲器 5.5节串口寄存器配置35 5.5串口寄存器配置 5.5.1串口寄存器分类SFR: 15Regs RegisterAddress 控制类 通常是可读可写,属性R/W 6个 ULCON00xE290_0000 UCON00xE290_0004 UFCON00xE290_0008 UMCON00xE290_000C UBRDIV00xE290_0028 UDIVSLOT00xE290_002C 状态类 通常是只读,属性
R 4个 UTRSTAT00xE290_0010 UERSTAT00xE290_0014 UFSTAT00xE290_0018 UMSTAT00xE290_001C 数据类 通常是可读可写,属性R/W 2个 UTXH00xE290_0020 URXH00xE290_0024 中断类 通常是可读可写,属性R/W 3个 UINTP00xE290_0030 UINTSP00xE290_0034 UINTM00xE290_0038 5.5.2查看uboot对串口寄存器的设置 [FriendlyLEG-TINY210]#md0xe2900000e2900000:00000003000002450000000000000000e2900010:00000000000000000001000000000010e2900020:000000000000000d0000002300000808e2900030:00000005000000050000000000000000e2900040:00000000000000000000000000000000e2900050:00000000000000000000000000000000e2900060:00000000000000000000000000000000e2900070:00000000000000000000000000000000e2900080:00000000000000000000000000000000e2900090:00000000000000000000000000000000 ....E...................................#....................................................................................................................... 36第5章UART控制器 ULCON0UCON0UFCON0UMCON0UBRDIV0UDIVSLOT0 0xE290_00000xE290_0004 0xE290_00080xE290_000C 0xE290_00280xE290_002C 0000000300000245 00 0000002300000808 其中FIFOcontrol&Modemcontrol可以不用设置 Timingsetting ULCON0 0x3 databit:8bit bit:1bit parity:none UCON0 0x245 enableTransmit&ReceiveMODE:0101 interrupt:disable dma:disable (INT&Polling) CLOCKsettingUCON0 00:PCLK(66M)-->115200bps(bit/second)-->波特率并不是串口控制器的工作频率,串口控制器在接收采样时,是波特率的16倍 66Mhz=66000000hz 分频因子=66000000/(115200*16)-1(分频因子+1)=PCLK/(bps*16) UBRDIV0:0x23=(66000000)/(115200*16)-1=35UDIVSLOT0: 5.6串口驱动代码实现 5.6.1uart.c参考代码实现 //uart.c#defineULCON0#defineUCON0#defineUTRSTAT0#defineUTXH0#defineURXH0#defineUBRDIV0#defineUDIVSLOT0 (*(volatileunsignedint*)0xE2900000)(*(volatileunsignedint*)0xE2900004) (*(volatileunsignedint*)0xE2900010)(*(volatileunsignedchar*)0xE2900020)(*(volatileunsignedchar*)0xE2900024) (*(volatileunsignedint*)0xE2900028)(*(volatileunsignedint*)0xE290002C) voiduart_init(void){ //66Mhz/(115200*16)-1=0x23//66Mhz/(19200*16)-1=0xD5//UBRDIV0=0xD5;return;} charuart_getchar(void){ charc;//pollingreceivestatus:ifbufferisfull//while((UTRSTAT0&(1<<0))==0)while(!
(UTRSTAT0&(1<<0))) ; c=URXH0; returnc;} voiduart_putchar(charc){ //pollingtransmitstatus:ifbufferisempty//while((UTRSTAT0&(1<<2))==0)while(!
(UTRSTAT0&(1<<2))) ; UTXH0=c; return;} 5.6.2uart.h参考代码实现 //uart.hvoiduart_init(void); charuart_getchar(void); voiduart_putchar(charc); 5.6节串口驱动代码实现37 第6章 SDRAM控制器 6.1SDRAM硬件连接 6.1.1SDRAM引脚描述 硬件原理图 1)从芯片角度地址线 数据线控制线 A0-A13 14根 BA0,BA1,BA2 DQ0-DQ7*4=32bitdatabus(8bit*4chips) nCS,nRAS,nCAS 2)从处理器角度 地址线 Xm1ADDR0-Xm1ADDR13 Xm1BA0,Xm1BA1,Xm1CSn1/BA2 数据线 Xm1DATA0-Xm1DATA31 控制线 Xm1CSn0,Xm1RASn,Xm1CASn 6.1.2SDRAM内部结构 芯片手册 1Gbit=128MByte内部分8bank,每个bank=128M/8=16M(24根地址线)24根地址线的信号分为行地址和列地址 行地址:14根列地址:10根 40第6章SDRAM控制器 6.1.3从SoC芯片到SDRAM芯片 128M*4chips=512M存储容量(512M=2^29) 29根地址线(A0-A28)A28,A27,A26:BA2,BA1,BA0A25-A12:行地址14根A11-A2:列地址10根A1,A0,-GND 如何访问0x0地址 A31,A30,A29:000 ->nCS片选无效 A28,A27,A26:000 A25-A12:00000000000000 A11-A2:0000000000 A1,A0:00 如何访问0x20000000地址 A31,A30,A29:001 ->nCS片选有效 A28,A27,A26:000 A25-A12:00000000000000 A11-A2:0000000000 A1,A0:00 如何访问0x21000000地址 A31,A30,A29:001 ->nCS片选有效 A28,A27,A26:000 A25-A12:01000000000000 A11-A2:0000000000 A1,A0:00 如何访问0x3FFFFFFF地址 A31,A30,A29:001 ->nCS片选有效 A28,A27,A26:111 A25-A12:11111111111111 A11-A2:1111111111 A1,A0:11 如何访问0x40000000地址 A31,A30,A29:010 ->nCS片选无效 A28,A27,A26:000 A25-A12:00000000000000 A11-A2:0000000000 A1,A0:00 6.2SDRAM管脚功能复用 搜索芯片数据手册,发现所有管脚均无功能复用。
举例Xm1ADDR[0] Xm1DATA[0]Xm1SCLKXm1RASnXm1CSn[0] Xm1CASn 6.3节SDRAM时序图41 6.3SDRAM时序图 Timing:/wangdxlove

标签: #软件 #文件夹 #程序 #苹果 #压缩文件 #怎么做 #好友 #程序