|
发表于 2012-12-15 20:54:25
|
显示全部楼层
smset 发表于 2012-12-15 17:27
非常不错!你又提供了一个亮点哈:任务函数带返回值, 我重新评估了任务函数带返回值的方案,首先会省掉1个 ...
采用任务函数返回值的方法,很不错啊。我在Mega8上测试,节省rom而且运行会变快。编译器winavr20100110
Size before:
text data bss dec hex filename
326 0 7 333 14d main.elf
avr-gcc -c -mmcu=atmega8 -I. -g -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-ahlms=main.lst main.c -o main.o
avr-gcc -mmcu=atmega8 -Wl,-Map=main.map,--cref main.o -lm --output main.elf
avr-objcopy -O ihex -R .eeprom main.elf main.hex
avr-objdump -h -S main.elf > main.lss
Size after:
text data bss dec hex filename
338 0 8 346 15a main.elf
新代码节省了一个byte的ram,rom减少了12byte。
以下是原来的程序编译的汇编代码,这里仅仅列出task0和runtask两个部分代码的区别
runtask原始代码的汇编:
RunTask(task0,0);
11e: 1f ef ldi r17, 0xFF ; 255
120: 80 91 62 00 lds r24, 0x0062
124: 88 23 and r24, r24
126: 39 f4 brne .+14 ; 0x136 <main+0x34>
128: 10 93 67 00 sts 0x0067, r17
12c: b7 df rcall .-146 ; 0x9c <task0>
12e: 80 91 67 00 lds r24, 0x0067
132: 80 93 62 00 sts 0x0062, r24
新代码的汇编:
RunTask(task0,0);
11a: 1f ef ldi r17, 0xFF ; 255
11c: 80 91 62 00 lds r24, 0x0062
120: 88 23 and r24, r24
122: 29 f4 brne .+10 ; 0x12e <main+0x30>
124: 10 93 62 00 sts 0x0062, r17
128: b9 df rcall .-142 ; 0x9c <task0>
12a: 80 93 62 00 sts 0x0062, r24
可以看出原来的代码由于传递数据需要currdt变量,因此在rcall前进行了255的赋值,之后又取出再赋值给tmers。
而新的代码由于没有了变量,因此在rcall钱直接给timers赋值255,之后通过rcall的返回值直接赋值。节省了取出currdt的这个时间。
task0里的WaitX的原始代码的汇编:
WaitX(20);
ba: 84 e6 ldi r24, 0x64 ; 100
bc: 80 93 61 00 sts 0x0061, r24
c0: 84 e1 ldi r24, 0x14 ; 20
c2: 80 93 67 00 sts 0x0067, r24
c6: 08 95 ret
新代码的汇编
WaitX(20);
ba: 84 e6 ldi r24, 0x64 ; 100
bc: 80 93 61 00 sts 0x0061, r24
c0: 84 e1 ldi r24, 0x14 ; 20
c2: 08 95 ret
上面的汇编,首先是对lc进行赋值,给0x0061寄存器,而等待20这个部分原始代码需要把这个数据传给currdt寄存器,再返回。
而新的代码由于没有了变量,因此直接给内部r24寄存器,然后返回。
因此采用任务函数带返回值的方式不仅节省了rom空间,节省了一个ram,而且程序运行也更快。
/****小小调度器开始**********************************************/
#define MAXTASKS 5
unsigned char timers[MAXTASKS];
#define _SS static unsigned char lc; switch(lc){case 0:
#define _EE ;}; lc=0; return 0;
#define WaitX(tickets) do {lc=__LINE__; return tickets ;} while(0); case __LINE__:
#define RunTask(TaskName,TaskID) do { if (timers[TaskID]==0){ timers[TaskID]=255; timers[TaskID]=TaskName(); }} while(0);
#define UpdateTimers() unsigned char i; for(i=0;i<MAXTASKS;i++){if((timers!=0)&&(timers!=255)) timers--;}
/*****小小调度器结束*******************************************************/
|
|