57
Techniki mikroprocesorowe Język C dla mikroprocesorów AVR Wykład 6

C dla AVR - lielow/PTM/Wyklady/W6_C_dla_AVR.pdf · Techniki mikroprocesorowe Języki programowania •Mikrokontrolery AVR ze względu na swoją popularność doczekały się implementacji

Embed Size (px)

Citation preview

Techniki mikroprocesorowe

Język C dla mikroprocesorów AVR

Wykład 6

Narzędzia

Techniki mikroprocesorowe

Programowanie AVR

2

Techniki mikroprocesorowe

Języki programowania

• Mikrokontrolery AVR ze względu na swoją popularność doczekały się implementacji kompilatorów dla znacznej części dostępnych języków programowania

• Najpopularniejsze w chwili obecnej są assembler i C

3

Techniki mikroprocesorowe

Kompilator języka C

• Najpopularniejszy zestaw narzędzi dla języka C dla platformy AVR bazuje na porcie kompilatora gcc: avr-gcc

• Zestaw ten dla środowiska Windows nasi nazwę WinAVR

http://winavr.sourceforge.net/

4

Techniki mikroprocesorowe

WinAVR

• W skład pakietu WinAVR wchodzą następujące elementy – Kompilator C/C++ (avr-gcc, avr-g++)

– Zestaw plików nagłówkowych dla wszystkich mikrokontrolerów AVR

– Program make

– Powłoka bash wraz z podstawowymi narzędziami

– Wygodny edytor Programmer’s Notepad 2 (PN2)

– Program avrdude do programowania pamięci mikrokontrolerów AVR

5

Techniki mikroprocesorowe

Programmer’s Notepad 2

• Jest to darmowy prosty edytor dla programistów, z obsługą projektów, kolorowaniem składni wielu języków oraz możliwością korzystania z kompilatora i programatora z poziomu edytora

http://www.pnotepad.org/

6

Techniki mikroprocesorowe

Programmer’s Notepad 2

7

Techniki mikroprocesorowe

Atmel Studio 6

• Jest to darmowe zintegrowane środowisko programistyczne, rozwijane przez firmę Atmel, producenta mikrokontrolerów AVR

• Umożliwia pisanie programów dla architektura AVR i ARM w assemblerze oraz C/C++

• Bazuje na MS Visual Studio, zintegrowanym z avr-gcc i arm-gcc

8

Atmel Studio 6

Techniki mikroprocesorowe

• Środowisko wspiera kilka typów programatorów oraz mechanizmy ułatwiające debugowanie

http://www.atmel.com/microsite/atmel_studio6/

9

Techniki mikroprocesorowe

Atmel Studio 6

10

Przygotowanie projektu WinAVR + PN2

Techniki mikroprocesorowe

Przygotowanie projektu

11

Techniki mikroprocesorowe

Etapy

• Utworzenie w PN2 nowego projektu

• Skopiowanie do katalogu projektu generycznego pliku Makefile, który można znaleźć w katalogu domowym WinAVR (podkatalog sample)

• Dodanie plik Makefile do projektu w PN2

• Konfiguracja pliku Makefile

12

Techniki mikroprocesorowe

Etapy

• Utworzenie jednego lub kilku plików z kodem źródłowym

• Dodanie informacji o plikach źródłowych do Makefile

• Kompilacja z poziomu PN2

• Programowanie mikrokontrolera AVR z poziomu PN2

13

Techniki mikroprocesorowe

Konfiguracja pliku Makefile

• W domyślnym pliku Makefile zmiany wymagają następujące elementy

– Model mikrokontrolera i częstotliwość zegara taktującego

– Lista plików z kodem źródłowym do kompilacji

– Flagi kompilatorów (opcjonalnie)

– Konfiguracja programatora (opcjonalnie)

14

Techniki mikroprocesorowe

Makefile - konfiguracja

• Zmiany w domyślnym pliku Makefile

MCU = atmega32 #model mikrokontrolera F_CPU = 11059200 #częstotliwość zegara w Hz TARGET = main #prefix plików wynikowych

SRC = $(TARGET).c #lista plików źródłowych C CPPSRC = … #lista plików źródłowych C++ ASRC = … #lista plików źródłowych assemblera

15

Techniki mikroprocesorowe

Makefile – konfiguracja

• Flagi optymalizacji

OPT = 0 #optymalizacja wyłączona

OPT = 1 #2 lub 3 – optymalizacja wydajności

OPT = s #optymalizacja rozmiaru pliku wynikowego

16

Techniki mikroprocesorowe

Makefile – flagi CFLAGS i CXXFLAGS kompilatora C/C++

-funsigned-char – używaj domyślnie „unsigned char” zamiast „char”

-funsigned-bitfields - używaj domyślnie pól bitowych bez znaku zamiast ze znakiem

-fpack-struct – umieszczaj elementy struktur bezpośrednio jeden za drugim, bez wyrównywania i powstałych w ten sposób dziur

-fshort-enums – alokuj tylko tyle miejsce dla typu enum ile mogą zająć możliwe wartości o zadeklarowanych zakresach

17

Techniki mikroprocesorowe

Makefile – flagi kompilatora C/C++

-Wstrict-prototypes – ostrzegaj, jeśli funkcja jest zadeklarowana lub zdefiniowana bez deklaracji typów argumentów

-mshort-calls – używaj funkcji rjmp/rcall (funkcje skoku o ograniczonym zakresie) dla układów z >8kB pamięci, domyślnie dla takich układów wykorzystywane są funkcje jmp/call

-fno-unit-at-a-time – opcja pozostawiona w celu zapewnienia kompatybilności

18

Techniki mikroprocesorowe

Makefile – flagi kompilatora C/C++

-Wundef – ostrzegaj, jeśli dyrektywa #if korzysta z niezadeklarowanego argumentu

-Wunreachable-code – ostrzegaj, jeśli program zawiera kod, który nigdy nie zostanie wykonany

-Wsign-compare – ostrzegaj, gdy jest porównywana zmienna ze znakiem i bez znaku

-Wall – wyświetlaj wszystkie typy ostrzeżeń podczas kompilacji

19

Techniki mikroprocesorowe

Makefile - programator

• W procesie programowania wykorzystywany jest program avrdude, obsługujący wszystkie popularne programatory dla AVR dostępne na rynku, w tym USBASP i STK500v2

• Konfiguracja polega na wybraniu modelu programatora i portu, do którego jest podłączony

20

Techniki mikroprocesorowe

Makefile - programator

#wskazanie modelu programatora

AVRDUDE_PROGRAMMER = stk500v2

#port, do którego jest podłączony programator

AVRDUDE_PORT = com1

21

Techniki mikroprocesorowe

Użyteczne komendy

• Kompilacja programu make all

• Usunięcie plików tymczasowych i wynikowych make clean

• Programowanie mikrokontrolera make program

22

Techniki mikroprocesorowe

avrdude – obsługa z konsoli

• Konfiguracja programu avrdude w pliku Makefile nie zawsze wystarcza do wykonania nietypowych operacji podczas programowania

• Niektóre przypadki, takie jak modyfikacja fusebitów jest niewygodna podczas realizacji przez Makefile i wygodniej jest wykonać niezbędne operacje z konsoli

23

Techniki mikroprocesorowe

avrdude – obsługa z konsoli

• Komenda bazowa avrdude -p atmega32 -c stk500v2 -P com1

• Odczyt pamięci EEPROM -D -U eeprom:r:"eeprom.eep":i

• Odczyt pamięci FLASH -U flash:r:"flash.hex":i

• Odczyt fusebitów -u -U lfuse:r:"fuse_lo.hex":i -U hfuse:r:"fuse_hi.hex":i

• Odczyt lockbitów -U lock:r:"fuse_lock.hex":i

24

Techniki mikroprocesorowe

avrdude – obsługa z konsoli

• Komenda bazowa avrdude -p atmega32 -c stk500v2 -P com1 -V

• Zapis pamięci EEPROM -D -U eeprom:w:"eeprom.eep":i

• Zapis pamięci FLASH -U flash:w:"flash.hex":i

• Zapis fusebitów -u -U lfuse:w:0xE1:m -U hfuse:w:0x99:m

• Zapis lockbitów -U lock:w:0x3F:m

25

Techniki mikroprocesorowe

avrdude – obsługa z konsoli

• Kasowanie pamięci mikrokontrolera avrdude -p atmega32 -c stk500v2 -P com1 -e

• Komendy z jednego slajdu mogą być ze sobą łączone

26

Język C dla AVR

Techniki mikroprocesorowe

Język C dla AVR

27

Techniki mikroprocesorowe

Język C dla AVR

• Konstrukcja programu w języku C dla mikrokontrolerów AVR jest bardzo podobna do programu dla PC

• W celu optymalnej i wygodnej obsługi wszystkich elementów mikrokontrolera programista ma do dyspozycji szereg makr, funkcji i typów, niespotykanych w bibliotece standardowej dla innych platform

28

Techniki mikroprocesorowe

Typy w języku C dla AVR

• Rozmiar generycznych typów zmiennych

Typ Rozmiar (bitów)

Wartość minimalna Wartość maksymalna

char 8 -128 (0) 127 (255)

signed char 8 -128 127

unsigned char 8 0 255

short int 16 -32768 32767

unsigned short int 16 0 65535

int 16 -32768 32767

unsigned int 16 0 65535

long int 32 -2^31 2^31-1

29

Techniki mikroprocesorowe

Typy w języku C dla AVR

Typ Rozmiar (bitów)

Wartość minimalna Wartość maksymalna

unsigned long int 32 0 2^32-1

long long int 64 -2^63 2^63-1

unsigned long long int

64 0 2^64-1

float 32 ±1.18·10^(-38) ±3.4·10^38

double 32 ±1.18·10^(-38) ±3.4·10^38

long double 32 ±1.18·10^(-38) ±3.4·10^38

30

Techniki mikroprocesorowe

Typy w języku C dla AVR

• Skrócone nazwy typów C dla AVR signed char int8_t

unsigned char uint8_t signed int int16_t unsigned int uint16_t signed long int int32_t unsigned long int uint32_t signed long long int int64_t unsigned long long int uint64_t

31

Techniki mikroprocesorowe

Obsługa rejestrów w języku C dla AVR

• Zastąpienie zawartości NAZWA_REJESTRU = (1 << NAZWA_BITU);

• Ustawienie bitu NAZWA_REJESTRU |= (1 << NAZWA_BITU);

• Wyczyszczenie bitu NAZWA_REJESTRU &= ~(1 << NAZWA_BITU);

• Odczyt stanu bitu wartosc_bitu = ((NAZWA_REJESTRU >>

NAZWA_BITU) & 0x1); 32

Techniki mikroprocesorowe

Obsługa rejestrów w języku C dla AVR

• Aby skonfigurować port PA0 jako wyjście: DDRA |= (1 << DDA0);

• Aby skonfigurować port PB1 jako wejście z domyślnym stanem logicznym „1”: DDRB &= ~(1 << DDB1); PORTB |= (1 << PORTB1);

• Aby ustawić na porcie PC2 logiczną „1”: PORTC |= (1 << PORTC2);

• Aby odczytać stan portu PD3: stan_pd3 = ((PIND >> PIND3) & 0x1);

33

Techniki mikroprocesorowe

Przerwania w języku C dla AVR

• Do obsługi przerwań w języku C służy makro ISR

ISR (NAZWA_WEKTORA_PRZERWANIA)

{

//obsługa przerwania

}

34

Techniki mikroprocesorowe

Przerwania w języku C dla AVR

• Alternatywnie można użyć do tego celu makra

SIGNAL (NAZWA_SYGNAŁU)

{

//obsługa przerwania

}

35

Techniki mikroprocesorowe

Przerwania – lista wektorów i sygnałów ATmega32

Opis Wektor Sygnał

External Interrupt Request 0 INT0_vect SIG_INTERRUPT0

External Interrupt Request 1 INT1_vect SIG_INTERRUPT1

External Interrupt Request 2 INT2_vect SIG_INTERRUPT2

Timer/Counter2 Compare Match TIMER2_COMP_vect SIG_OUTPUT_COMPARE2

Timer/Counter2 Overflow TIMER2_OVF_vect SIG_OVERFLOW2

Timer/Counter1 Capture Event TIMER1_CAPT_vect SIG_INPUT_CAPTURE1

Timer/Counter1 Compare Match A TIMER1_COMPA_vect SIG_OUTPUT_COMPARE1A

Timer/Counter1 Compare Match B TIMER1_COMPB_vect SIG_OUTPUT_COMPARE1B

Timer/Counter1 Overflow TIMER1_OVF_vect SIG_OVERFLOW1

Timer/Counter0 Compare Match TIMER0_COMP_vect SIG_OUTPUT_COMPARE0

Timer/Counter0 Overflow TIMER0_OVF_vect SIG_OVERFLOW0

Serial Transfer Complete SPI_STC_vect SIG_SPI 36

Techniki mikroprocesorowe

Przerwania – lista wektorów i sygnałów ATmega32

Opis Wektor Sygnał

USART, Rx Complete USART_RXC_vect SIG_USART_RECV SIG_UART_RECV

USART Data Register Empty USART_UDRE_vect SIG_USART_DATA SIG_UART_DATA

USART, Tx Complete USART_TXC_vect SIG_USART_TRANS SIG_UART_TRANS

ADC Conversion Complete ADC_vect SIG_ADC

EEPROM Ready EE_RDY_vect SIG_EEPROM_READY

Analog Comparator ANA_COMP_vect SIG_COMPARATOR

2-wire Serial Interface TWI_vect SIG_2WIRE_SERIAL

Store Program Memory Ready SPM_RDY_vect SIG_SPM_READY

37

Techniki mikroprocesorowe

Modyfikator volatile

• Zmienne globalne, które mają być wykorzystywane wewnątrz zwykłych funkcji i funkcji obsługi przerwań powinny być zaopatrzone w modyfikator volatile

volatile TYP_ZMIENNEJ NAZWA_ZMIENNEJ;

• Modyfikator volatile zapobiega optymalizacji polegającej na operowaniu przez program na tymczasowej kopii zmiennej, co może być źródłem utraty danych

38

Techniki mikroprocesorowe

PROGMEM

• Zmienne, które nie będą modyfikowane, a potrzebują dużo pamięci mogą być trzymane w pamięci programu, zamiast pamięci RAM

#include <avr/pgmspace.h>

TYP ZMIENNA PROGMEM = WARTOŚĆ;

TYP ZMIENNA_1 = pgm_read_xxx(ADRES_ZMIENNEJ);

39

Techniki mikroprocesorowe

PROGMEM

• W zależności od lokalizacji zmiennej w pamięci wyróżnia się wersje „near” i „far” funkcji pgm_read_xxx

• Adres w wersji „near” jest 16-bitowy, natomiast w wersji „far” – 32-bitowy

40

Techniki mikroprocesorowe

PROGMEM

• Funkcje w wersji „far”

– pgm_read_byte_far(address_long)

– pgm_read_word_far(address_long)

– pgm_read_dword_far(address_long)

– pgm_read_float_far(address_long)

41

Techniki mikroprocesorowe

PROGMEM

• Funkcje w wersji „near”

– pgm_read_byte(address_short)

– pgm_read_word(address_short)

– pgm_read_dword(address_short)

– pgm_read_float(address_short)

42

Techniki mikroprocesorowe

Modyfikator inline

• Modyfikator ten informuje kompilator, że jeśli nastąpi wywołanie funkcji inline, to zamiast wygenerować w tym miejscu przeniesienie sterowania (skok) do tej funkcji, bezpośrednio wstawi wygenerowany kod tej funkcji

• Funkcje inline stosuje się w sytuacji, gdy wydajność jest ważniejsza od objętości kodu wynikowego

43

Techniki mikroprocesorowe

Modyfikator inline

• Przykład inline uint8_t max(uint8_t a, uint8_t b) { return a > b ? a : b; }

44

Techniki mikroprocesorowe

cli() i sei()

• Aby zapewnić niepodzielność operacji przez przerwania , które mogłyby być w tym czasie zgłoszone, stosuje się funkcje cli() i sei(), blokującą i odblokowującą globalną obsługę przerwań na czas wykonywania takiej operacji

45

Techniki mikroprocesorowe

Obsługa portów I/O

• Makra upraszczające obsługę portów I/O #define PORT(x) XPORT(x) #define XPORT(x) (PORT##x) #define PIN(x) XPIN(x) #define XPIN(x) (PIN##x) #define DDR(x) XDDR(x) #define XDDR(x) (DDR##x) Np. #define DRIVER_PORT A #define DRIVER_PIN_0 0 PORT(DRIVER_PORT) = (1 << DRIVER_PIN);

46

Optymalizacja kodu

Techniki mikroprocesorowe

Optymalizacja kodu

47

Techniki mikroprocesorowe

Cele optymalizacji

• Ograniczenie rozmiaru kodu wynikowego

• Ograniczenie zużycia pamięci operacyjnej

• Ograniczenie zużycia czasu procesora

• Zapewnienie niezawodności programu

• Ograniczenie liczby potencjalnie niebezpiecznych elementów kodu

48

Techniki mikroprocesorowe

Ograniczenie rozmiaru kodu wynikowego

• Przykłady realizacji

– Unikanie funkcji inline

– Unikanie powtarzania tych samych fragmentów kodu, jeśli to możliwe zastąpić je jedną funkcją

– Niekorzystanie z rozbudowanych gotowych funkcji, jeśli ich możliwości nie będą w pełni wykorzystane

– Użycie flagi optymalizacji „s”

49

Techniki mikroprocesorowe

Ograniczenie zużycia pamięci operacyjnej

• Stosowanie zmiennych ze znakiem i/lub zmiennoprzecinkowych tylko w razie konieczności

• Stosowanie możliwie „małych” typów danych

• Dokładne szacowanie objętości potrzebnych danych w pamięci RAM

• Unikanie rekurencji

• Stosowanie dynamicznego przydziału pamięci tylko w ostateczności (ryzyko wycieku)

50

Techniki mikroprocesorowe

Ograniczenie zużycia czasu procesora

• Wykorzystywanie funkcji inline • Wstawki assemblerowe • Jeśli to możliwe zastąpienie złożonych funkcji

arytmetycznych (np. sin, cos) tablicami • Korzystanie z flag optymalizacji „1”, „2”, „3” • Unikanie typów zmiennych liczbowych, na

których operacje arytmetyczne wykonywane są w sposób programowy

• Operacje arytmetyczne wykonywać na liczbach całkowitych

51

Techniki mikroprocesorowe

Poprawienie czasu odpowiedzi programu

• Wykorzystywanie asychronicznych trybów pracy peryferiów

• Przeniesienie możliwie dużej części sterowania programem do funkcji obsługi przerwań (pamiętając o priorytetach przerwań!)

• Priorytetyzacja zadań w programie

• Uproszczenie i optymalizacja funkcji krytycznych dla responsywności systemu

52

Techniki mikroprocesorowe

Zapewnienie niezawodności programu

• Unikanie dynamicznego alokowania pamięci oraz korzystanie z narzędzi do analizy użycia pamięci

• Unikanie funkcji operujących na strumieniach, o zmiennej liczbie argumentów itp.

• Unikanie operowania na rejestrach korzystając z numerów bitów zamiast nazw bitów

• Korzystanie z układów BOD (Brown-out Detection) i watchdog

53

Przykład prostego programu

Techniki mikroprocesorowe

Przykład

54

Techniki mikroprocesorowe

Przykład prostego programu

#include <inttypes.h> #include <avr/io.h> #include <avr/interrupt.h> volatile uint8_t led = 0; //obsluga przerwan INT0 (przycisk) ISR (INT0_vect) { led = (led + 1) % 2; }

55

Techniki mikroprocesorowe

Przykład prostego programu

int main(void) { //konfiguracja portow I/O DDRA |= (1<<DDA0); //wyjscia sterujace diodami PORTA |= (1<<PORTA0); PORTD |= (1<<PORTD2); //wejscie przycisku cli(); //blokujemy globalnie dzialanie przerwan MCUCR |= (1<<ISC01); //przerwania INT0 reagujace na zbocze opadajace

(nacisniecie przycisku) GICR |= (1<<INT0)); //wlaczamy przerwania INT0 sei(); //odblokowujemy globalnie dzialanie przerwan

56

Techniki mikroprocesorowe

Przykład prostego programu

//nieskonczona petla glowna programu while(1) { if(led == 0) PORTA &= ~(1<<dioda); else PORTA |= (1<<dioda); } return 0; }

57