ATTiny13 — avr-gcc Hello World는 100 바이트 이상을 사용합니까?


9

ATTiny13에 대한 프로그램을 작성하려고합니다. 내 문제는 크기 제약이 크다는 것입니다. 첫 번째 Hello World 프로그램을 만들 때 조명을 켜고 끄는 데 100 바이트의 프로그램 공간이 필요했습니다! 이 크기를 줄이기 위해 avr-gcc에 제공 할 수있는 옵션이 있습니까? 또한 crt0에 무엇입니까? 나는 AVR 어셈블리에 너무 열중하지 않아서 많이 이해하지 못한다 ..

이 프로젝트를 위해 어셈블리로 드롭하지 않아도됩니다.


작은 참고로, 일부 사람들은이를 "블링키"프로그램이라고 부릅니다.
Johan

1
@Johan 잘 나는 "blinkenlights"철자하는 방법을 확실하지 않았다
Earlz

답변:


9

crt0은 uC의 시작 루틴입니다. 루틴은 레지스터 설정 및 데이터 초기화를 수행합니다.

100 바이트에 인터럽트 벡터 테이블이 포함됩니까? ATtiny13에 대해서는 확실하지 않지만 ATtiny25 / 45 / 85에는 15 개의 인터럽트 벡터가 있습니다. 이 작업에는 30 바이트가 소요됩니다.

gcc는 crt0에 링크하는 옵션이 있습니다. AVR crt0.S 파일을 가져 와서 수정할 수 있습니다. 너무 길지 않아서 어렵지 않아야합니다.


crt0 소스를 찾을 수 없지만 crt1에는 인터럽트 벡터 테이블이있는 것 같습니다. 아마 그게
다야

내 시스템에서 찾을 수 없습니다 :( 나는 소스에서 모든 도구를 컴파일 했으므로 거기에있을 것이라고 생각했습니다. "crt0.S atmel"에 대한 Google의 경우 시작, crt0 및 gcc에 대한 몇 가지 Atmel 앱 노트 아마도 그 문서들에 힌트가있을 것입니다.
jluciani

@jlu 나는 둘 사이의 차이점을 알아 내려고 노력하고 있지만 아직 스택 오버플로에서 좋은 점을 얻지 못했습니다 : stackoverflow.com/questions/2709998/…
Earlz

2
avr-libc는 AVR 칩 유형마다 CRT가 다르며 표준 avr-libc 배포판에는 파일의 .o 버전 만 포함됩니다. ATtiny13은 [avr-libc-path] /avr-3/lib/crttn13.o에 있습니다.
todbot

@todbot 흠. 아, 그래 /avr-libc-1.6.7/avr/lib/avr2/attiny13/crttn13.S
맞아

19

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는 일종의 중복입니다. (메인에서 돌아 오지 않겠다고 약속 할 수 있음)

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>

이 둘은별로 유용하지 않습니다. _exit는 아마도 C 표준에 필요하고 __stop_program이 제대로 작동하려면 필요합니다.


16

최종 신청은 무엇입니까? 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>

int main (void)
{
    DDRB | = _BV (PB3);
    while (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는 거의 모든 프로그램을 몇 바이트 씩 늘 렸습니다)


avr-gcc -std=c99 -Wall -Os -mmcu=attiny13 -o hello.out helloworld.c내 makefile (자체 생성)의 관련 줄입니다. 그리고는 LED I 이용 플립하는 것을 제외하고는 거의 동일한 코드를 사용 PORTB &= ~(1 << LED);등을
Earlz을

그리고 예, 크기는 일정하지만 46 바이트조차도 스택 프레임을 설정하면됩니다.
Earlz

2

공간이 부족한 경우 IAR의 Embedded Workbench를 사용해보십시오. 무료 '킥 스타트'버전에는 4K 단어 코드 크기 제한이 있으므로 ATTiny의 경우에는 충분하며 gcc보다 최적화가 더 좋습니다.


1
최적화 비교는 높은 경합의 대상입니다. 나는 거기에 가지 않을 것이다.
tyblu

1
@tyblu 나는 동의하지만, IAR은 예를 들어 avr-gcc보다 작은 바이너리를 생성하는 것으로 알려져 있습니다. 또한 mikeselectricstuff에도 동의 할 것이며 제정신의 조언이라고 생각합니다.
Morten Jensen

1

이와 같은 장치는 종종 어셈블러로 프로그래밍되어 실행 파일 크기가 작아집니다. 노력하고 사용하는 법을 배울 가치가 있습니다.


1
나는 동의하지만 IMHO의 목표는 전체 장치를 어셈블리로 프로그래밍하는 것이 아니라 (이것은 자주 수행되고 있음을 알고 있음) C 컴파일러가 뒤에서 수행하는 작업을 디코딩하고 확인할 수 있다는 것입니다. 또한 컴파일러를 자주 추측하고 C로 작성한 코드를 최적화하여 작은 실행 파일 크기를 얻을 수 있음을 의미합니다.
jpc
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.