mikroPascal vs. C na AVRy

Witajcie.

Wziąłem prosty program i skompilowałem go dwóch środowiskach programistycznych celem porównania wielkości kodu wynikowego.

  1. Mikropascal
  2. AVR Studio + GCC

Zadaniem programu testowego było utworzenie migacza z diody LED.

W C:

#include <avr/io.h>

#include <util/delay.h>

#define F_CPU 4000000 #define CYCLES_PER_US ((F_CPU+500000)/1000000)

#define LED_ON sbi(DDRD,PD0);sbi(PORTD,PD0) #define LED_OFF sbi(DDRD,PD0);cbi(PORTD,PD0)

int main (void) { for (;;) { LED_ON; _delay_ms(1000); LED_OFF; _delay_ms(1000); } return (0); }

  1. Pascal:

program miagacz;

procedure wait; begin Delay_ms(300); end; begin DDRD:=$FF; while true do begin PORTD:=$FF; // włącz wait; PORTD:=$00; // wyłącz wait; end; end.

Wynik był następujący (porównanie wielkości pliku .hex):

C: 9697 bajtów + 13 bajtów plik *.eep

mikroPascal : 300 bajtów

Jak zminiejszyć "objętość" programu w C ?

Chciałem wybrać C jako narzędzie do oprogramowania chipów ale składnia i prostota mikroPascala zdecydowanie przemawia za nim.

Pozdrawiam L.

Reply to
Legato
Loading thread data ...

Włącz opcję -Os w GCC.

pozdrawiam Krzysztof Kajstura

Reply to
Krzysztof Kajstura

Legato napisał(a):

A dlaczego dla porównania nie napisałeś takiego samego migacza w asemblerze? Kod wynikowy będzie liczył pewnie kilkadziesiąt bajtów, kod źródłowy nie będzie raczej dłuższy ani bardziej skomplikowany niż w języku C. Porównuj lepiej długość kodu binarnego (po konwersji hex2bin) a nie pliku hex.

Wracając do tematu: sam kod wynikowy "właściwy" funkcji migającej w C ma kilkanaście bajtów, dodatkowo funkcja opóźniająca nieco dodaje. Reszta to biblioteka standardowa (głównie start programu w C). Można oczywiście pewnymi sztuczkami wyeliminować te dodatki, ale tylko w tym konkretnym przypadku.

Twoją funkcję sprawdziłem kompilując kod dla procesora ATmega128 kompilatorem avr-gcc 4.1.1 (WinAVR 20070122). No to po kolei:

1) używasz chyba starego kompilatora gcc, w nowej wersji nie ma już makr sbi ani cbi - zastąpiłem odpowiednimi sekwencjami |= i &=~ 2) wynikowy plik binarny ma 228 bajtów (w Makefile'u nie dołączam bibliotek do printf'ów ani matematycznej - może to u Ciebie jest problemem?) 3) pierwsze 140 bajtów kodu wynikowego to wektory przerwań, tu można oszczędzić najwięcej nie korzystając ze standardowych plików startowych (opcja -nostartfiles) ale wtedy najczęściej musiałbyś zapewnić także własne funkcje: zerującą sekcję danych .bss (__do_clear_bss) i przepisującą sekcję .data (__do_copy_data) a wcześniej ustawić wskaźnik stosu i wyzerować r1 4) oczywiście dla mniejszych procesorów będzie mniej wektorów przerwań - program skompilowany dla np. ATtiny22 (wykorzystujący PORTB i DDRB bo nie ma portu D w tym procu) ma tylko 88 bajtów binariów 5) możesz zainicjować raz a dobrze rejestr DDR a potem tylko migać pinem portu - binaria schodzą do 86 bajtów 6) na koniec rozwiązanie totalne czyli wywalenie standardowego startupu (patrz pkt. 3) i niekorzystanie z biblioteki standardowej (opcja

-nostdlib) daje wynikowy plik binarny długości 28 bajtów.

Czy taka optymalizacja ma sens? Oczywiście nie ale to już inna sprawa.

Finalny kod źródłowy w C dający 28-bajtowy binarny plik wynikowy (do linkera dorzucone opcje -nostartfiles i -nostdlib):

#define F_CPU 4000000

#include <avr/io.h>

#include <util/delay.h>

#define LED_ON PORTB |= (1 << PB0) #define LED_OFF PORTB &= ~(1 << PB0)

int main (void) { DDRB |= (1<<PB0); for (;;) { LED_ON; _delay_ms (1000); LED_OFF; _delay_ms (1000); } return 0; }

Reply to
Adam Dybkowski
Reply to
Jerzy Turynski

Adam Dybkowski napisał(a):

Wiem, wiem ale nie napisałem dlatego, że niestety nie znam assemblera :(

Zdecydowaną poprawę wniosło ustawienie opcji -Os zaproponowanej przez kol. Krzysztof Kajstura oraz wyeliminowaniu zbędnych bibliotek.

Masz rację. Mam avr-gcc-3.4.1 Zabieram się do aktualizacji :)

Powiem tak, skompilowałem to "standardowo" jak leci w AVRStudio bez zastosowania wszelakich "optymizerów" kodu. Stąd wyszło jak wyszło. Do następnych kompilacji zastosuję się do porad Twoich jak i innych kolegów.

Dzięki Tobie i innym za fajną lekcję :)

Dopiero startuję z pisaniem w C na AVRy więc Twoje uwagi są dla mnie cenne. Jak by co to pozwolę sobie zamącić Wam w tym temacie głowę.

Pozdrawiam L.

Reply to
Legato

Adam Dybkowski napisał(a):

Nie udało mi się dogonić mistrza. Wpisując Twoje parametry udało mi się osiągnąć postęp który jest dość znaczny :)

349 bajtowy plik hex i 116 bajtowy bin

Gdybyś był uprzejmy przeglądnąć plik makefile byłbym Ci wdzięczny. Oto on:

############################################################################### # Makefile for the project Migacz ###############################################################################

## General Flags PROJECT = Migacz MCU = atmega8 TARGET = Migacz.elf CC = avr-gcc.exe

## Options common to compile, link and assembly rules COMMON = -mmcu=$(MCU)

## Compile options common for all C compilation units. CFLAGS = $(COMMON) CFLAGS += -Wall -gdwarf-2 -nostartfiles -nostdlib -DF_CPU=4000000UL

-Os -fsigned-char CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d

## Assembly specific flags ASMFLAGS = $(COMMON) ASMFLAGS += $(CFLAGS) ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2

## Linker flags LDFLAGS = $(COMMON) LDFLAGS +=

## Intel Hex file production flags HEX_FLASH_FLAGS = -R .eeprom

HEX_EEPROM_FLAGS = -j .eeprom HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load" HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings

## Library Directories LIBDIRS = -L"F:\avr\winavr\avr\include\avr"

## Objects that must be built in order to link OBJECTS = migacz.o

## Objects explicitly added by the user LINKONLYOBJECTS =

## Build all: $(TARGET) Migacz.hex Migacz.eep size

## Compile migacz.o: ../migacz.c $(CC) $(INCLUDES) $(CFLAGS) -c $<

##Link $(TARGET): $(OBJECTS) $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)

%.hex: $(TARGET) avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@

%.eep: $(TARGET) -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0

%.lss: $(TARGET) avr-objdump -h -S $< > $@

size: ${TARGET} @echo @avr-size -C --mcu=${MCU} ${TARGET}

## Clean target .PHONY: clean clean: -rm -rf $(OBJECTS) Migacz.elf dep/* Migacz.hex Migacz.eep

## Other dependencies

-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)

Pozdrawiam L.

Reply to
Legato

In the darkest hour on Wed, 31 Jan 2007 07:28:09 +0100, Janusz <janusz snipped-for-privacy@poczta.onet.pl> screamed:

Absolutnie nic. To taka informatyka przez duże U.

Reply to
Artur M. Piwko

Jerzy Turynski napisał(a):

:-o Ale o so chozi?

Pod pojęciem "finalny kod źródłowy" przytoczyłem poprawioną wersję kodu źródłowego załączonego przykładu programu w języku C, uwzględniającą ograniczenia wymuszane przez nowszą wersję kompilatora avr-gcc takie jak brak makr cbi i sbi. Poza tym w języku C często na kilka sposobów można zapisać sekwencję dającą ten sam binarny kod wynikowy - więc mój "finalny kod źródłowy" to tylko przykład poprawienia programu migającego diodą na jeden z wielu możliwych sposobów.

Reply to
Adam Dybkowski

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.