Język C dla AVR
Transkrypt
Język C dla AVR
Język C dla mikroprocesorów AVR Wykład 6 Techniki mikroprocesorowe Programowanie AVR Narzędzia 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 Techniki mikroprocesorowe Atmel Studio 6 • Środowisko wspiera kilka typów programatorów oraz mechanizmy ułatwiające debugowanie http://www.atmel.com/microsite/atmel_studi o6/ 9 Techniki mikroprocesorowe Atmel Studio 6 10 Techniki mikroprocesorowe Przygotowanie projektu Przygotowanie projektu WinAVR + PN2 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 Techniki mikroprocesorowe Język C dla AVR 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 unsigned char signed int unsigned int signed long int unsigned long int signed long long int unsigned long long int int8_t uint8_t int16_t uint16_t int32_t uint32_t int64_t 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 Techniki mikroprocesorowe 36 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 Techniki mikroprocesorowe Optymalizacja kodu 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 Techniki mikroprocesorowe Przykład Przykład prostego programu 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 Techniki mikroprocesorowe