http://blog.sina.com.cn/s/blog_7420cd1701019c6x.html
为一款MCU开发软件,首先要了解的是芯片的结构,是冯.诺尹曼结构,还是哈佛结构。这里我们一起来看下AVR规格书的介绍吧:
上图为AVR系列MCU的芯片结构图,如图所示,程序总线与数据总线是分开的,即不在同一个线性空间。
规格书中亦有介绍:
The AVR uses a Harvard architecture - with separate memories andbuses for program and data.
鉴于上边提到的AVR程序与数据总线是分开的,那在软件编码即需要体现出来,因此需要在编译器中设置允许扩展语法Allow IARextensions,如下图所示:
编译器手册中,与数据存储有关的扩展字如下:
__eeprom Controls the storage of data objects in code memoryspace
__ext_io Controls the storage of data objects in I/O memory spaceSupports I/O instructions; used for SFRs
__far Controls the storage of data objects in data memoryspace
__farflash Controls the storage of data objects in code memoryspace
__flash Controls the storage of data objects in code memoryspace
__generic Declares a generic pointer
__huge Controls the storage of data objects in data memoryspace
__hugeflash Controls the storage of data objects in code memoryspace
__io Controls the storage of data objects in I/O memory spaceSupports I/O instructions; used for SFRs
__near Controls the storage of data objects in data memoryspace
__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 theobject code even if unused
__tiny Controls the storage of data objects in data memoryspace
__tinyflash Controls the storage of data objects in code memoryspace
这里的自定字很多,就笔者所用的芯片ATxmega64A1来讲,仅关注__flash即可,详细使用如下:
__flash Controls the storage of data objects in flash (code) memoryspace.
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 ofon-board RAM, this
memory should not be wasted on data that could be stored in flashmemory (of which
there is much more). However, because of the architecture of theprocessor, a default
pointer cannot access the flash memory. The __flash keyword is usedto identify that
the constant should be stored in flash.
A header file called pgmspace.h is installed in the avr\incdirectory, to provide some
standard C library functions for taking strings stored in flashmemory as arguments.
Examples
A program defines a couple of strings that are stored in flashmemory:
__flash char str1[] = "Message 1";
__flash char str2[] = "Message 2";
The program creates a __flash pointer to point to one of thesestrings, 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 2844 96
AppService 2 026 198
CMD_List 3 659 1 592
+shared 20
QueueList 170
eeprom 1506 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 (commandline) 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,================================\r\n");
Shell_OutTXT(curSwitch, "$UNVER,3.1.0,Build: %s%s\r\n",__DATE__,__TIME__);
Shell_OutTXT(curSwitch, "$UNAUR,walnutcy,Email:walt_chen@163.com\r\n");
Shell_OutTXT(curSwitch, "$UNCMT,================================\r\n");
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_OutTXTUART_Printf
#define Shell_OutTXT_FUART_Flash_PrintStr
并更改字符串定义如下:#define _MEMATTR__flash
_MEMATTR const char s_ver_comment[] ="$UNCMT,================================\r\n";
_MEMATTR const char s_ver_info1[] ="$UNVER,3.1.0,Build: "__DATE__ " " __TIME__"\r\n";
_MEMATTR constchar s_ver_info2[] ="$UNAUR,walnutcy,Email:walt_chen@163.com\r\n";
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
另一种办法是修改编译设置,如下图所示:
但按理论而言,需要对等修改函数,类似于笔者增加的函数:
void UART_Flash_PrintStr(u8 sw, const char _MEMATTR * fmt);
这里不再做测试,因为需要修改原始的函数较多。
如有更好的想法,可以邮件联系walnutcy#gmail.com; |