韦东山嵌入式新一期笔记第一个ARM裸板程序及引申_第1页
韦东山嵌入式新一期笔记第一个ARM裸板程序及引申_第2页
韦东山嵌入式新一期笔记第一个ARM裸板程序及引申_第3页
韦东山嵌入式新一期笔记第一个ARM裸板程序及引申_第4页
韦东山嵌入式新一期笔记第一个ARM裸板程序及引申_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第一个ARM裸板程序及引申1、点亮LED(怎么做)1)看原理图确定控制LED的引脚。2)看主芯片手册,确定如何设置/控制引脚3)写程序。注意:a)LED导通电阻很小,为防止回路电流过大,需串联一电阻。b)引脚驱动能力不足一般指输出电流或电压过小,无法驱动负载正常工作。(采用三极管一>开关作用,基极电压控制e、c间通断)c)电子系统中,我们不关心引脚输出电压具体多少,只关心输出为高电平还是低电平(如我们不关心输出3.3v还是1.2v,只关心输出了高电平),即输出1/0(逻辑1/逻辑0)d)同名net表示引脚连接在一起。VDDiJV 'nLED2ln.lR^KW力一口1nLm2nLED2ln.lR^KW力一口1nLm2iiLLL:"♦LED*uLED1MI7nL±D2LI4□LED4LI5nLED*ILKEIN/跖哂riNT4OT4EINTSOTiEINTWUPFGEINTJOTTr>ni-tv!I力网EIN/跖哂riNT4OT4EINTSOTiEINTWUPFGEINTJOTTr>ni-tv!I力网pein1KUBVML1ALEIXRED)_ED(RE曲—产一衿JIDtRLDie)nLED_1:n表示低电平有效。(如低电平灯亮,在这里有效即指灯亮)2、GPF4输出1/0(怎么做)1)配置为输出引脚。(GPFCON)2)设置它的状态(pinstates,配置GPFDAT寄存器)。3、S3C2440框架与启动过程SOC(SystemOnChip):CPU+GPIO控制器+4KSRAM(4K内存)+NandFlash控制器注:GPIO:GeneralPurposeInput/Output启动过程:1)NOR启动:NORFlash基地址为0,片内SRAM地址为0x4000,0000,CPU读出NOR上第一个指令(前4字节),执行。CPU继续读出其他指令执行。2)Nand启动:片内4KSRAM基地址为0,NORFlash不可访问(即设为Nand启动时,就无法使用NORFlash)。S3C2440的硬件把Nand前4K内容复制到片内内存(SRAM),然后CPU从0地址(SRAM内)取出第一条指令执行。注:NOR与Nand区别:CPU可直接读取NORFlash内的数据;CPU读取NandFlash中数据时,需先将代码复制到SRAM(内存)中,再从SRAM中读取NandFlash的数据(即CPU不能直接读取NandFlash中的数据)。参考资料:链接库\001_LED原理图及S3C2440启动流程.jpg4、点亮LED程序寄存器:1)CPU寄存器:R1、R2、R3、...(可使用R1、R2等直接访问)2)GPIO寄存器:GPFCON、GPFDAT、GPFUP、...(仅能通过寄存器地址进行访问)注:1)访问即指对寄存器的操作,修改、设置寄存器中各个位的值。2)ARM9为32位处理器,所有寄存器都为32位(4字节一>一个指令长度3)处理器中所有的内存或者寄存器都是编址的,即每个地址都对应一块特定的空间(1个字节),可能是内存,也可能是寄存器。几条汇编:1)LDR(load):读内存命令如:LDRR0,[R1],假设R1值为x,读取地址x(实际上是地址x所对应的那块区域,可能是内存,也可能是寄存器)上的数据(4字节,因为是32位处理器),保存到R0中。注: a)计算机是按字节存储数据,一个字节对应一个地址。32位处理器一次处理4字节数据(32位),所以地址按4依次增加32位处理器的寄存器大小也为32位,所以寄存器地址也按4依次增加。b)设x、y为十进制数x-y=a,证明两数据差值为a设x、y位十六进制数x-y=a,证明两数据差值为a即,两个数据间差值即为两数据之差,与进制无关系。如:寄存器GPFCON地址为0x56000050,GPFDAT地址为0x56000054,两寄存器地址相差4,因为其差值为4,与其是几进制数据无关。又如0b1011与0b1010差值为1,因为0b1011-0b1010=1,或者0b1011=0d11,0b1010=0d10,0d11-0d10=1。由上分析可知,数据运算结果与其进制形式无关,进制形式仅是数据的表现形式(书写形式)不同而已,数据的本质一大小是保持不变的,采用不同的进制形式是为了方便数据的书写、表达和分析、处理,或者在某些专业领域某些进制形式更符合物理实际,更利于观察规律、解决问题。总之采用不同的进制形式是为了在数据使用操作过程中更加方便,而数据的本质属性一大小是不发生改变的。2)STR(store):写内存命令如:STRR0,[R1],假设R1值为x,把R0的值写到地址x(实际上是地址x所对应的那块区域,可能是内存,也可能是寄存器)上去(4字节因为是32位处理器)。B:跳转MOV(move)如:MOVR0,R1把R1的值赋给R0,即R0=R1MOVR0,#0x100即,R0=0x100LDRR0,=0x12345678(伪指令:并不存在这样一条指令,它最终会被拆分成几条真正的ARM指令)最终所得结果为:R0=0x12345678注:R0=0x12345678如果使用MOV指令完成,即,MOVR0,#0x12345678,则会被报告为错误指令,原因如下:一条ARM指令有32位,其中某些为表示MOV指令本身和R0,剩下不足32位来存放数据,如果该数据过大(超过32位或者等于32位),则该指令会报错。即,MOV指令不能处理任意值,只能处理简单值(又被称为立即数)。所以引入伪指令:LDRR0,=任意值(与之前读内存指令区别在于多了一个“二”)注:关于配置Linux服务器,进行linux与Windows直接文件传输与共享的教程(链接库\Ubuntu16.04如何使用samba服务器.pdf)注:关于arm-linux-gcc安装配置的一系列问题参考。(链接库\Ubuntu16.04[64bit]嵌入式交叉编译环境arm-linux-gcc搭建过程图解.pdf)5、.S(汇编文件)文件编译成.bin(二进制流一机器码)文件1)arm-linux-gcc-c-oled_on.oled_on.S(编译:汇编-->机器码--0/1代码)2)arm-linux-ld-Ttext0led_on.o-oled_on.elf(链接:机器码-->机器码--增加了链接库代码)3)arm-linux-objcopy-Obinary-Sled_on.elfled_on.bin(链接文件-->bin文件,都是机器码;注意大写O、S)4)arm-linux-objdump-Dled_on.elf>led_on.dis(反汇编指令:机器码-->汇编代码)6、CPU寄存器CPU内部有15个寄存器:R1--R15,每个寄存器都有对应的别名(代表其各自的功能),如:R15-->pc、R14-->lr、R13-->sp等。PC:程序计数器(program禽口也©『当前指令+8)CPU工作模式为流水线:当前执行地址A的指令,已经在对地址A+4的指令进行译码,已经在读取地址A+8的指令。(注:一个字节对应一个地址

编号,ARM9为32位处理器,一次处理32位数据,4字节,对应4个地址编号,所以下一个取指令地址为A+4)stackpointer:栈LinkRegister:返回地址(函数调用注意1)#30:30为立即数,可理解为普通常数直接使用。2)[pc,#20]:pc的值+20.3)关于程序下载到板子内存后每条指令(或数据)所在地址问题。在使用。『以田卜旗程序时,送释从出址处JI始下载,历以程序的里条指令在口地址处“(存篙布Hand或月口区中.)0:B:::1.4:e59flDl^e3a00c01e5810000e59flD{]ce3a00000e581QDOOIdrmovstrIdrmovstr]。,#2560:B:::1.4:e59flDl^e3a00c01e5810000e59flD{]ce3a00000e581QDOOIdrmovstrIdrmovstr]。,#256r0f[rl]LP'-frOr#Cr0r[r_[#12];OxD;lc<halt+0x4>0x100;20<haLt+0xB>1.0:lc:::20:eafEfffe560000505600005410-word.ward0x560000500x56000054(原始文件:链接库\1.png)4)只要是接入系统的存储器(内存一Nand和NOR、寄存器等),CPU都会将他们统一编号(地址),每块空间都对应一个唯一固定的地址(寄存器地址必定不变,其他存储器若更换则地址可能会变。),将程序或者数据放到某个地址上,则就存放到了某块确定的空间(如某个具有特定功能的寄存器,即操作、设置寄存器)。5)在程序里边,寄存器和内存没有本质差别,CPU都把他们当做内存来使用。6)GPFCON/GPFDAT,在CPU角度,他们就是内存,只不过这些内存比较特殊,设置某些位(在某个确定地址上存放预定的值)就可以控制引脚。7)关于汇编到机器码在地址层面的分析(一条汇编一>4字节机器码一>整个bin文件)0:etyriujlidrzl,|pcF120) ;Lc<halt-i-0x4>4-Ei^aOOcCH0:etyriujlidrzl,|pcF120) ;Lc<halt-i-0x4>4-Ei^aOOcCHJimiO,t25€ ;OkLOQ6-@5810000str111r(rl]C-b59fl00cidril,|pcF*12] ;20<halt+0K8>10-B^aOOOOOjibiO,fd;0x014;55810000stxxOr(rl]0000001]<b-alt>;19-eafffffrbIB1c:56000050nward0k5€00005020:56000055,word0k5€000Q5^a度汇编J.创日OOODODOD<3tart>:母府的hi枚#U西谨寻桥汇粕打转抵成『嚣Wr如,IdrrLMjisn]—vsmfiui语*在Mfc址t第一条指令、.实际存放的是机三码.G所有的汇物科蒯语或机智心受此1班了bin文忤(物:G,将其烧录到内存中,一个地址*TF西三中蟠址所用应的空间存过可宇节,32粒歆据t指令).3)$干bin文件,在下则指定地址,从下荻地址开始,鼻个地址处存或4字节(但对于立性处现器1,侬忒存液F去,百对于1«hJ堤冢的恬立,h■■工文坤内•算的才存放的地址.按文件中普定的地址琼内存放人指定的内存中.4/i:jT7-坏.地Giiii.后DimaanDtiDOMOlDL«a10 3em口■= 也心 口口on 三ip*>50DO 垃 3LILn il.=. £«£f £=(H才前="*gM5E(原始文件:链接库\2.png7、ARM构架汇编码转机器码:movr0,#256-->e3a00c01,具体如何转换?rotate=12immed8=11000000000x100参考ARM架构中MOV指令机器码格式,修改其中立即数即可。(链接库\ARM架构rotate=12immed8=11000000000x100cond00I1101SSBZRdshifter_operand立即数二imined_8循环右移(2xrotate)MOV指令机器码312827262524232221201916151211-vro,0x100 11110011101000000000 110000000001度攫)3晒空颂e0-循环右移24位C 高四位:rotate■^日nwJ,低八位,immed_8即数 00x10000000000000000000000000000000123位rotate=U (立即数)Ox4oolOOOOOOOOOOQi循环右移8=;«>1011-0000>00018、进制I无论是十进制、十六进制还是二进制都是对同一数值的不同描述,其实质一数值大小是不变的。如:对数字17该如何表示?「十进制:17二进制:10001二进制:10001十六进制:11--->表示同一个数值(可以通过计算方式验证)〔八进制:21II十进制一->n进制(二进制、十六进制、八进制)III为何引入:1)二进制(从硬件方面):在电子系统中,晶体管只有两个状态(on:1;off:0),数据使用多个晶体管来表示。如:8bit数据-->8个晶体管用二进制描述,吻合硬件状态。2)八进制:方便对二进制的记忆。3bit一组(1组用八进制1位表示)。「000---0黑二2J11---73)十六进制:更加方便对二进制的记忆。4bit一组(1组用十六进制1位表示)。‘0000---00001---140010---2J111---15IV快速转换2/8/16进制:8421-->二进制权重1111=1X23+1X22+1X21+1X20=1X8+1X4+1X2+1X1二进制一>八进制(划分为3bit一组,按组计算:421二进制一>十六进制(划分为4bit一组,按组计算:8421八进制或十六进制转成二进制同理。V在C语言中表示二进制、八进制、十进制、十六进制:1)C语言中没有语法表示二进制,只能表示八进制、十进制和十六进制inta=96;//表示十进制inta=0140;//0开头表示八进制inta=0x60;//0x开头表示十六进制以上表示方法都为C语言中语法,即在C语言中以这种格式书写会被编译器识别所采用的进制。(也可以看出不同的进制表示的同一数值参考:链接库\003.编程知识.进制.jpg9、字节序inta=0x12345678;1)对于十六进制,一位表示4bit,两位表示1个字节。2)计算机中,一个字节对应一个地址编号。即,1个地址中存放1个字节数据(十六进制的两位3)数据在内存中两种存放方式:小字节序:低位存在低地址;(一般arm芯片都使用小字节序,S3C2440可修改字节序)大字节序:高位存在低地址10、位操作移位左移:a<<2=aX22右移:a>>2=a/22取反(~,not原来为0的位一>1原来为1的位一>0位与(And)1&1=1;1&0=0;0&1=0;0&0=0。位或(or1|1=1;1|0=1;0|1=1;010=0。置位(由基本位操作完成,置位指将相应位设置为1如:inta=0x123,把Bit7、8置位intb=a|(1<<7)|(1<<8)=0x1a3。清位(由基本位操作完成,清位指将相应位设置为0如:inta=0x123,把Bit7、8清位intb=(a&(〜(1<<7)))&(〜(1<<8))=0x23参考:链接库\004.编程知识.节序—位操作.jpg11、C语言操作LEDI指针:1)所有变量在内存中都有一块区域inta=123;int*p=&a;-->p所在内存中存放a所在内存的起始地址。2)可以通过变量或指针来操作内存。int*p=A1;*p=789;-->若①p的值是A1;②p的类型是1世*-->把789写入A1对应的4字节(int)内存中。II写出了main函数,谁来调用它?main函数中变量保存在内存中,这个内存地址是多少?答:还需要写一个汇编代码,给main函数设置内存,调用main函数IIINand和Nor启动区别:当从NAND启动时cpu会自动从NANDflash中读取前4KB的数据放置在片内SRAM里(s3c2440是soc),同时把这段片内SRAM映射到nGCS0片选的空间(即0x00000000)cpu是从0x00000000开始执行,也就是NANDflash里的前4KB内容。因为NANDFLASH连地址线都没有,不能直接把NAND映射到0x00000000,只好使用片内SRAM做一个载体。通过这个载体把nandflash中大代码复制到RAM(一般是SDRAM)中去执行。当从非NANDflash启动时norflash被映射到0x00000000地址(就是nGCS0,这里就不需要片内SRAM来辅助了,所以片内SRAM的起始地址还是0x40000000).然后cpu从0x00000000开始执行(也就是在Norflash中执行)。即,Nor中可以直接执行程序,Nand必须以SRAM为载体,将Nand中程序转存到SRAM中,在SRAM中执行程序。Nand启动时,需要把做核心的启动程序放在NandFlash的前4K中。IV理解栈顶与栈底(栈区向下增长SRAM大小为4k,故只能从NandFlash中转移前SRAM大小为4k,故只能从NandFlash中转移前4k数据到SRAM中,4k=4096字手动申请.手动回收未初始化的全局变量和好态变量发起函数调用时存放函数内局部变量自动申请.自动回收中、3・BSS(BlockStartedbySymbol)节,1字节对应一个地址,4k对应4096个地址,地址编码从0x0000到0x1000(0d4096),高地址为栈顶,故栈顶指针sp可设置为sp=4096(0x1000)IV为何为什么nor启动要将栈顶指针sp设置为0x40000000+4096sdram的地址是:0x30000000-0x40000000。nand启动时,片内ram在0地址处。nor启动时,片内ram在0x40000000往后的4k(即此时SRAM地址范围是0x40000000-0x40000000+4k),此时的栈顶可以设置到内存的上限0x40000000+4kVI将地址数据直接赋给指针会报警告,如:unsignedunsignedint*pGPFCON=0x56000050;unsignedunsignedint*pGPFDAT=0x56000054;警告:led.c:5:warning:initializationmakespointerfromintegerwithoutacastled.c:6:warning:initializationmakespointerfromintegerwithoutacast这对结果没有影响,可以将地址数据强制转化成unsignedint*型就可消除警告。如:unsignedint*pGPFCON=(unsignedint*)0x56000050;unsignedint*pGPFDAT=(unsignedint*)0x56000054;12、补充汇编指令add:addr0,r1,#4;r0=r1+4subsubr0,r1,#4;r0=r1-4subr0,r1,r2;r0=r1-r2BL:branchandlinkblxxx:1)跳转到xxx;2)把返回地址(下一条指令地址)保存在lr寄存器

1dm(m_many):读内存,写入多个寄存器stm(m_many):把多个寄存器的值写入内存stmdb:先减、后存sp!:sp等于最终的被修改的sp的值Idmia:先读、后增。参考:链接库\002—编写LED程序.jpg注:1)_start:〃可理解为C语言中的函数名2)R0-R3(即a1-a4)寄存器为工作寄存器,可以被破坏,随意使用。(可以理解为一般的内存,能够存储中间数据等)寄存器刍字Reg#APCS意义RO al 工作寄存器TOC\o"1-5"\h\zRI :i2 ”R2 a:3 ”R3 ”R4 vl 必须保护R5 v2 ”KB v3 r,RT v4 ”E8 v5 ”R9 v6 ”RID h1 栈限制Ml fp 桢指针RI2 ipR13 国 栈指针lr 连接寄存器R15 pc 程序计数器3)BSS(BlockStartedbySymbol)发起函数调用时存放函数内局部变・自动申请,自动回收BSS(BlockStartedbySymbol)发起函数调用时存放函数内局部变・自动申请,自动回收对于上图栈区、堆区、BSS、data段、代码段的解释:该整块空间(包含栈区、...、代码段)可以为SRAM(Nand启动时,4k)、Nor(Nor启动时)。比如Nand启动时,内存地址从低地址0x0000开始到高地址0x1000,共4字节从低地址开始依次为代码段、数据区 栈区,中间可能有部分区段没有(如,可能只有代码区和栈区)因为代码段和栈区使用的较多,因此应该将栈区在高地址,距离代码段最远,防止出现内存覆盖现象。(参考讲课笔记深入理解)4)调用函数之前需要把寄存器(fp、ip、pc等)数据压入栈中,调用结束之后把栈中数据取回寄存器。(保护现场)压栈:push{fp};或stmdbsp!,{fp,ip,lr,pc)出栈:pop{fp};或ldmiasp,{fp,sp,pc)5)pc:程序计数器,保存当前所执行指令的地址(从0地址指令开始执行,即pc=0,依次增加)。6)bxlr:相当于MOVpclr,Ir中保存子程序返回地址,在子程序执行结束后,执行bxlr将返回地址复制到程序计数器pc中,便可实现子程序的返回。(因为程序跳转到子程序后,程序计数器pc必定发生变化,pc中的值为当前子程序指令所在的地址)7)同一代码的反汇编结果可能不同。8)栈:sp所指向的内存(本质上就是一块普通的内存空间)。作用:①保存寄存器值(压栈、出栈一>保护现场)②局部变量。9)程序中并不一定需要main函数,之前写程序都是以main函数开始,是因为编译器给封装好了,程序开始直接跳转到main函数来执行(bmain)。我们也可以不写main函数,写成其他函数(bfun)。可以理解为这些过程都在一个汇编文件中封装好的,而我们现在就要自己动手写这个汇编文件(start.S),来实现这些功能。汇编中调用函数传参方法:MOVr0,p1;MOVr1,p2;MOVr2,p3bfun;(相当于:fun(p1,p2,p3);)。10)栈指向一块内存,该内存可读可写,只要不与代码存储区域冲突即可栈从上往下增长,代码存储区从下往上增长)11)区分Nand启动和NOR启动:Nand启动时,0地址对应片内内存;NOR启动时,0地址对应NORFlashNORFlash可以理解为类似硬盘的东西,可以像内存一样读,但不能像内存一样写(对于NOR

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论