您好,欢迎访问三七文档
当前位置:首页 > 金融/证券 > 综合/其它 > EasyARM1138学习过程
今天拿到了周立功的EasyARM1138开发板,又要准备大干一场了!晒晒:我准备分以下几个方面开始学习:1.了解LM3s1138内部结构,包括存储器,ADC,GPIO,等等。其中我认为最重要的是对各个寄存器地址的掌握。因为个人认为写驱动程序就是对各种寄存器的读写,只要把各个寄存器的地址弄清楚了(个人愚见),那么很多问题也就迎刃而解了。2.熟悉软件开发平台IAR。这一点我就不想多啰唆了,反正每个处理器都有一个自己的软件开发平台,所以我就烦感:又得花时间去熟悉。那么多家大公司能不能合伙一起开发一个软件平台呢,这样给用户带来好多的方便。3.软件硬件结合开发。这就要好多东西了~!有的搞的,呵呵。。下面结合实例程序谈谈对这个板子的理解。这是一个简单的LED程序:第一行是添加到系统的头文件,我们找到这个头文件:在这个头文件里面,又包含了很多的头文件,还有一些宏定义,不要怕麻烦,在看看这些子头文件里面到底是什么:我们打开第一个头文件hw_types.h,字面意思应该是硬件类型的定义。打开看看就知道了:果然如此,第一句就说这是Stellaris外设驱动程序库3223的一部分;第二句蓝色字体就是说定义了一个Boolean类型,它的值是true表示1,false表示0。我们接着往下看:同样,这里也无非就是些#define,咋一看有点复杂。不怕,我们看看蓝体字:意思是宏硬件访问,不管是直接访问还是通过bit-band区域访问。这里我对bit-band就不了解了,没关系,现在就去了解它。查看lm3s1138的datasheet。这里说的很清楚。具体是这样的:Stellaris器件内部的SRAM的地址是0x2000.0000,为了减少读-修改-写(RMW)操作的时间,ARM在Cortex-M3处理器中引入了bit-banding技术。在bit-banding使能的处理器中,存储器映射的特定区域(SRAM和外设空间)能够使用地址别名,在单个原子操作中访问各个位。使用下面的公式来计算bit-band别名:bit-band别名=bit-band基址+(字节偏移量*32)+(位编号*4)例如,如果要修改地址0x2000.1000的位3,则bit-band别名计算如下:0x2200.0000+(0x1000*32)+(3*4)=0x2202.000C通过计算得出的别名地址,对地址0x2202.000C执行读/写操作的指令仅允许直接访问地址0x2000.1000处字节的位3。其中0x2200.0000是bit-band基址的起始地址,0x1000是偏移地址,3是位编号。好,这里先告一段落,我们继续看前面的宏:#defineHWREG(x)(*((volatileunsignedlong*)(x))这一句后面的(*((volatileunsignedlong*)(x)))是什么意思呢?我也不知道了,那么百度一下吧。搜到这样的文章:#defineA(*(volatileunsignedlong*)详解2008/08/0309:00A.M.#defineA(*(volatileunsignedlong*)0x48000000)对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的。如果系统结构支持独立的IO地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,因为C语言并没有提供真正的“端口”的概念。如果是内存映射,那就方便的多了。举个例子,比如像寄存器A(地址假定为0x48000000)写入数据0x01,那么就可以这样设置了。#defineA(*(volatileunsignedlong*)0x48000000)...A=0x01;...这实际上就是内存映射机制的方便性了。其中volatile关键字是嵌入式系统开发的一个重要特点。volatile(可变的)这个关键字说明这变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。这种“意想不到地改变”,不是由程序去改变,而是由硬件去改变。volatile限定编译器不对这个指针的指向的存储单元进行优化,即不用通用寄存器暂时代替这个指针的指向的存储单元,而是每次取值都直接到指针的指向的存储单元取值.volatile主要用于变量会异步改变的情况下,主要有三个方面:1.cpu外设寄存器2.中断和主循环都会用到的全局变量3.操作系统中的线程间都会用到的公共变量.上述表达式拆开来分析,首先(volatileunsignedlong*)0x48000000的意思是把0x48000000强制转换成volatileunsignedlong类型的指针,即对指针的操作的范围是从0x48000000开始的4个字节(long型).暂记为p,那么就是#defineA*p,即A为P指针指向位置的内容了。这里就是通过内存寻址访问到寄存器A,可以读/写操作!仔细看看这位兄台的文章,说的很清楚了。那么我们的那句:#defineHWREG(x)(*((volatileunsignedlong*)(x))就是等于#defineHWREG(x)(x),这里的(x)就是你想设置的存储器地址了。例如HWREG(0x22000000)=0x12就是把0x12这个数存储在地址0x22000000里面。呵呵~A=HWREG(0x22000000)就是把存储空间0x22000000里面的数据读出来。OK,这里搞定!接下来看下面这个宏:#defineHWREGBITW(x,b)HWREG(((unsignedlong)(x)&0xF0000000)|0x02000000|(((unsignedlong)(x)&0x000FFFFF)5)|((b)2))初一看有点长,其实不用怕。一步一步来:首先根据C语言的语法规则()的优先级最高,那先算()里面的呗。b2=b*4记为b1;(x)&0xF000000就得到高4位的值,低28位置0记为X1;x&0x000FFFFFF就得到低20位的值,高12位置0记为X2;X25=X2*32记为X3;X1|0x02000000记为X4;X3|X4记为X5;好,现在设x=0x20001000,b=3。那么算得X5=0x2202000C。这个X5貌似见过,对,哈哈就是上文的bit-band的值。现在清楚了:这个宏的作用就是计算对应的bit-band的地址。例如:HWREGBITW(0x20001000,3)=1就表示把1写进0x20001000存储空间的位3,而且对应的bit-band地址是0x2202000C的位3。同理下面两个defineHWREGBITH(x,b)HWREGH(((unsignedlong)(x)&0xF0000000)|0x02000000|(((unsignedlong)(x)&0x000FFFFF)5)|((b)2))#defineHWREGBITB(x,b)HWREGB(((unsignedlong)(x)&0xF0000000)|0x02000000|(((unsignedlong)(x)&0x000FFFFF)5)|((b)2))也是一样的,只是数据的宽度不同。至此,hw_types.h头文件里面的宏都差不多弄清楚了。说差不多是因为还有些我不懂的东西,贴图期待高手解决:今天是学习LM3s1138的第二天,我们接着昨天的继续学习。昨天我打开了SystemInit.h的头文件,深入学习了里面的hw_types.h子头文件。今天我开始学习另外的几个头文件:hw_memmap.h。这个头文件就比较简单了从字面意思看就知道是存储器映射的头文件。我们打开看看,果不其然:这和LM3s1138datasheet上是一样的:只是这个头文件里面只定义了它的起始地址。还有些存储器的映射我这里就不一一例举了。好,接下来看看hw_ints.h里面的东西:从第一行看这是一个定义错误的任务;我们看看datasheet上是怎么说的:我的理解是这样的:CPU的中断是由异常引发的,异常也有多种。于是怎么处理多个异常呢?ARMCortex-M3处理器和嵌套向量中断控制器(NVIC)区分所有的异常并对其进行处理。在出现异常时,处理器的状态被自动存储在堆栈中,并在中断服务程序结束后自动从堆栈中恢复。所以CPU先给每个异常分配一个堆栈地址即向量号。这样就处理好了异常的先后顺序。比如:#defineFAULT_NMI2就表示不可屏蔽的中断(NMI)是优先级为2的级别这里就用FAULT_NMI表示它在堆栈中的具体优先级2,这样既清楚又方便。其他的同理。继续往下看:这定义的是中断顺序号和上面的异常是一样的,这里就不在啰唆了。好,那么关于hw_ints.h头文件就初步学习了。下午再看下面的interrupt.h://*****************************************************************************////interrupt.h-PrototypesfortheNVICInterruptControllerDriver.////Copyright(c)2005-2008LuminaryMicro,Inc.Allrightsreserved.////SoftwareLicenseAgreement#ifndef__INTERRUPT_H__#define__INTERRUPT_H__//*****************************************************************************////IfbuildingwithaC++compiler,makeallofthedefinitionsinthisheader//haveaCbinding.////*****************************************************************************#ifdef__cplusplusexternC{#endif//*****************************************************************************////Macrotogenerateaninterruptprioritymaskbasedonthenumberofbits//ofprioritysupportedbythehardware.////*****************************************************************************#defineINT_PRIORITY_MASK((0xFF(8-NUM_PRIORITY_BITS))&0xFF)//*****************************************************************************////PrototypesfortheAPIs.////*****************************************************************************externtBooleanIntMasterEnable(void);externtBooleanIntMasterDisable(void);externvoidIntRegister(unsignedlongulInterrupt,void(*pfnHandler)(void));externvoidIntUnregister(unsignedlongulInterrupt);externvoidIntPriorityGroupingSet(unsignedlongulBits);externunsignedlongIntPriorityGroupingGet(void);externvoidIntPrior
本文标题:EasyARM1138学习过程
链接地址:https://www.777doc.com/doc-3995101 .html