walnutcy

基于IAR环境开发ATxmega系列之RAM优化

0
阅读(2926)
为一款MCU开发软件,首先要了解的是芯片的结构,是冯.诺尹曼结构,还是哈佛结构。这里我们一起来看下AVR规格书的介绍吧:
基于IAR环境开发ATxmega系列之RAM优化上图为AVR系列MCU的芯片结构图,如图所示,程序总线与数据总线是分开的,即不在同一个线性空间。
规格书中亦有介绍:
The AVR uses a Harvard architecture – with separate memories and buses for program and data.

鉴于上边提到的AVR程序与数据总线是分开的,那在软件编码即需要体现出来,因此需要在编译器中设置允许扩展语法Allow IAR extensions,如下图所示:
基于IAR环境开发ATxmega系列之RAM优化
编译器手册中,与数据存储有关的扩展字如下:
__eeprom Controls the storage of data objects in code memory space
__ext_io Controls the storage of data objects in I/O memory space Supports I/O instructions; used for SFRs
__far Controls the storage of data objects in data memory space
__farflash Controls the storage of data objects in code memory space
__flash Controls the storage of data objects in code memory space
__generic Declares a generic pointer
__huge Controls the storage of data objects in data memory space
__hugeflash Controls the storage of data objects in code memory space
__io Controls the storage of data objects in I/O memory space Supports I/O instructions; used for SFRs
__near Controls the storage of data objects in data memory space
__no_init Supports non-volatile memory
__regvar Places a data object in a register
__root Ensures that a function or data object is included in the object code even if unused
__tiny Controls the storage of data objects in data memory space
__tinyflash Controls the storage of data objects in code memory space

这里的自定字很多,就笔者所用的芯片ATxmega64A1来讲,仅关注__flash即可,详细使用如下:
__flash Controls the storage of data objects in flash (code) memory space.
The __flash memory attribute places objects in flash (code) memory.
Note that it is preferable to declare flash objects as constant. The __flash keyword is
available for all AVR chips.
Because the AVR microcontrollers have only a small amount of on-board RAM, this
memory should not be wasted on data that could be stored in flash memory (of which
there is much more). However, because of the architecture of the processor, a default
pointer cannot access the flash memory. The __flash keyword is used to identify that
the constant should be stored in flash.
A header file called pgmspace.h is installed in the avrinc directory, to provide some
standard C library functions for taking strings stored in flash memory as arguments.
Examples
A program defines a couple of strings that are stored in flash memory:
__flash char str1[] = “Message 1″;
__flash char str2[] = “Message 2″;
The program creates a __flash pointer to point to one of these strings, and assigns it
to str1:
char __flash *msg;
msg=str1;

到这,理论知识已准备充足,再来看看实践吧。

首先看下map文件,
Module CODE DATA
—— —- —-
(Rel) (Rel)
?C_STARTUP 44
?EPILOGUE_B_L09 42
?FILLER_BYTES 4
+ common 496
?FLOATS_L04 812
?L_EC_MUL_L03 64
?PROLOGUE_L09 34
?RESET
+ common 4
?SL_DIVMOD_L03 16
?SS_DIVMOD_L02 48
?SS_SHR_L02 12
?S_EC_MUL_L02 16
?S_SHL_L02 12
?UL_DIVMOD_L03 70
?UL_SHR_L03 16
?US_DIVMOD_L02 40
?__exit 2
?_exit 4
?exit 4
?frexp 196
?low_level_init 4
?segment_init 162
?xV_SWITCH_L06 156
?xdnorm 156
AppPrintf 2 844 96
AppService 2 026 198
CMD_List 3 659 1 592
+ shared 20
QueueList 170
eeprom 1 506 6
eeprom_driver 188
fpga 2 273 128
gpio_driver 336 44
+ common 388
main 1 689 212
nmea_decode 1 694 298
shellMain 736 158
system 1 114
timer_driver 256 2
+ common 68
usart_driver 950 594
+ common 496
N/A (command line) 288
N/A (alignment)
———- —— —–
Total: 21 375 3 616
+ common 496
这里仅以CMD_List一个文件为例进行优化,编译结果显示CMD_List占用1592字节内存。
分析代码发现问题主要集中在一个打印输出的方式上,更改前:

u32 GetVersion(s16 argc, TCHAR* argv[])
{
Shell_OutTXT(curSwitch, “$UNCMT,================================rn”);
Shell_OutTXT(curSwitch, “$UNVER,3.1.0,Build: %s %srn”,__DATE__,__TIME__);
Shell_OutTXT(curSwitch, “$UNAUR,walnutcy,Email: walt_chen@163.comrn”);
Shell_OutTXT(curSwitch, “$UNCMT,================================rn”);

return 0;
}

按IAR的扩展定义要求,作如下更改,
增加一个接口函数UART_Flash_PrintStr,

extern void UART_Printf(u8 sw, const char *fmt, …);
extern void UART_Flash_PrintStr(u8 sw, const char _MEMATTR * fmt);

#define Shell_OutTXT UART_Printf
#define Shell_OutTXT_F UART_Flash_PrintStr

并更改字符串定义如下:

#define _MEMATTR __flash

_MEMATTR const char s_ver_comment[] = “$UNCMT,================================rn”;
_MEMATTR const char s_ver_info1[] = “$UNVER,3.1.0,Build: “ __DATE__ ” “ __TIME__ “rn”;
_MEMATTR const char s_ver_info2[] = “$UNAUR,walnutcy,Email: walt_chen@163.comrn”;

u32 GetVersion(s16 argc, TCHAR *argv[])
{
Shell_OutTXT_F(curSwitch, s_ver_comment);
Shell_OutTXT_F(curSwitch, s_ver_info1);
Shell_OutTXT_F(curSwitch, s_ver_info2);
Shell_OutTXT_F(curSwitch, s_ver_comment);
return 0;
}

可以精简内存几百字节,按同样道理修改CMD_List中其他类似模块,可以优化到以下结果:
CMD_List 3 721 687
+ shared 20

另一种办法是修改编译设置,如下图所示:
基于IAR环境开发ATxmega系列之RAM优化
但按理论而言,需要对等修改函数,类似于笔者增加的函数:
void
UART_Flash_PrintStr(u8 sw, const char _MEMATTR * fmt);
这里不再做测试,因为需要修改原始的函数较多。
如有更好的想法,可以邮件联系walnutcy#gmail.com;QQ:279449586.