我正在尝试为ATTiny13编写程序。我的问题是它具有巨大的尺寸约束。好了,制作我的第一个Hello World程序时,只花了100个字节的程序空间就可以打开和关闭灯!我可以给avr-gcc提供任何选择来缩小此大小吗?另外,crt0中包含什么?我不太喜欢AVR组装,所以我不太了解。
我不想为这个项目而去组装。
我正在尝试为ATTiny13编写程序。我的问题是它具有巨大的尺寸约束。好了,制作我的第一个Hello World程序时,只花了100个字节的程序空间就可以打开和关闭灯!我可以给avr-gcc提供任何选择来缩小此大小吗?另外,crt0中包含什么?我不太喜欢AVR组装,所以我不太了解。
我不想为这个项目而去组装。
Answers:
crt0是uC的启动例程。例程执行寄存器的设置以及数据的初始化。
100个字节是否包括中断向量表?我不确定ATtiny13,但是ATtiny25 / 45/85有15个中断向量。这将占用30个字节。
gcc可以选择链接您的crt0。您可以获取AVR crt0.S文件并进行修改。时间不是很长,所以应该不难做。
/avr-libc-1.6.7/avr/lib/avr2/attiny13/crttn13.S
您可以使用avr-objdump -d .elf查看正在生成的内容:
让我们来分析一下:
[jpc@jpc ~] avr-objdump -d avr.elf | sed -e 's/^/ /' | pbcopy
avr.elf: file format elf32-avr
Disassembly of section .text:
00000000 <__vectors>:
0: 09 c0 rjmp .+18 ; 0x14 <__ctors_end>
2: 0e c0 rjmp .+28 ; 0x20 <__bad_interrupt>
4: 0d c0 rjmp .+26 ; 0x20 <__bad_interrupt>
6: 0c c0 rjmp .+24 ; 0x20 <__bad_interrupt>
8: 0b c0 rjmp .+22 ; 0x20 <__bad_interrupt>
a: 0a c0 rjmp .+20 ; 0x20 <__bad_interrupt>
c: 09 c0 rjmp .+18 ; 0x20 <__bad_interrupt>
e: 08 c0 rjmp .+16 ; 0x20 <__bad_interrupt>
10: 07 c0 rjmp .+14 ; 0x20 <__bad_interrupt>
12: 06 c0 rjmp .+12 ; 0x20 <__bad_interrupt>
20个字节的中断向量表(如果您坚持并承诺永远不会启用相应的中断,则至少可以省略某些条目)。
00000014 <__ctors_end>:
14: 11 24 eor r1, r1
16: 1f be out 0x3f, r1 ; 63
18: cf e9 ldi r28, 0x9F ; 159
1a: cd bf out 0x3d, r28 ; 61
1c: 02 d0 rcall .+4 ; 0x22 <main>
1e: 05 c0 rjmp .+10 ; 0x2a <_exit>
清除SREG(我不确定这是否确实需要),将0x9f(RAMEND)写入SPL(堆栈指针)并跳转到main。最后一个rjmp是多余的。(您可以保证永远不会从main返回)
00000020 <__bad_interrupt>:
20: ef cf rjmp .-34 ; 0x0 <__vectors>
这些中断的默认中断过程在C中不会被覆盖。(与__vectors相同的规则)
00000022 <main>:
22: bb 9a sbi 0x17, 3 ; 23
24: c3 9a sbi 0x18, 3 ; 24
26: c3 98 cbi 0x18, 3 ; 24
28: fd cf rjmp .-6 ; 0x24 <main+0x2>
您的主要过程。紧。
0000002a <_exit>:
2a: f8 94 cli
0000002c <__stop_program>:
2c: ff cf rjmp .-2 ; 0x2c <__stop_program>
这两个不是很有用。C标准可能需要_exit,并且需要__stop_program才能使其正常工作。
您最终的申请是什么?一个ATtiny13具有1kB的闪存,您可以在C语言中完成很多工作。crt0是avr-libc C运行时。它包含诸如堆栈处理之类的内容,因此您可以将函数与参数和返回值一起使用。
嵌入式C设置的100字节还不错,并且大小不变。将程序逻辑行加倍不一定会使它变成200个字节。您正在编译什么优化级别?您应该位于“ -Os”。您如何编译呢?可从avr-libc站点获得的演示项目中的Makefile非常好且全面。
下面的简单LED开/关程序在ATtiny13上占用62个字节,在avr-gcc 4.3.3上带有“ -Os”。从CrossPack-AVR:
#include <avr / io.h> #include <avr / delay.h> int main(无效) { DDRB | = _BV(PB3); while(1){ PORTB | = _BV(PB3); _delay_ms(200); PORTB&=〜_BV(PB3); _delay_ms(200); } }
删除_delay_ms()调用将使其变为46个字节。
ATtiny13上的一个更大的例子是我的Smart LED原型。该代码包含一个3通道软件PWM,一个从HSV到RGB的颜色转换,一个状态机,并读取两个按钮。它写得不是很好,只有864字节。在avr-gcc 3.x下,它甚至更小。(由于某种原因,avr-gcc 4使得几乎所有程序都增加了几个字节)
avr-gcc -std=c99 -Wall -Os -mmcu=attiny13 -o hello.out helloworld.c
是我的makefile(自行创建)中的相关行。和我使用几乎相同的代码,除了翻转我使用的LED PORTB &= ~(1 << LED);
等等
如果空间不足,请尝试使用IAR的嵌入式工作台-他们的免费“ kickstart”版本具有4K字码大小限制,对于ATTiny来说足够多,并且可能比gcc更好的优化