ATTiny13에 대한 프로그램을 작성하려고합니다. 내 문제는 크기 제약이 크다는 것입니다. 첫 번째 Hello World 프로그램을 만들 때 조명을 켜고 끄는 데 100 바이트의 프로그램 공간이 필요했습니다! 이 크기를 줄이기 위해 avr-gcc에 제공 할 수있는 옵션이 있습니까? 또한 crt0에 무엇입니까? 나는 AVR 어셈블리에 너무 열중하지 않아서 많이 이해하지 못한다 ..
이 프로젝트를 위해 어셈블리로 드롭하지 않아도됩니다.
ATTiny13에 대한 프로그램을 작성하려고합니다. 내 문제는 크기 제약이 크다는 것입니다. 첫 번째 Hello World 프로그램을 만들 때 조명을 켜고 끄는 데 100 바이트의 프로그램 공간이 필요했습니다! 이 크기를 줄이기 위해 avr-gcc에 제공 할 수있는 옵션이 있습니까? 또한 crt0에 무엇입니까? 나는 AVR 어셈블리에 너무 열중하지 않아서 많이 이해하지 못한다 ..
이 프로젝트를 위해 어셈블리로 드롭하지 않아도됩니다.
답변:
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는 일종의 중복입니다. (메인에서 돌아 오지 않겠다고 약속 할 수 있음)
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이 제대로 작동하려면 필요합니다.
최종 신청은 무엇입니까? 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);
등을
공간이 부족한 경우 IAR의 Embedded Workbench를 사용해보십시오. 무료 '킥 스타트'버전에는 4K 단어 코드 크기 제한이 있으므로 ATTiny의 경우에는 충분하며 gcc보다 최적화가 더 좋습니다.