IAR相关

IAR-C有着强大的软件仿真功能,但其中的寄存器位操作定义却十分烦琐,并且编译后生成的ASM代码冗余较多,针对该问题,版主自已定义一个位操作定义的方法,初学者可参考定义,并且该种方法可应用于所有寄存器位操作定义。

共实现置位--Set_Bit, 清位--Clr_Bit,取反位Com_Bit,测试位Test_Bit四种位操作功能,并且每条位操作定义仅需一条3字节的ASM指令序列即可,简便直接。

//*****************************************************

//P00位操作定义

#define Set_P00 (P0 = P0 | 0x1)

#define Clr_P00 (P0 = P0 & ~0x1)

#define Com_P00 (P0 = P0 ^ 0x1)

#define Test_P00 (P0 & 0x1)

//P01位操作定义

#define Set_P01 (P0 = P0 | 0x2)

#define Clr_P01 (P0 = P0 & ~0x2)

#define Com_P01 (P0 = P0 ^ 0x2)

#define Test_P01 (P0 & 0x2)

//P02位操作定义

#define Set_P02 (P0 = P0 | 0x4)

#define Clr_P02 (P0 = P0 & ~0x4)

#define Com_P02 (P0 = P0 ^ 0x4)

#define Test_P02 (P0 & 0x4)

//P03位操作定义

#define Set_P03 (P0 = P0 | 0x8)

#define Clr_P03 (P0 = P0 & ~0x8)

#define Com_P03 (P0 = P0 ^ 0x8)

#define Test_P03 (P0 & 0x8)

//P04位操作定义

#define Set_P04 (P0 = P0 | 0x10)

#define Clr_P04 (P0 = P0 & ~0x10)

#define Com_P04 (P0 = P0 ^ 0x10)

#define Test_P04 (P0 & 0x10)

//P05位操作定义

#define Set_P05 (P0 = P0 | 0x20)

#define Clr_P05 (P0 = P0 & ~0x20)

#define Com_P05 (P0 = P0 ^ 0x20)

#define Test_P05 (P0 & 0x20)

//P06位操作定义

#define Set_P06 (P0 = P0 | 0x40)

#define Clr_P06 (P0 = P0 & ~0x40)

#define Com_P06 (P0 = P0 ^ 0x40)

#define Test_P06 (P0 & 0x40)

//P07位操作定义

#define Set_P07 (P0 = P0 | 0x80)

#define Clr_P07 (P0 = P0 & ~0x80)

#define Com_P07 (P0 = P0 ^ 0x80)

#define Test_P07 (P0 & 0x80)

//*************************************

//P1端口操作位定义

//P10位操作定义

#define Set_P10 (P1 = P1 | 0x1)

#define Clr_P10 (P1 = P1 & ~0x1)

#define Com_P10 (P1 = P1 ^ 0x1)

#define Test_P10 (P1 & 0x1)

//P11位操作定义

#define Set_P11 (P1 = P1 | 0x2)

#define Clr_P11 (P1 = P1 & ~0x2)

#define Com_P11 (P1 = P1 ^ 0x2)

#define Test_P11 (P1 & 0x2)

//P12位操作定义

#define Set_P12 (P1 = P1 | 0x4)

#define Clr_P12 (P1 = P1 & ~0x4)

#define Com_P12 (P1 = P1 ^ 0x4)

#define Test_P12 (P1 & 0x4)

//P13位操作定义

#define Set_P13 (P1 = P1 | 0x8)

#define Clr_P13 (P1 = P1 & ~0x8)

#define Com_P13 (P1 = P1 ^ 0x8)

#define Test_P13 (P1 & 0x8)

//P14位操作定义

#define Set_P14 (P1 = P1 | 0x10)

#define Clr_P14 (P1 = P1 & ~0x10)

#define Com_P14 (P1 = P1 ^ 0x10)

#define Test_P14 (P1 & 0x10)

//P15位操作定义

#define Set_P15 (P1 = P1 | 0x20)

#define Clr_P15 (P1 = P1 & ~0x20)

#define Com_P15 (P1 = P1 ^ 0x20)

#define Test_P15 (P1 & 0x20)

//P16位操作定义

#define Set_P16 (P1 = P1 | 0x40)

#define Clr_P16 (P1 = P1 & ~0x40)

#define Com_P16 (P1 = P1 ^ 0x40)

#define Test_P16 (P1 & 0x40)

//P17位操作定义

#define Set_P17 (P1 = P1 | 0x80)

#define Clr_P17 (P1 = P1 & ~0x80)

#define Com_P17 (P1 = P1 ^ 0x80)

#define Test_P17 (P1 & 0x80)

//*************************************

//P2端口操作位定义

//P20位操作定义

#define Set_P20 (P2 = P2 | 0x1)

#define Clr_P20 (P2 = P2 & ~0x1)

#define Com_P20 (P2 = P2 ^ 0x1)

#define Test_P20 (P2 & 0x1)

//P21位操作定义

#define Set_P21 (P2 = P2 | 0x2)

#define Clr_P21 (P2 = P2 & ~0x2)

#define Com_P21 (P2 = P2 ^ 0x2)

#define Test_P21 (P2 & 0x2)

//P22位操作定义

#define Set_P22 (P2 = P2 | 0x4)

#define Clr_P22 (P2 = P2 & ~0x4)

#define Com_P22 (P2 = P2 ^ 0x4)

#define Test_P22 (P2 & 0x4)

//P23位操作定义

#define Set_P23 (P2 = P2 | 0x8)

#define Clr_P23 (P2 = P2 & ~0x8)

#define Com_P23 (P2 = P2 ^ 0x8)

#define Test_P23 (P2 & 0x8)

//P24位操作定义

#define Set_P24 (P2 = P2 | 0x10)

#define Clr_P24 (P2 = P2 & ~0x10)

#define Com_P24 (P2 = P2 ^ 0x10)

#define Test_P24 (P2 & 0x10)

//P25位操作定义

#define Set_P25 (P2 = P2 | 0x20)

#define Clr_P25 (P2 = P2 & ~0x20)

#define Com_P25 (P2 = P2 ^ 0x20)

#define Test_P25 (P2 & 0x20)

//P26位操作定义

#define Set_P26 (P2 = P2 | 0x40)

#define Clr_P26 (P2 = P2 & ~0x40)

#define Com_P26 (P2 = P2 ^ 0x40)

#define Test_P26 (P2 & 0x40)

//P27位操作定义

#define Set_P27 (P2 = P2 | 0x80)

#define Clr_P27 (P2 = P2 & ~0x80)

#define Com_P27 (P2 = P2 ^ 0x80)

#define Test_P27 (P2 & 0x80)

//*************************************

//P3端口操作位定义

//P30位操作定义

#define Set_P30 (P3 = P3 | 0x1)

#define Clr_P30 (P3 = P3 & ~0x1)

#define Com_P30 (P3 = P3 ^ 0x1)

#define Test_P30 (P3 & 0x1)

//P31位操作定义

#define Set_P31 (P3 = P3 | 0x2)

#define Clr_P31 (P3 = P3 & ~0x2)

#define Com_P31 (P3 = P3 ^ 0x2)

#define Test_P31 (P3 & 0x2)

//P32位操作定义

#define Set_P32 (P3 = P3 | 0x4)

#define Clr_P32 (P3 = P3 & ~0x4)

#define Com_P32 (P3 = P3 ^ 0x4)

#define Test_P32 (P3 & 0x4)

//P33位操作定义

#define Set_P33 (P3 = P3 | 0x8)

#define Clr_P33 (P3 = P3 & ~0x8)

#define Com_P33 (P3 = P3 ^ 0x8)

#define Test_P33 (P3 & 0x8)

//P34位操作定义

#define Set_P34 (P3 = P3 | 0x10)

#define Clr_P34 (P3 = P3 & ~0x10)

#define Com_P34 (P3 = P3 ^ 0x10)

#define Test_P34 (P3 & 0x10)

//P35位操作定义

#define Set_P35 (P3 = P3 | 0x20)

#define Clr_P35 (P3 = P3 & ~0x20)

#define Com_P35 (P3 = P3 ^ 0x20)

#define Test_P35 (P3 & 0x20)

//P36位操作定义

#define Set_P36 (P3 = P3 | 0x40)

#define Clr_P36 (P3 = P3 & ~0x40)

#define Com_P36 (P3 = P3 ^ 0x40)

#define Test_P36 (P3 & 0x40)

//P37位操作定义

#define Set_P37 (P3 = P3 | 0x80)

#define Clr_P37 (P3 = P3 & ~0x80)

#define Com_P37 (P3 = P3 ^ 0x80)

#define Test_P37 (P3 & 0x80)

//*************************************

//P4端口操作位定义

//P40位操作定义

#define Set_P40 (P4 = P4 | 0x1)

#define Clr_P40 (P4 = P4 & ~0x1)

#define Com_P40 (P4 = P4 ^ 0x1)

#define Test_P40 (P4 & 0x1)

//P41位操作定义

#define Set_P41 (P4 = P4 | 0x2)

#define Clr_P41 (P4 = P4 & ~0x2)

#define Com_P41 (P4 = P4 ^ 0x2)

#define Test_P41 (P4 & 0x2)

//P42位操作定义

#define Set_P42 (P4 = P4 | 0x4)

#define Clr_P42 (P4 = P4 & ~0x4)

#define Com_P42 (P4 = P4 ^ 0x4)

#define Test_P42 (P4 & 0x4)

//P43位操作定义

#define Set_P43 (P4 = P4 | 0x8)

#define Clr_P43 (P4 = P4 & ~0x8)

#define Com_P43 (P4 = P4 ^ 0x8)

#define Test_P43 (P4 & 0x8)

//P44位操作定义

#define Set_P44 (P4 = P4 | 0x10)

#define Clr_P44 (P4 = P4 & ~0x10)

#define Com_P44 (P4 = P4 ^ 0x10)

#define Test_P44 (P4 & 0x10)

//P45位操作定义

#define Set_P45 (P4 = P4 | 0x20)

#define Clr_P45 (P4 = P4 & ~0x20)

#define Com_P45 (P4 = P4 ^ 0x20)

#define Test_P45 (P4 & 0x20)

//P46位操作定义

#define Set_P46 (P4 = P4 | 0x40)

#define Clr_P46 (P4 = P4 & ~0x40)

#define Com_P46 (P4 = P4 ^ 0x40)

#define Test_P46 (P4 & 0x40)

//P47位操作定义

#define Set_P47 (P4 = P4 | 0x80)

#define Clr_P47 (P4 = P4 & ~0x80)

#define Com_P47 (P4 = P4 ^ 0x80)

#define Test_P47 (P4 & 0x80)

//*****************************************************

围观 340

(一)程序固化后运行方式:

程序开始运行后需要将RW 和ZI段搬移到RAM中去,程序下载进Flash中以后,上电后是怎样将RW ZI断搬移到RAM中去的?注意IAR和ADS在进行完.s文件的初始化以后都不是直接跳转到main函数去执行,IAR是跳转到?main中而ADS是跳转到__main函数中,在这些函数中根据icf文件的配置,将RW和ZI段搬移到icf文件规定的RAM区域中。

如果程序的运行时域是在片外RAM中,那程序是在什么时候对片外RAM控制器进行初始化呢?

因为.s文件的开始部分是CODE ROM的,不需要RAM空间,所以可以在.s文件中对片外RAM进行配置。

还有一个问题,这个问题是在硬件设计时必须注意的,如果需要程序固化在外部Flash必须注意外接的Flash必须是片子上电后默认片外总线就支持的片子。

(二)程序在RAM中调试的运行方式

为了调试的方便,程序有时候是不需要下载进flash进行调试,而是直接在RAM中运行,将icf文件中的ROM 和RAM地址都设成硬件RAM的地址,将Flashloader的使能关掉,那么程序就运行在RAM中了。

但是问题又产生了,因为有时我们想在外部RAM中调试代码,所以片外RAM控制器需要在代码下载进RAM之前进行初始化,怎么能够实现呢?

IAR是通过.mac文件实现的。

在程序下载之前先执行了。mac文件中的程序,下面是一个例子

execUserFlashInit()
{
__writeMemory32(0x1000ffef, 0xffe00000 , "Memory");
__writeMemory32(0x0f000114, 0xE002C014, "Memory");
}

该例子是lpc初始化外部RAM的例子。配置好了外部RAM就可以在里面跑代码了。

(三)程序的IAR下载

1、文件在片内Flash中下载运行

这是最简单也是最常用的方式,一般的ARM芯片都会带有片内Flash,IAR会通过Flashloader将二进制的可执行文件下载到Flash中。

下载的方式如下:如果要将程序B下载到片子里,IAR先将一个程序A(IAR事先编好的程序)下载到片内
的RAM中,然后利用这个程序A通过JTAG和Flashloader交互完成程序B的下载。

2、文件在片外Flash中下载

IAR下载进RAM中的程序A必须支持片外的Flash,他能够完成片外Flash的擦除。往往这个程序需要自己写。

像HJTAG的下载机制也是这样,HJTAG中列举了很多HJTAG支持的芯片,所谓支持就是HJTAG很有这些芯片
的A程序。在HJTAG中必须要指定程序A将要下载到的RAM的地址,而且这个地址的RAM必须是可用的,

比如,如果用的片外SDRAM的话就必须初始化SDRAM控制器。这在HJTAG的Init Script中完成、在IAR的mac文件中完成。

3、文件在片内RAM中下载 、文件在片外RAM中下载

由于这两种方式不需要Flashloader的参与,这时程序的加载时域和运行时域是相同的,程序运行后不涉及程序的搬移,所以只要给IAR指定运行时域的RAM地址就行了,如果是内部RAM,那非常省事,直接在icf文件中将地址都设置成内部RAM就行,如果是外部RAM那么在mac文件中初始化外部SDRAM控制器,或者其他的RAM,然后IAR就可以完成将程序放在已经初始化好的外部RAM里,并运行。

围观 978

GCC和IAR分配堆栈的方式不同,IAR先分配堆栈空间,相当于定义一个全局数组为堆栈空间,堆栈初始为堆栈空间最高地址;GCC不用先分配堆栈,自动把RAM剩余空间作为堆栈空间,堆栈初始为RAM最高地址。
 
初学者很容易忽视这个问题,造成程序跑飞而找不到问题的症结,我在用IAR For MSP430的时候没遇到过这个问题,因为MSP430的RAM比较大,IAR默认是80字节,足够一般程序使用。 

但是使用IAR For SAM8的时候,有一个比较耗费堆栈的程序运行一段时间后出问题,由于要记录一个24小时的数组,而数组元素的值是在堆栈里改变的,所以,记录到一定时间以后,出现了堆栈不足的情况,初学者如果没有仿真器,是很难发现这个问题的,还好我用的仿真器在Debug的时候出现了堆栈不足的警告,我才意识到是这里问题。 

IAR For SAM8默认堆栈是32字节,既然不够用,那么就要增大,但是设置到多少合适呢? 首先编译你的程序,看程序用了多少自己的RAM,

在看看芯片的Datasheet,看看芯片总共有多大的RAM,

好了现在你就知道剩余多少RAM了:208-142=66(Byte) 
前面说过IAR的CSTACK,NEAR_HEAP和RSTACK是预先分配好的,占用存储空间是固定不变的,相当于定义了一个全局数组,GCC堆栈策略与IAR不同,堆栈大小不是预先分配好的,而是把SRAM里面剩余空间作为堆栈空间。 如果是GCC,那么编译器就会自动设置剩余的RAM为数据堆栈(和数据返回堆栈RSTACK,NEAR_HEAP等)。 

在IAR里,STACK应该设置到多少呢? 

在工程-》Options-》Linker-》List(不同的IAR版本会稍有不同),选择生成LIST文件,并包含stack选项

在./Debug/list目录下,得到.map(可能是.lst等其他格式)文件,用记事本打开,找到以下内容:   

**************************************** * * 
* CALL GRAPH * * * 
****************************************  
->Sub-tree of type: Interrupt function tree that does not make : indirect calls CSTACK 
| Stack used (prev) : 00000000 01 int_T0_OV 
| Stack used (prev) : 00000000 | + function block : 0000000C  
......(省略N行)  
01 main 
| Stack used (prev) : 0000003A | + function block : 00000000 <-Sub-tree of type: Function tree | Stack used : 0000003A  

找到最大的Stack used,我的就是0000003A,58个字节,这就是用到的最大的堆栈空间,保守一点,我设置成64字节,没有超过剩余RAM,再重新编译,运行,仿真器没有堆栈不足警告,程序也能正常运行了。

围观 412

方法1:

启动文件中:(默认启动文件也是这样)

org 0x18
ldr pc,[pc,#-0xFF0] ; 直接跳转到用户中断处理函数

直接写用户中断函数
__irq __arm void Tmr0_IntOnMR0_isr(void)
{
............
}

__irq __arm void Tmr1_IntOnMR0_isr(void)
{
............
}

方法2:

启动文件中:(默认启动文件也是这样)

org 0x18
ldr pc,=irq_handler ;跳转到公共中断处理函数,再分支到具体功能的中断处理函数中

__irq __arm void irq_handler (void)//公共中断处理函数,检查VICVectAddr是否为空
{
void (*interrupt_function)();
unsigned int vector;

vector = VICVectAddr; // Get interrupt vector.
interrupt_function = (void(*)())vector;
if(interrupt_function != NULL)
{
interrupt_function(); // Call vectored interrupt function.
}
else
{
VICVectAddr = 0; // Clear interrupt in VIC.
}
}

具体功能的中断处理函数
void Tmr0_IntOnMR0_isr(void)
{
............
}

void Tmr1_IntOnMR0_isr(void)
{
............
}

方法3:

使用#pragma vector不管启动文件如何写法,

#define IRQV 0x18
#pragma vector=IRQV
__irq __arm void irq_handler (void)
{
void (*interrupt_function)();
unsigned int vector;

vector = VICVectAddr; // Get interrupt vector.
interrupt_function = (void(*)())vector;
if(interrupt_function != NULL)
{
interrupt_function(); // Call vectored interrupt function.
}
else
{
VICVectAddr = 0; // Clear interrupt in VIC.
}
}

具体功能的中断处理函数
void Tmr0_IntOnMR0_isr(void)
{
............
}

void Tmr1_IntOnMR0_isr(void)
{
............
}

//================================================================================================
ldr pc, [pc,#-0xFF0]是直接copy的,是不好看。
应该去掉注释,写成 ldr pc,[pc,#-0xFF0]。

org 0x18
ldr pc, [pc,#-0xFF0] ; 直接跳转到用户中断处理函数
此时PC = 0x18+8 = 0x20
0x20 - 0xff0 = 0xFFFFF030
0xFFFFF030 正是 VICVectAddr
//================================================================================================
LPC23XX,LPC24XX的VICVectAddr地址是0xFFFFFF00 ,也没关系,用
org 0x18
LDR PC, [PC, #-0x0120] ; Vector from VicVectAddr
道理是一样的:
(0x18+0x08)-0x0120 = 0x20 - 0x0120 = 0xFFFFFF00

围观 362

第一部分产品介绍

AVR® IAR Embedded Workbench® IDE用户手册的这部分包括以下章节:

产品介绍

已安装文件

1.1产品介绍

嵌入式IAR Embedded Workbench®是一个非常有效的集成开发环境(IDE),它使用户充 分有效地开发并管理嵌入式应用工程。作为一个开发平台,它具备任何在用户每天的工作地方所想要的特性。

本章介绍了嵌入式IAR Embedded Workbench IDE,旨在使用户获得对本产品的所有集成工具的总体了解。

1.1.1嵌入式IAR Embedded Workbench IDE

嵌入式IAR Embedded Workbench IDE提供一个框架,任何可用的工具都可以完整地嵌入其中,这些工具包括:

高度优化的IAR AVR C/C++编译器;

AVR IAR汇编器;

通用IAR XLINK Linker;

IAR XAR库创建器和 IAR XLIB Librarian;

一个强大的编辑器;

一个工程管理器;

IAR C-SPY TM 调试器,一个具有世界先进水平的高级语言调试器。

嵌入式IAR Embedded Workbench适用于大量8位、16位以及32位的微处理器和微控制器,使用户在开发新的项目时也能在所熟悉的开发环境中进行。它为用户提供一个易学和具有最大量代码继承能力的开发环境,以及对大多数和特殊目标的支持。嵌入式IAR Embedded Workbench有效提高用户的工作效率,通过IAR工具,用户可以大大节省工作时间。 我们称这个理念为:“不同架构,同一解决方案”。

点击下载

围观 230

► IAR EW430总体介绍

瑞典IAR System公司推出的IAR EW软件是一种非常有效的嵌入式系统开发工具,它使用户能够充分有效地开发并管理嵌入式应用项目,其界面类似于MS Visual C++,可以在Windows平台上运行,功能十分完善。包含有源程序文件编辑器,项目管理器,源程序调试器等,并且为C/C++编译器,汇编器,连接定位器等提供了单一而灵活的开发环境。源级浏览器功能可以快速浏览源文件;还提供了对第三方工具软件的接口,允许启动用户指定的应用程序。

IAR EW适用于开发基于8位,16位以及32位的处理器的嵌入式系统,其具有同一界面,用户可以针对多种不同的目标处理器,在相同的集成开发环境中进行基于不同CPU嵌入式系统应用程序的开发。另外IAR的链接定位器(XLINK)可以输出多种格式的目标文件,使用户可以采用第三方软件进行仿真调试。

针对TI MSP430,IAR也有相应的IAR EW430软件。其具有上面所说的所有IAR软件共有功能,另外还有所有MSP430也包括MSP430X设备的配置文档,C-SPY调试器支持FET (TI's Flash Emulation Tool )驱动,并支持实时操作系统相关信息的调试,还提供MSP430的项目例子以及相关的代码模板等。

► 现给以演示来具体说明其特性和使用:

♦ 1、在安装好的文件夹下面开打IAR_KickStartCard应用工程,右击鼠标选择OPTIONS会弹出如图1所示,在CATEGORY中选择GENERAL OPTION在右边点击Target,从下面的Device右边的浏览器中可以看见IAR EW430所支持的所有常见的具体设备,在选择好具体的设备后IAR软件会自动的在后台调用相应的I/O头文件,以及设备描述文件(C-SPY为了能对不同的器件的中断系统进行正确仿真,必须了解当前使用器件关于中断的详细信息,这类信息由设备描述文件.ddf文件提供)。


图1

♦ 2、编译器:在CATEGORY中点击C/C++ COMPILER,IAR的编译器提供了DLIB库,支持符合ANSI C标准的C/C++编程语言以及多字节参数和MISRA标准等。从图2中可见其的选择。(MISRA (The Motor Industry Software Reliability Association 汽车工业软件可靠性联会)所谓的MISRA C Coding Standard,这一标准中包括了127条C语言编码标准,通常认为,如果能够完全遵守这些标准,则你的C代码是易读、可靠、可移植和易于维护的)


图2

Language选项区域用于设置希望采用的编程语言,如果您选择Automatic单选按钮,则根据源程序文件的扩展名自动选择。如扩展名为 .C时作为C源程序进行编译。Enable multibyte support允许在C/C++源程序文件中使用多字节符号。图3中可以看见MISRA C选项卡,单击ALL后选择所有MISRA C规则校验模块当然也可以增加删除MISAR C规则校验模块,其作用就是按照MISRA C标准来检查校验您的代码。


图3

IAR的编译器支持对代码大小和运行速度的多层次优化,在Optimizations选择区域可选择优化方法有SIZE和SPEED两种,前者以代码大小进行优化,后者以运行速度进行优化。另外还有NONE不优化对调试支持最好,LOW低级优化,MEDIUM中级优化和HIGH高级优化4种不同的优化级别。根据您所选择的优化方法和优化级别,Enabled transformations框将自动选择不同的优化项目。另外,针对一个项目中不同的源文件也可以选择不同的具体优化代码方式。具体见图4

IAR提供了特殊性质的扩展关键字,可以直接在源程序中使用这些关键字,而不用用汇编语言写任何的函数而达到操作硬件设备命令。如monitor用于定义监视函数,其在执行期间禁止中断,从而允许完成操作等。除以上功能外IAR编译器还支持内嵌汇编语言,符合IEEE标准的32位和64位浮点运算等。

♦ 3、调试器:C-SPY调试器完全集成在IAR EW软件中,通过不同驱动DRIVER实现与目标系统通信和仿真控制。MSP430软件的C-SPY调试器提供了2种类型的驱动:纯软件仿真驱动和硬件仿真器驱动。纯软件仿真驱动可以实现在没有实际硬件的条件下,采用软件模拟方式进行用户程序的仿真也就是C-SPY提供的Simulator方式;硬件仿真器驱动为C-SPY调试器和专用硬件仿真器(例如J-LINK)提供接口,实现对目标系统的实时在线仿真调试。在调试过程中可以编辑代码不用退出调试环境,并且可以在调试之前在代码中直接设置断点。选择Project—Debug后进入调试状态见下图5,可以选择您感兴趣的窗口。例如打开Register窗口,还可以选择不同的寄存器见下图6


图5


图6

还可以看不同的存储器,通过AUTO看当前语句相关变量和表达式的值,LOCAL查看当前运行函数的局部变量和函数参数值。如图7 C-SPY还提供了函数刨析功能和代码覆盖功能,用于对应用程序进行分析以确定其运行的瓶颈问题(注意FET仿真驱动没有代码覆盖功能),函数刨析功能可以找出程序运行过程中对一个给定激发信号耗时最长的函数,从而使用户能够集中精力研究如何更好地对这些函数进行优化。例如在编译时选择速度优化模式,或者将函数移到能更高效寻址的存储器中运行等。在VIEW中选择PROFILING开打刨析记录。启动程序全速运行,当运行到一个断点或程序结束时,窗口中将显示对当年程序所有函数运行的刨析记录结果,如图8:


图7


图8

当一个函数由不含自身源代码的函数调用时,例如库函数,则没有耗时测试。当要查看与该函数有关的调用和被调用详细信息时,可以看刨析细节窗口。

代码覆盖分析用于帮助用户确认是否所有程序代码都得到执行,这对于鉴别程序代码中是否有不能被执行的部分特别有用。打开VIEW-CODE COVERAGE窗口,如图9显示的是当前代码覆盖分析状态报告,即哪部分代码在分析开始后至少执行了一次。IAR C/C++编译器在应用程序每条语句以及每个函数调用处以STEP POINT步点形式生成详细的步进信息,以百分比统计了所有已经执行的布点数量,并列出了所有还没有执行的布点等。


图9

在程序调试时往往希望能对函数的调用过程进行跟踪,C-SPY可以在调试过程中随时显示整个调用链,跟踪显示当前调用函数内容,以方便调试和修改源代码中的错误。在VIEW-CALL STACK打开调用堆栈窗口其中显示的是程序调用过程中函数调用的列表。并将当前函数置顶。见图10

C-SPY共有4种单步运行命令:Step Over,step Into,Step out和 Next Statement等。Step Into是单步运行无论是否在同一个函数内,对于Step Over是在同一函数中将运行到下一布点。Step out命令立即执行完整个函数调用并返回到调用话句的下一条语句。

另外IAR软件的输出格式也支持其他的调试器如下图您可以选择您用的调试器可读格式供30多种工业标准格式供选择如UBROF,ELE/DWARF,COFF,Inter-extended,Motorola等见下图:


图11
围观 1042

首先要说明,没有哪款开发工具是万能的,也没有哪款工具在所有方面都具有绝对优势。对于Keil MDK-ARM和IAR两款工具择,可以根据自己的习惯来选择,而不应该在使用其中的一款时贬低另外一款,或者总是赞美自己的选择。

好了,下面开始讲Keil MDK-ARM和IAR的区别。

一、概述

Keil MDK-ARM(旧称RealView MDK)开发工具源自德国Keil公司,被全球上百万的嵌入式开发工程师验证和使用,是ARM公司目前最新推出的针对各种嵌入式处理器的软件开发工具。

KEIL MDK集成了业内最领先的技术,包括uVision3、uVision4、uVision5集成开发环境与 ARM编译器。支持ARM7、ARM9、Cortex-M0、Cortex-M0+、Cortex-M3、Cortex-M4、Cortex-R4内核核处理器。

Keil MDK可以自动配置启动代码,集成Flash烧写模块,强大的Simulation设备模拟,性能分析等功能,与ARM之前的工具包ADS等相比,ARM编译器的最新版本可将性能改善超过20%以上。
  
IAR Embedded Workbench是一套用于编译和调试嵌入式系统应用程序的开发工具,支持汇编、C和C++语言。它提供完整的集成开发环境,包括工程管理器、编辑器、编译链接工具和C-SPY调试器。IAR Systems以其高度优化的编译器而闻名。每个C/C++编译器不仅包含一般全局性的优化,也包含针对特定芯片的低级优化,以充分利用您所选芯片的所有特性,确保较小的代码尺寸。IAR Embedded Workbench能够支持由不同的芯片制造商生产,且种类繁多的8位、16位或32位芯片。

二、区别

1、MDK不支持层叠文件夹,在文件夹的下一级中必须为文件;IAR支持层叠,可以比较方便管理代码,理清层次。


2、MDK连接library,直接添加到文件夹即可;IAR则需要从工程中选项中设置。这应该不算什么问题,毕竟大多数IDE都是这么做的,但最让人很郁闷的是,IAR不能采用相对路径。比如../MUF/MUF.LIB在编译时,就会连接到别的目录,只能采用d:/MUF/MUF.lib绝对路径的形式。


3、 MDK支持dynamic_cast<>运算符,而IAR文档中明确表示不支持。如果在IAR中强行使用该运算符,则编译会报错:

Error[Pe020]: identifier "dynamic_cast" is undefined

4、MDK默认只创建工程,工作区是不会直接创建。如果想多个工程聚合,则首先需要创建一个multi的工作区,然后再添加相应的工程。 IAR,默认是创建工程和工作区,如果想多个工程并存,直接添加即可。 相比之下,MDK创建工程的文件比较少,而IARM创建工程生成的文件比较多。

5、MDK编译时,只有level的选择;IAM有debug和Release的快速选择

6、默认状态,MDK的工具栏功能比较多,有点繁杂;IAM的比较简洁,但相对,也比较单薄。

7、MDK的C++有std::这个命名空间;IAR下面的所有容器和算法,都不采用std命名空间

8、MDK的程序文件,最后必须要有一个新的空行,否则会有编译警告:

warning: #1-D: last line of file ends without a newline

一般来说,如果主要是采用C,并且也不会有太多的library需要连接,MDK和IAR都能胜任。不过这种情形就比较推荐IAR,因为其非常简洁,上手也快,代码层次也能清晰明了。
  
如果主要是采用C++,并且用到很多特性,或是需要有多个工程进行协作,那么注定只能选择MDK,只不过这样就一定要每个文件最后加上新的空行了。

文章来源:米尔科技

围观 380

页面

订阅 RSS - IAR相关