您的当前位置:首页IAR 2440 初步

IAR 2440 初步

2022-10-01 来源:乌哈旅游
采用IAR 作为2440开发板单片机部分的开发环境不知道是否正确。

首先对IAR 开发环境做一下简要介绍对IAR开发环境并不了解,在网上查找到的资料也都是IAR 4.3的,而我所使用的IAR5.20的资料相当少。IAR5.20 与IAR4.3的主要区别在于IAR5.20开始连接器linker开始采用ilinker,不再是以前4.30所采用的xlinker,连接生成的文件 格式为标准的elf格式文件。不要小瞧这个修改,就是这部分导致IAR5.20环境上手十分困难。

IAR5.20 EWARM支持几乎所有的ARM核CPU,包括最新的Context M3,ARM 11等,并且IAR环境为许多嵌入式CPU提供了相应的例程,当然,各个例程大多只是提供对相应CPU的初始化,引导main函数等操作。而对于没有在例程中出现的CPU就非常非常麻烦了,这就意味着开发环境没仅为你提供了基本的一些设置方法,所有的部分需要自己根据CPU的spec进行设置,同时由于是 用IAR开发环境,你还需要了解IAR开发环境的设置方式。为了调通第一个IAR下的2440A点灯程序费了我将近半个月的业余时间,现在把总体过程总结 一下,希望能够对大家有所帮助。

首先,IAR5.20环境的基本设置我就不详细说了,网上关于这部分有很多。CPU类型不选错就好啦,哈哈,只说 几个重中之重,关键的部分,

在C/C++ Compiler选项Preprocessor选项中可以添加自己的头文件路径,$PROJ_DIR$\\代表工程目录,例 如:$PROJ_DIR$\\inc\\;

最重要的是Linker选项卡中,一定要在Config配置项中设置自己的icf配置文件,对该部分下面会 详细说明。在该选项卡的List选项下勾选Gererate linker map file,这个map文件非常重要,由IAR在链接是自动生成,map文件内包含的就是在链接过程中不同文件在最终二进制文件中所处的置是否正确。

在 Debugger选项卡中是关于所使用的仿真器的描述选择自己的调试工具,这部分下面也会有详细说明。

下面进行详细说明:进行嵌入式开 发,IAR5.20只是一个编译环境,编译生成目标CPU上可运行的二进制代码而已。这句似乎就是废话,任何有一点嵌入式经验的人都知道。但这句话的潜台 词就是进行嵌入式开发,如果你不是运行在操作系统之上的,那么你就需要完成所有的硬件初始化,CPU 总线、flash,SDRAM,各个IO端口,等。这样我们就需要了解CPU的启动过程,CPU启动后运行代码的过程。而这部分是我们正常开发软件所不会 接触的。为了快速开发嵌入式、减低嵌入式开发的难度,在IAR环境中为很多CPU提供程序运行时所处内存位置的描述。也就是我们刚才所提到的icf文件。 <.icf文件的重要性>

icf 链接文件内包含对程序段各部分存放位置的描述,相当于ADS中link内文件摆放位置就是最终代码顺序的关系。默认所使用的icf文件在IAR文件夹 下\\IAR Systems\\Embedded Workbench 5.0 Evaluation\\ARM\\config文件夹下的generic.icf文件,我们可以将该文件拷贝到工程目录中,通过在Config选项卡中选择 路径来配置自己的icf文件,在icf文件中需要指定interrupt vector的位置,默认的ARM处理器在启动后都是从0x0000 0000位置开始设置中断向量表的,可以查找芯片的中断向量表修改,对应几个模式的中断处理函数的地址,在Memory Region内包括对CPU内的ROM,RAM空间的地址,这里就要详细说明了,首先如果你所使用的CPU只使用CPU内部的SROM,SRAM的话,直接查找SROM,SRAM所对应的地址填入就好啦,这里的数值还涉及到你所采用的调试方式,如果采用仿真器调试的话,可以将ROM RAM地址都指定为CPU内SRAM的地址段,这样程序通过仿真器就自动的下载到CPU内SRAM运行了。如果在CPU外有自己的SDRAM的话,就把 RAM地址段

指定为SDRAM在CPU内映射的位置,同时在启动程序中需要设置SDRAM内存段的配置。同样如果采用片外的NAND FLASH/NORFLASH的话在ROM地址段就需要在启动代码段内进行相应的初始化设置。最后需要设置各种堆栈的大小,CSTACK是C程序运行所需 要的堆栈空间,下面的SVC,IRQ,FIQ,UND,ABT分别对应ARM内5种特殊运行模式的堆栈空间,在ARM下用户态与超级系统态内所使用的堆栈 空间是相同的,可以根据代码量、RAM空间的大小进行设置,HEAP/CSTACK应该设置的大一些,至少要0x1000以上。

如果不使用Linker选项卡下Config选项中Edit可以使用IAR提供的脚本进行自动的修改,我们也可以通过手动直接修改icf文件来实现。通过阅读icf文件我们可以发 现在icf文件中根据我们的设置选项生成了多个堆栈空间地址。我们所指定的堆栈都在指定的RAM 空间中。

对icf文件的描述就到这里,完成 icf文件的设置后,我们需要编写自己的startup代码,我们可以通过修改IAR5.20例子中所提供的cstartup.s文件修改为自己的CPU 启动代码。在IAR5.2O中,程序启动以__iar_program_start段名指定,可以再Linker选项卡Library选项内进行修改,改 为自己指定的启动段名。修改cstartup的代码我就不献丑了,附上一个标准的cstartup.s代码,大家考下来看看就明白了,需要添加自己的代码 就在相应的位置进行添加。

MODULE ?cstartup

;; Forward declaration of sections. SECTION IRQ_STACK:DATA:NOROOT(3) SECTION ABT_STACK:DATA:NOROOT(3) SECTION SVC_STACK:DATA:NOROOT(3) SECTION UND_STACK:DATA:NOROOT(3) SECTION FIQ_STACK:DATA:NOROOT(3) SECTION CSTACK:DATA:NOROOT(3) ;

; The module in this file are included in the libraries, and may be

; replaced by any user-defined modules that define the PUBLIC symbol ; __iar_program_start or a user defined start symbol.

;

; To override the cstartup defined in the library, simply add your ; modified version to the workbench project. SECTION .intvec:CODE:NOROOT(2) PUBLIC __vector

PUBLIC __iar_program_start

EXTERN undef_handler, prefetch_handler, data_handler, EXTERN irq_handler, fiq_handler

ARM

__vector:

;;

ldr pc,=__iar_program_start ;; Reset

B . ;; Undefined instructions

B . ;; Software interrupt (SWI/SVC)

B . ;; Prefetch abort B . ;; Data abort B . ;; RESERVED ldr pc,[pc,#-0xF20] ;; IRQ ldr pc,[pc,#-0xF20] ;; FIQ ; --------------------------------------------------

; ?cstartup -- low-level system initialization code. ;

; After a reser execution starts here, the mode is ARM, supervisor ; with interrupts disabled. ;

SECTION .text:CODE:NOROOT(2) ; PUBLIC ?cstartup EXTERN ?main REQUIRE __vector ARM __iar_program_start: ?cstartup:

;

; Add initialization needed before setup of stackpointers here. ;

; Initialize the stack pointers.

; The pattern below can be used for any of the exception stacks: ; FIQ, IRQ, SVC, ABT, UND, SYS.

; The USR mode uses the same stack as SYS.

; The stack segments must be defined in the linker command file, ; and be declared above. ;

; --------------------

; Mode, correspords to bits 0-5 in CPSR

MODE_BITS DEFINE 0x1F ; Bit mask for mode bits in CPSR USR_MODE DEFINE 0x10 ; User mode

FIQ_MODE DEFINE 0x11 ; Fast Interrupt Request mode IRQ_MODE DEFINE 0x12 ; Interrupt Request mode SVC_MODE DEFINE 0x13 ; Supervisor mode ABT_MODE DEFINE 0x17 ; Abort mode

UND_MODE DEFINE 0x1B ; Undefined Instruction mode SYS_MODE DEFINE 0x1F ; System mode

MRS r0, cpsr ; Original PSR value BIC r0, r0, #MODE_BITS ORR r0, r0, #ABT_MODE MSR cpsr_c, r0 LDR sp, =SFE(ABT_STACK) BIC r0, r0, #MODE_BITS ORR r0, r0, #SVC_MODE MSR cpsr_c, r0

LDR sp, =SFE(SVC_STACK) BIC r0, r0, #MODE_BITS ORR r0, r0, #UND_MODE MSR cpsr_c, r0 LDR sp, =SFE(UND_STACK) BIC r0, r0, #MODE_BITS ORR r0, r0, #FIQ_MODE MSR cpsr_c, r0 LDR sp, =SFE(FIQ_STACK) BIC r0, r0, #MODE_BITS ORR r0, r0, #IRQ_MODE MSR cpsr_c, r0 LDR sp, =SFE(IRQ_STACK) BIC r0 ,r0, #MODE_BITS ORR r0 ,r0, #SYS_MODE MSR cpsr_c, r0 LDR sp, =SFE(CSTACK) #ifdef __ARMVFP__

;; Enable the VFP coprocessor.

MOV r0, #0x40000000 FMXR fpexc, r0 ; Clear the mode bits ; Set ABT mode bits ; Change the mode

; End of ABT_STACK ; Clear the mode bits ; Set SVC mode bits ; Change the mode

; End of SVC_STACK

; Clear the mode bits ; Set UND mode bits ; Change the mode ; End of UND_STACK ; Clear the mode bits ; Set FIQ mode bits ; Change the mode ; End of FIQ_STACK ; Clear the mode bits ; Set IRQ mode bits ; Change the mode

; End of IRQ_STACK ; Clear the mode bits ; Set System mode bits ; Change the mode ; End of CSTACK ; Set EN bit in VFP ; FPEXC, clear others.

;

; Disable underflow exceptions by setting flush to zero mode.

; For full IEEE 754 underflow compliance this code should be removed ; and the appropriate exception handler installed. ;

MOV r0, #0x01000000 ; Set FZ bit in VFP FMXR fpscr, r0 ; FPSCR, clear others. #endif ;

; Add more initialization here ;

; Continue to ?main for C-level initialization. LDR r0, =?main BX r0 END

在完成cstartup.s后我们就可以最基本的使用C代码进行编程了,大家加油啊!!

其实IAR环境的选项众多,它们就是gas gar等进行编译时选项,只是IAR环境以可视化的形式进行呈现了,还有就是icf文件,icf文件在这里其实就是表现为在调用cstartup.s前所 使用的一个选项文件,链接器会根据该文件进行代码段的安排,为了不造成冲突,需要在cstartup.s中根据icf文件对堆栈进行相应的设置。在完成 cstartup.s后就可以进入main函数了,这里的main函数还只是能够运行最基本的c语言,对所要使用的C函数库的话还要查找相应的文件进行相 应的设置才行。深入进去后再了解吧。IAR环境非要加入个icf文件,并且隐藏提供cstartup.s文件,这个到底是方便了还是复杂了就是仁者见仁的 事了。

总结如下:首先进行嵌入式开发就需要对CPU的data sheet认真仔细的阅读一下,重点是CPU memory地址分配、CPU启动后中断向量位置,等,在IAR5.20的环境中,它的编译过程其实就是首先编译icf文件,后在cstartup中使用 icf文件内声明的程序段位置进行初始化的过程。就是说icf文件相当于程序链接后的Option程序,在icf文件中声明这些变量的值在 cstartup.s中直接使用这些变量。在CPU启动后其实只要有堆栈空间,就为CPU提供了最基本的运行环境,也就是在icf文件的内容为CPU启动 的最基本设置值,在cstartup.s中只需要将icf内的堆栈变量赋给系统各个模式就可以跳转到main函数运行了。在IAR5.20中所使用的汇编 语言比较特殊,我们不必完全掌握,其提供的examples内有比较多的启动代码,可以通过修改这些例子来实现我们的需要。好啦,就先写这些吧,希望对大 家有帮助。天道酬勤!诸君共勉!

New Article

对使用IAR 5.20编写cstartup.s启动2440的几个提示:

1.IAR 5.20在编译时是使用__iar_program_start做为初始代码起始处的标志的。编译时 IAR会自动搜索该标志,并把该文件连接到内存起始处。

2.使用IAR 调试2440启动代码的时候,我们一般使用的是JLINK仿真器调试,在IAR下识别为RDI设备时,使用是能够正常使用的,但调试结束的时候会告诉你找不到iarlibsuppot.dll这个文件,其实不用管它,不影响调试的,如果有人知道如何修正这个问题请告诉我,找了个很久也没找到解决办法。

3.启动2440开发板首先要关闭看门狗,这个东西会导致我们的程序运行一段时间后就自动进入IRQ中断服务例程里面,2440默认启动时自动启动看门狗,看门狗的详细资料各位查找手册就知道了,简单说就是看门狗用来检测程序是否跑死了,重要的一个函数是喂狗程序,如果一段时间内喂狗程序没有运行,CPU认为程序已经跑死了,就自动重启系统,而由于我们使用的是JLINK的调试方式,CPU一重启,JLINK就已经不能对CPU控制了,这就是为什么我们在最初点个LED灯一会就灭的原因。而正常的单片机如果使用看门狗的话,是要定时喂狗的,这样程序就能正常运行了,在我们的程序中,简单的方法就是初始化时先关闭看门狗功能。 New 2

弄到2440的开发板也有3个多月了,这中间一直是在业余时间哩哩啦啦的弄着,开始打算好好熟悉一下将2440作为单片机进行开发,本来计划是1 个月,就好啦,可没想到居然弄了这么久。这里面的原因总结如下,希望对大家有帮助:

首先说一下我的设备:TQ2440开发板,64MB SDRAM,256MB NANDFLASH,2MB NORFLASH ,JLINK7调试器,IAR5.20 EWARM开发环境。

本来按照2440的DATA SHEET以及我在前一篇初始中所说的步骤进展还是很顺利的,俗话说万事开头难,在前一篇博客中,本来已经能够运行闪灯程序了,按理来说,也就是开发环境 已经搭建完毕了。

可在进行中断的实验过程中,出现了奇怪的问题。发现无论如何也进不了中断,反汇编后的语句居然是LDR PC,[PC,#0 ],怎么都不行,开始以为是程序的问题,就把设置vector的语句按照好几种方式进行编写,结果不行。后来以为是设置icf文件将程序都放在片内 SRAM

内运行,所以不行,后来查了大量资料,发现其实icf只是告诉IAR在link过程中如何链接程序段,这个过程耗费了大量时间,结果中断还是进不 去。

最后想来想去,只能是JLINK的毛病了,可是我在使用过程中对JLINK印象中没有改过什么设置啊。死马当活马医,将JLINK不连接IAR,使 用JLINKARM直接向板子内烧录一个bin,结果居然告诉我找不到CORE,当时百思不得其解,又使用JLINK.EXE查看一下,在命令行下一切正 常,能够看到2440。开始以为是JLINK硬件有问题,想邮回原厂修一下,后来一想有没有可能是JLINKARM设置的问题那,又看了一下JLINK的 使用手册,比对我的设置,JLINK的设置选项比较少,如果不适用FLASH编程那些东西,对单片机开发来说可设置的主要就是关于时钟频率那里了,最后居 然发现在JLINKARM中我的JLINK初始时钟设置的是兼容性频率,初始完毕的时钟是自动,把初始时钟改为自动后,一切都恢复 了。。。。。。。。。。。,JLINKARM能够烧录进程序了,中断也能够进去了。这个情况好像主要是兼容性频率针对一些比较特别的板子,如LPC系列 的,正常设置自动,JLINK会首先进行测试,再与MCU通讯,问题终于找到啦。

总结:对于使用IAR进行中断测试的时候,有很多例程可以参考,但遇到进不去中断的奇怪错误,现在想来,是IAR使用JLINK不正常造成的,可 JLINK设置错误的话,为什么程序运行正常,只是中断向量部分不正确那,猜测应该是在设置中断向量时JLINK时钟还不正常,在初始化完成后JLINK 才恢复正常。总之,把这个问题贴出来,希望能帮到碰到同样问题的童鞋。JLINK........... New 3

以JLINK为例,我们知道,在使用JLINK过程中,如果除去IAR,AXD等开发工具的支持,单纯使用JLINK提供的JLINK ARM对MCU进行烧录,运行的话,首先需要在JLINK ARM内建一个工程,对工程进行设置,主要包括MCU型号,片内FLASH,片外FLASH等的型号等,其中对MCU的设置,主要指定MCU内片内SRAM的地址,是否含有片内flash等信息,flash芯片的相关信息主要指定所使用的flash NORFLASH芯片的读写规则,主要指位宽,扇区大小,芯片容量等信息。除此之外再JLINK ARM工程内主要包括的就是JLINK时钟频率等通用信息了.Eddy:还包括对存储控制器的设置呢

在JLINK ARM工程内,应该说最重要的就是JLINK 进行仿真过程执行前进行的准备工作了,对该部分内容我的理解是,首先在进行JTAG口进行调试的过程,实际上也是一个使用JLINK对MCU硬件进行编程的过程,是JLINK通过MCU向MCU内相关的地址进行数据传输

的过程,在该过程中MCU也是在正常运行的,也就是说如果在仿真时需要写入Nor flash或者SDRAM,都是需要首先对相关的寄存器进行设置的,否则MCU并不能够访问与自身连接的SDRAM,Nor flash等设备。而这就需要JLINK在进行对MCU外围设备进行写入操作之前初始化相应的环境,也就是初始化MCU相应的寄存器,这样做的目的是将MCU带入一个确定的初始化状态,在该状态下,MCU能够正常访问自身的SDRAM,Norflash等外设。为了达到这一状态,JLINK一般的执行过程就是首先重启MCU,为了防止JLINK在烧录MCU过程中受到其他中断等异常向量的干扰,需要执行关闭看门狗,关闭中断响应等操作,接着对MCU内与写入数据的外设(SDRAM,Norflash等)相关的寄存器进行配置,使各个外设能够正常访问了,就可以通过JLINK向MCU相关外设写入编译后的程序了。 在进行烧录完毕后就可以重启MCU使MCU自动执行程序了, 这个过程又涉及很多内容,如果当时烧录的是片内flash,或者为片外Norflash的话,MCU断电自动启动读取相应的程序,而如果直接写入的为SDRAM,SRAM的话,则只能进行线上调试,也就是只能工作AXD,GDB等调试工具通过JLINK进行调试,断电后内容自动消失。但是二者之间的区别就是使用SRAM,SDRAM进行数据写入速度快,调试速度也比较快,这样能够大大提高调试的速度,因此在开发过程中一般是使用SRAM,SDRAM对工程进行调试工作的,在产品中使用flash的方式。

再说一下使用JLINK在集成开发环境下的启动,使用过程,这里,我们一JLINK配合IAR为例来说明,在IAR下使用JLINK需要的配置项非常简单,就是一个.mac结尾的初始化文件,该文件与在JLINK ARM工程中的初始化的过程一样,同样是进行烧录环境的初始化。只是两者语句上略有差异,但所使用的寄存器,初始化值都是相同的。

最后总结一下仿真器执行过程,首先明确,仿真器并不是直接向MCU的相 关管脚写入数据的,仿真器只是通过JTAG口向MCU发出相关的指令,通过MCU向MCU自身相关的 管脚输入出 数据。也就是说,JLINK烧录是不可能越过MCU的一环的,烧录首先需要使MCU正常工作,MCU能够正常访问外设(SDRAM,SRAM,Norflash)的话JINK才能执行相应的写入操作。其次,为了使MCU进入这个适宜烧录的确定状态所执行的那些诸如关闭看门狗寄存器,中断寄存器等的执行过程只是一个在烧录过程中所执行的,与烧录的程序无关,也就是编写的嵌入式程序首先依然要执行这个初始化的过程,JLINK所执行的烧录过程只是进行烧录,烧录完成后,会自动重启MCU,初始话所写入的寄存器也就无效了。所以其实使用仿真器进行硬件仿真所调用的初始化寄存器与程序运行后的过程是无关的,不能将二者混淆。

以上,已经将我对仿真器的理解进行了说明,上述如有不妥,请各位看官不啬赐教,共同讨论。 New 4

对嵌入式软 件的开发,讲解的教程、教材都比较多,但这些都还只是在理论上进行说明,并且,对开发环境、仿真器的作用对于一个嵌入式开发的门外汉来讲都是非常复杂的知识,这里就将我所总结出来的嵌入式开发过程的相关概念进行一下解释,主要是对ARM嵌入式中关于片内flash,片外flash,片内RAM,片外

RAM 的相关调试工作进行一下详细的说明。

我所获取的知识的实践环境还是老样子:IAR+JLINK V7.0,这套环境说明一下:IAR是一套非常成熟的嵌入式开发环境,之所以选择它,是因为入门时的项目就是拿他做的,当时用的是LM1138 是M3的ARM核。作为一个嵌入式的门外汉辛辛苦苦的详细了解了IAR环境的一个调试过程,然后就产生了惰性,哈哈,懒得用别的开发环境了。其实就是这样 的,做软件开发的,尤其是嵌入式软件开发,你用什么开发工具其实都是一样的,几种开发工具ADS,IAR,MDK其实都是各有优缺点的,我感觉IAR的环 境下官方例程较多,如果采用比较常见的MCU的话,基本在里面都能找到相应的例程的;并且IAR是在不断更新的,目前的最新版本已经到了5.4.1了,相 对非常成熟,对各种新的核心支持非常及时;ADS是早期对ARM开发支持的最好的环境之一,兼容所有ARM指令集、伪指令集,应该可以说是标准的开发环境 了,但ADS环境永远停留在了1.2版本上,对新ARM核的支持已经无从谈起,它在设计上比较优越的就是将软件调试AXD与编辑ADS是分开两个程序的, 我们可以使用ASD对非ADS开发的bin程序进行调试,算是比较方便的,网上的资源相对来讲也是比较多的,如果是嵌入式爱好者使用ADS作为开发环境还 是相当不错的。MDK没有用过,不太清楚,不过MDK是ARM在放弃ADS环境支持后选择的第二个官方编译环境,对新内核的支持也是非常迅速的。总的说 来,做嵌入式软件开发,选用哪一中开发环境其实都是没有什么关系的,从开发上来讲,他们的主要区别主要还是集中在汇编指令不同、程序入口函数名不同等等, 这些非常细节上的东西,对程序主体所使用的C语言是完全相同的。这些开发环境在网上都有相应的破解版,如果是个人作为学习之用选择哪一个都是无所谓的。

作为仿真器来讲,JLINK我认为是非常值得推荐的,主要原因还是JLINK破解的非常完善,随便在淘宝上一搜就有一堆,现在的价钱又非常的便宜, 一般在80块左右使用起来就没有问题了,与正版的JLINK在功能上现在已经没有什么区别了。JLINK支持几乎所有片内flash烧录,以及大部分的 Norflash的烧录。但JLINK不支持直接的NAND flash的烧录。而目前对产品开发来说所使用的仿真器如ZLG的AK100来说是支持NAND flash的直接烧录的。并且在IAR下不论使用JLINK方式还是RDI的调试方式,都是不能使用JLINK的Norflash烧录程序的,只能使用片内flash的烧录算法。

好啦,上面的工具说明就说到这里;下面主要说一下关于IAR环境调试的主要方式。在嵌入式开发中,由于对flash芯片的烧录速度较慢,读取flash芯片的速度也非常慢,而调试的时候需要频繁修改程序,对程序的读取、写入速度对开发速度影响很大。因此对调试来说,一般讲程序直接烧入片内 ram或者是片外的ram中运行的,这样调试速度极快。这在IAR中是通过在linker中所设置的icf文件所实现的,在调试时,我们一般讲icf中 RAM ROM都设置为片内ram的地址范围,这样程序在链接时所使用的地址范围都在片内ram中,IAR调试时将程序镜像放于片内RAM中,跳转到入口程序 __iar_start就可以对程序进行调试了。但有时片内RAM空间并不够使用,我们需要使用片外的RAM,但是我们需要知道,使用片外RAM的话我们 需要首先设置CPU内相应的存储器管理寄存器,告诉CPU如何访问片外RAM(主要有片外RAM 地址、大小、位宽、时序等)这部分工作是需要在程序写入片外RAM之前就完成的,所以将这部分指令实现为IAR下的linker设置中的mac文件,在该 文件中完成对CPU相关寄存器的设置后,IAR通过仿真器向片外RAM写入数据。这里需要说明一个问题就是异常向量的访问,我们在片内或者片外RAM中调 试程序的时候,是不能够运行正常的异常向量的,我们知道异常向量表是在地址空间0x000000的位置的,一般是flash空间,(不经过 Remap,MMU的修改,关于Remap,MMU在这里就不进行展开说明了,改日再讨论)而我们的程序都是写入RAM地址空间的,这就导致我们的程序如 果进入异常状态那就肯定会跑飞,就是说程序跳转到异常处理函数,而异常处理函数又指向一个不存在的函数地址,这样就非常不方便调试异常状态了。

再说一下关于片内flash,片外flash的调试方法,首先,我们要明确,只要是flash不管是NAND,还是Norflash,对flash 芯片的访问都是需要驱动程序的,这是嵌入式初学者经常糊涂的地方,对Norflash来说,它的地址线、数据线连接与片外SRAM,SDRAM其实是差不 多的,为什么对SRAM,SDRAM我们只需要在mac文件中设置寄存器,而flash确一定要使用驱动程序那,这里,主要是对RAM的访问,我们只需要 设置地址、大小、位宽、时序就可以访问了,而对flash来说,我们在向其中写入或者读出数据,我们首先要向flash芯片内相应的寄存器写入命令才能都 完成后续的读取、写入、设置的操作,这就是flash芯片驱动程序的作用。可能有人发现,IAR下对片内flash并没有设置flash驱动程序啊,其实 这部分在我们设置工程中使用的DEVICE名称时就自动设置好啦,如我们使用LM1138

的芯片,IAR在将程序写入片内flash时,自动调用 LM1138的flash驱动函数向flash中写入程序。这样片外flash又该如何操作那,这里就要说一下啦,只要是flash就必须要有驱动,对 flash芯片的烧录过程就是首先,IAR在芯片的片内RAM中运行flash驱动程序,将程序烧录入片内或者片外的flash芯片中。片内flash 驱动IAR已经自动设置好啦,片外的flash就需要我们来写驱动了,这里就有两种方式来调用驱动了,一个是在IAR下编译根据flash芯片的数据手册 编写驱动,然后通过IAR的flashloader调用编译好的驱动程序,片外flash芯片写入数据。还有就是功能比较全面的仿真器,可以直接在设置时 指定片外flash芯片驱动程序,IAR通过相应的调试接口支持相关的仿真器的在线调试。使用JLINK的话只能通过在IAR下编写片外flash芯片驱动的方式开实现对片外flash芯片读写的需要。

最后说一下程序链接与程序烧录的关系,在程序链接时指定ROM,RAM地址的范围,ROM,RAM其实就相当于程序烧录地址,也就是说,设置链接器 地址时需要对应芯片数据手册、开发板的地址空间范围等,设计好程序运行地址空间,设置链接地址。

对很多概念我也不是很清楚,欢迎大家讨论! New

终于在IAR下将2440A的中断响应调通了,对中断响应部分有了些许新的理解,首先,在IRQ_HANDLER中的主要工作是把当前用户态下的各 个寄存器值复制到堆栈中,保存当前环境,设置返回函数地址,跳转到中断处理函数,在返回函数中恢复现场。简单代码如下:

IRQ_Handler:

sub lr, lr, #4 ;计算返回地址

stmdb sp!, { r0-r12,lr } ;保存使用到的寄存器

ldr lr, =int_return ;设 置返回地址

BL on_irq

int_return:

ldmia sp!,{ r0-r12,pc }^ ;中断返回, ^表示将spsr的值复制到cpsr

这里有几点需要说明一下,中断之所以麻烦,是因为不好跟踪的原因,在ARM中由USER模式到IRQ模式转换后就跟踪不了了,并不是中断部分有多 难。

调试困难原因。这里如果从深层次上来讲就要简单说一下ARM支持在线仿真调试的原理了,简单说就是ARM核带有调试模块,在ARM7TDMI中的 那个I就是这个模块,在ARM9及以上的系列中都带有该模块,从外部来讲就是我们通常说的那个JTAG调试口,我们的仿真器就是通过这个接口控制ARM核 运行或者停止的、读取寄存器状态的。而我们的开发环境如IAR、ADS等等,通过对仿真器的控制、读取将ARM核中的数据传送到屏幕上实时显示、单步运 行,或者将各条指令传送给仿真器,再由仿真器控制ARM核进行指令运行、等待等动作。这种方式在调试正常运行的程序是没有问题的,但在调试ARM特殊状态 时就会产生问题,这里有几点需要说明,首先,在使用开发工具开发程序时,通过编译器将程序编译到相应地址空间中的各个段,再到ARM中运行。为了调试快 速、方便我们在开发时所指定的空间一般都是RAM空间,也就是说我们的程序都是直接运行在RAM空间的,这样读取、写入速度都非常快速,调试方便。也许有 人要问,这调试方法跟中断有什么关系那,这里涉及到的问题就是ARM的特殊模式,在ARM中由用户,特权,中断,快速中断,未定义等等7种特殊模式,与我 们开发经常使用的的主要是用户,特权,中断,快速中断几种模式,其中用户模式是ARM的正常运行模式,其它都叫做ARM的特殊模式,ARM在遇到特定事件 就会进入特殊模式执行相应的程序段,在这里就有一个确定、不确定的问题了,所有的ARM核都有特定的中断向量表,指定每种特殊模式的入口地址,这个向量表 是确定的,特殊模式的入口地址是不确定的是需要我们手动编写程序指定的。而这里就是调试中断的症结所在了,其实ARM核的调试模块只能跟踪在正常USER 模式下运行的指令,不能够在特殊状态下跟踪,这就使我们不能够使用IAR等开发工具跟踪中断入口、中断指令的执行了。其次,就是刚才说的,我们的开发工具 为了开发方便,初期都是将程序运行在RAM中的,目前的高档ARM MCU基本都将程序放在片外的Norflash,或者NAND中,而ARM中断向量表的位置都在这些flash芯片中,也就是说,如果我们想要调试中断程 序,我们就必须把程序烧录到片外的flash芯片中,而片外的flash种类太多,不同厂家flash芯

片都千差万别,我们需要为其编写驱动才能成功将程 序烧录进去,运行速度又慢,调试又进行不了,就是中断调试的困难之处。

如果各位看过我之前的日志的话,就应该知道我所要表达的意思了。由ARM小白一步步调通这个过程又是难上难,现在将问题总结如下:第一,中断肯定不 能用调试工具调试了,这个没什么可说的,不要妄图使用跟踪工具跟踪了。第二,在运行中断时,由于它在中断时是跳到flash中去读取运行的入口地址的,这 就导致如果不明白中断响应过程,调试中断过程中,能够运行中断,但运行的却不是自己想要运行的程序的现象。这是由于你flash空间有问题,在flash 中的中断入口地址不是由你指定的,所以运行的程序当然不是你想要的结果啦。第三,在调试中断时,既不能运行UART,又不能跟踪,我们所能做的就只能是通 过点灯来显示当前工作的状态了。

详细说下中断的调试方法,首先,我们在编译程序时,需要编译为程序段都在ROM,内的最终版(release版)就是说我们自己写的中断向量表要在 ROM起始地址存放异常状态的入口点地址,这是成功运行中断的基础,并为各种异常状态分配相应的异常状态堆栈空间,这里为调试中断,一定要分配中断堆栈空 间。在准备好编译的条件后,编写中断入口函数,这里的入口函数就是我上面程序段中所写的,首先保存当前运行的下条指令,也就是

lr-4(简要说明一下,由于ARM体系是流水线结构的,每级流水处理一条指令,当前运行指令的下一条指令是流水线中的下一条指令,采用lr-4是 其指令地址)后面有一条指令ldr lr, =irt_return就是将返回的执行程序存入返回后的地址内,就是中断返回后所运行的程序位置,接着就将R1~R12几个寄存器放入用户堆栈中保存, (由于ARM体系中不同模式下所使用的寄存器是不一致的,在用户态到中断态中其R1~R12寄存器是通用的,所以需要保存用户寄存器数据,防止在中断状态 下改变各个寄存器,也可以通过这些寄存器为中断传递各个中断处理函数的参数),这里要说一下,由于寄存器是通用的,也就是刚才所说的通过点灯来调试中断是 有破坏性的,也就是点灯程序一定要在保存完寄存器现场后再运行,显示当前运行位置,不可以先运行点灯再运行保存现场的操作,否则中断返回后恢复现场寄存器 会发生错误。下面就是通过BL跳转到中断处理函数中了。中断返回后将用户堆栈中刚才保存的寄存器数据恢复现场,继续运行原程序。这就是 简单的中断相应过程。

以上对中断部分的整理希望能对大家有所帮助,如有不正确的地方,欢迎讨论。 New

为了学习嵌入式,我是在09年的9月初买的2440开发板。对2440的学习从最初就定为三步走,单片机、bootloader、linux操作系 统,由于当时已经有LM1138(是CONTEX-M3核心)的经验了,所以对单片机的困难程度估计不足,当时想2个月左右的业余时间应该就能够完成的, 没想到拖到这么久。这里原因分析一下挺简单的,首先,我所使用的LM1138是周立功的1138开发板,用的是配套的IAR开发环境,其核心也与ARM正 统系列有所区别,ZLG的相关技术支持做的实在是太好了,在那块开发板上连仿真器都做成一体了,导致我一度认为1138不用仿真器,通过U口就能直接烧录 程序了。由于当时是工作需要使用其作为开发目标板的,所以一切的目标就是完成任务,所以很多东西,能用现成的就用现成的,而周公的例程又是最全的,几乎所 有的硬件器件都有相应的例程,在其基础上修改一下就能够成功运行了,这里不得不说一下工作于学习的区别还真大,工作中,为了追求速度,很多都是用已有的现 成的东西,而学习为了理解深入,却需要由0开始,才能对整体有深层次的把握。周公提供的开发板、开发环境、开发例程已经把涉及到架构、中断响应、初始化过 程的东西都已经写好了,所要做的选择就是填空,诸如在这里写个函数,把函数指针添加到中断响应的列表中之类的。但对中断响应的过程、初始化却一无所知。所 以当时我在制定以2440作为单片机的计划时,将开发板商提供的环境ADS抛弃,转而将2440以IAR作为目标环境进行学习,应该说这是一个痛苦的开 始。这里应该说明的是,其实以哪种环境作为嵌入式开发环境并没有什么区别的,所要做的工作都是一样的,主要的不同是不同的环境针对不同的MCU有不同的资 源,IAR下针对2440的资源就相当的少,对很多常用的MCU IAR都为其提供了相应的例程,通过例程学习该MCU是比较迅速的,但对2440,IAR没有例程,在网上也很少会找到在IAR下调2440的系统介绍, 每种环境又有着自己独特的语法,如IAR 、ADS针对ARM汇编语句的支持就是不一样的,这就导致在初学时使用陌生的环境,学习陌生的知识,难度可想而知,但我认为既然目的是学习,就需要由困难 的地方入手,这样学到的东西才是最多的。虽然时间确实耗费了很多,统计下来,由09年9月初,到10年3月末,中间整整7个月时间,刨去春节、各种事情的 干扰,其它的业余时间都耗费在了这个上面,中间曾一度因为一个问题而耽搁整整3个月时间,一步一绊的走到这里,回想起来依然很令我感慨,总结下来中间经历 的有:IAR环境的熟悉,主要包括:仿真器设置、链接文件icf的地址分配,使用仿真器调试闪灯程序--这就像软件中的Hello World!一样让人兴奋。但在这个时候所有的程序还是跑在RAM中的,只能是个调试程序,断电后就都消失了。但在这个过程中熟悉IAR、仿真器是很重要 的,是一个基础性的工作。下一步正式开始嵌入式ARM的开发,编写异常向量,设置各个中断入口,这里都是使用汇编编写的,对ARM的汇编需要一定的了解, 对ARM异常向量表设置、响应的过程也要有了解,这里需要注意的是,在调试中断时就不能使用仿真器跟踪调试了,需要通过仿真器烧录到ROM中运行了。能够 在RAM中跟踪的是最好的,在不能够跟踪的时候我们就需要调通UART串口输出了,通过打印数据来表明当前的运行状态。最后,我们是需要配置icf文件将 所有的程序跑在片外的SDRAM.flash中的。这里对异常向量表栈空间、程序正常运行栈空间又有深入的理解。使能MMU,对ARM存储器控制有实际操 作的感性认识,最后使能PLL将CPU运行频率设置为400MHZ,实际运行速度,单片机的学习过程就告一段落了。应该说中间走了很多弯路,没有一个人请教真的是一件很痛苦的事,网上的很多东西不可不信又不可全信,很多时候,人家说的都是正确的,但你却用错误的方法去使用,那肯定得不到正确的结果的。

就写到这吧,如果大家有什么问题,欢迎大家讨论。特开QQ:1162752477 欢迎讨论。

因篇幅问题不能全部显示,请点此查看更多更全内容