ATtiny13 -- avr-gcc Hello World 使用超过 100 个字节?

电器工程 avr 服装 编程 编译器
2022-01-25 13:25:31

我正在尝试为 ATtiny13 编写一个程序。我的问题是它有很大的尺寸限制。好吧,在制作我的第一个 Hello World 程序时,只需要 100 字节的程序空间就可以打开和关闭灯!我可以给 avr-gcc 提供什么选项来缩小这个大小吗?另外,crt0中有什么?我不太热衷于 AVR 组装,所以我不太了解它..

我不想为了这个项目而去组装..

4个回答

您可以使用 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 开/关程序在 avr-gcc 4.3.3 上带有“-Os”的 ATtiny13 上占用 62 个字节。来自 CrossPack-AVR:

#include <avr/io.h>
#include <avr/delay.h>

诠释主要(无效)
{
    DDRB |= _BV( PB3 );
    而(1){
        PORTB |= _BV( PB3 );
        _delay_ms(200);
        PORTB &=~ _BV( PB3 );
        _delay_ms(200);
    }
}

删除 _delay_ms() 调用使其变为 46 个字节。

ATtiny13 上一个更大的例子是我的智能 LED 原型此代码包含 3 通道软件 PWM、HSV 到 RGB 颜色转换、状态机和读取两个按钮。它写得不是特别好,只有 864 字节。在 avr-gcc 3.x 下它甚至更小。(出于某种原因,avr-gcc 4 使几乎所有程序都增长了几个字节)

crt0 是 uC 的启动例程。这些例程执行寄存器的设置以及数据的初始化。

100 字节是否包含中断向量表?我不确定 ATtiny13 但 ATtiny25/45/85 有 15 个中断向量。这将占用 30 个字节。

gcc 有一个选项来链接你的 crt0。您可以获取 AVR crt0.S 文件并对其进行修改。它不是很长,所以应该不难做到。

如果您空间不足,请尝试 IAR 的嵌入式工作台——他们的免费“kickstart”版本有 4K 字代码大小限制,对于 ATTiny 来说已经足够了,并且可能比 gcc 更好的优化