procesory sygnaŁowe - laboratorium Ćwiczenie nr 01
TRANSCRIPT
PROCESORY SYGNAŁOWE - LABORATORIUM
Ćwiczenie nr 01
Zajęcia wprowadzające, wprowadzenie do środowiska programistycznego
Code Composer Studio firmy Texas Instruments
1. Tworzenie nowego projektu w środowisku „Code Composer Studio”.
Każdy projekt programu w języku C składa się z wielu różnych rodzajów plików.
Najważniejsze z nich są pliki źródłowe języka C (pliki z rozszerzeniem *.c) i pliki
assemblera (pliki z rozszerzeniem *.asm). W plikach tych znajdują się definicje zmiennych
globalnych i funkcji realizujących program sterujący pracą procesora. Projekt musi zawierać
co najmniej jeden plik źródłowy, w którym znajduje się definicja funkjcji main(). Funkcja
definiuje punkt startowy programu w języku C.
Powiązania między plikami źródłowymi realizowane są poprzez pliki nagłówkowe (pliki z
rozszerzeniem *.h). W plikach nagłówkowych znajdują się deklaracje funkcji, zmiennych i
typów. Deklaracje funkcji określają nazwę funkcji, typ zwracanej wartości oraz liczbę i typy
argumentów. Deklaracje typów określają zwykle typy złożone takie jak struktury, tablice czy
wskaźniki. Deklaracje zmiennych globalnych umożliwiają dostęp do zmiennych globalnych
między modułami. W skład projektu wchodzą również pliki konfiguracyjne, które określają
parametry kompilacji i łączenia skompilowanych plików źródłowych. Ponadto zawierają
Rys. 1. Tworzenie nowego projektu – polecenie „ New CCS Project” z menu „Project”.
informację o tym, gdzie znajdują się pliki
nagłówkowe i biblioteki funkcji
dostarczonych przez Texas Instruments.
Pierwszym krokiem do wygenerowania
programu sterującego pracą procesora
TMS320C6713 jest stworzenie nowego
projektu. Należy wybrać polecenie „New
CCS Project” z menu „Project” (Rys. 1) .
Następnie w oknie nowego projektu
uzupełnić nazwę projektu i wybrać opcję
pustego projektu z plikiem źródłowym
main.c (Rys. 2). Opcje programowanego
urządzenia należy pozostawić bez zmian.
Podobnie typ wyniku budowania projektu
pozostaje „Executable”. Po naciśnięci
przycisku „Finish” nowy projekt pojawi
się w oknie głównym. W następnych
krokach można modyfikować i dodawać pliki (Rys. 3) (źródłowe, nagłówkowe) oraz
modyfikować konfiguracje kompilatora i linkera języka C (Rys. 4).
Rys. 3. Nowe pliki do projektu dodaje się wybierając polecenie „New” z menu „File”. Najczęściej
dodawane będą nowe pliki źródłowe języka C (*.c) lub assemblera (*.asm) oraz pliki nagłówkowe
języka C (*.h).
Rys. 2. Okno nowego projektu. W polu „Project
Name” wpisuje się nazwę projektu. W polu
„Project templates and examples” należy wybrać
„Empty Project (with main.c).
Pliki do projektu dodaje się korzystając z polecenia „New” z menu „File”. Po wybraniu
rodzaju pliku (źródłowy czy nagłówkowy) można podać jego nazwę wraz z rozszerzeniem.
Rys. 5. W zaawansowanych opcjach kompilatora języka C należy dodać definicję układu. Na
zajęciach właściwą wartością będzie „CHIP_6713”. Możemy ją wpisać w oknie edycyjnym
pojawiającym się po naciśnięciu plusa (na rysunku zaznaczony czerwonym kółkiem).
Rys. 4. Właściwości projektu (kompilatora i linkera języka C) są dostępne za pomocą polecenia
„Properties” z menu „Project”
Dodane pliki stają się natychmiast widoczne w panelu bocznym projektu i można rozpocząć
ich edycję.
Ustawienia konfiguracji kompilatora i linkera języka C można dokonać poprzez polecenie
„Properties” z menu „Project”. W oknie właściwości projektu należy dokonać modyfikacji
opcji kompilatora i linkera, jeżeli zamierzamy korzystać z biblioteki „Chip Support Library”
(CSL) dostarczonej przez Texas Instruments do programowania urządzeń zewnętrznych
procesora TMS320C6713. W opcjach kompilatora konieczne jest dodanie definicji symbolu
„CHIP_6713”, który pozwala na konfigurację dołączanych plików nagłówkowych (Rys. 5).
Natomiast w opcjach linkera należy dodać nazwę pliku biblioteki ”csl6713.lib” (Rys. 6), w
której znajdują się definicje funkcji biblioteki CSL. Po modyfikacji konfiguracji można
przystąpić do tworzenia programu, który będzie sterował procesorem.
2. Eksport i import projektu
Wszystkie oceniane zajęcia laboratoryjne będą rozpoczynały się od zaimportowania
projektu programu. Projekt ten będzie w trakcie zajęć modyfikowany, a następnie będzie
eksportowany do pliku archiwalnego. Natomiast plik archiwalny będzie można wysłać pocztą
elektroniczną i samodzielnie przeanalizować.
Rys. 6. W opcjach linkera języka C należy dodać bibliotekę „Chip Support Library”. W polu „File
Search Path” naciskamy znak plus (na rysunku zaznaczony czerwonym kółkiem) i wpisujemy
nazwę ”csl6713.lib”.
Żeby wykonać import pliku archiwalnego, należy wybrać polecenie „Import Existing CCS
Eclipse Project” z menu „Project” (Rys. 7).
W oknie importu (Rys. 8) należy wybrać
plik archiwalny (*.zip albo *.tar), który
zawiera pliki importowanego projektu. Po
wybraniu pliku archiwalnego w polu
„Discovered projects” widoczne będą
dostępne w archiwum projekty. Zaznaczamy
projekt, który będzie importowany i
naciskamy przycisk „Finish”.
Jeżeli wszystkie czynności zostały
wykonane prawidłowo, to zaimportowany
projekt stanie się widoczny w panelu
bocznym projektów. Można będzie
sprawdzić czy znajdują się w nim wszystkie
pliki i rozpocząć dalszą pracę z tym
projektem (edycja istniejących plików,
dodawanie nowych, zmiana ustawień parametrów kompilatora czy linkera języka C).
Rys. 7. Import projektu do „Code Composer Studio”. Należy wybrać polecenie „Import Existing
CCS Eclipse Project” z menu „Project”
Rys. 8. Wybór archiwum, z którego będzie
importowany projekt. Po wybraniu
importowanego archiwum naciskamy przycisk
„Finish”.
Żeby na koniec zajęć wyeksportować zmodyfikowany projekt, należy prawym przyciskiem
myszy kliknąć na nazwę projektu w panelu bocznym. Z menu kontekstowego (Rys. 9)
wybieramy polecenie „Export”. Następnie w pierwszym kroku wybieramy metodę eksportu,
którą w tym wypadku jest eksport do pliku archiwalnego. Jest to metoda, w której pliki
Rys. 10. Wybór metody eksportu. Najlepiej wybrać plik archiwum („Archive file”). W drugim
kroku wybór projektu, który ma zostać wyeksportowany. Można również modyfikować listę
eksportowanych plików.
Rys. 9. Eksport całego projektu „Code Composer Studio” do pliku archiwalnego. Po kliknięciu
prawym przyciskiem myszki na eksportowanym projekcie wybieramy polecenie „Export” z menu
kontekstowego.
źródłowe i konfiguracyjne projektu są kompresowane i dodawane do archiwum tar lub zip.
Projekt w takiej postaci można łatwo przesłać za pomocą poczty elektronicznej lub innego
medium. Archiwum może być zaimportowane przez środowisko „Code Composer Studio”
lub rozpakowane przez dowolny program obsługujący archiwizację zip lub tar.
W drugim kroku wybiera się projekt do eksportu. Można również zmodyfikować listę
eksportowanych plików. Po naciśnięci przycisku „Finish” wybrany projekt jest
archiwizowany w pliku o nazwie podanej przez użytkownika.
3. Skalowalna i efektywna implementacja maszyny stanów w języku C.
Jednym z podstawowych zadań układów mikroprocesorowych jest sterowanie rożnymi
procesami. Do układu dochodzą różnego rodzaju sygnały zewnętrzne. Zadaniem procesora
jest odpowiednia reakcja na takie bodźce. Najprostszym sposobem zakodowania takiej reakcji
jest struktura instrukcji warunkowych, w których warunki zależą od stanu rejestrów urządzeń
wejścia/wyjścia i aktualnych wartości zmiennych. Złożone problemy sterowania sprawiają
jednak, że taka struktura może stać się niezwykle złożona i nieczytelna dla programisty.
Ponadto mnogość instrukcji warunkowych sprawia, że program działa wolniej (wiele
warunków do sprawdzenia zanim nastąpi reakcja).
Rozwiązaniem opisanego tu problemu jest implementacja skalowalnej i efektywnej
maszyny stanów. Taka implementacja opiera się na wskaźnikach funkcyjnych, a jej podstawą
jest typ strukturalny definiujący stan maszyny.
typedef struct _STATE { struct _STATE (*fun)();} STATE;
Maszynę określa zmienna strukturalna typu STATE, która w pętli programowej będzie
modyfikowana przez funkcje przejścia zwracające w wyniku wartość typu STATE.
Struktura zawiera tylko jedno pole, które jest wskaźnikiem na funkcję zwracającą strukturę
STATE. Zadaniem funkcji przejścia jest sprawdzanie warunku przejścia z bieżącego stanu do
stanu następnego.
Przykład kodu w którym zrealizowany jest prosty detektor ciągu znaków „123”, w ciągu
znaków odczytywanych z jakiegoś urządzenia za pomocą funkcji read().
Przykład:
typedef struct _STATE { struct _STATE (*fun)();} STATE;
#define CONDITION1 (read()==’1’)
#define CONDITION2 (read()==’2’)
#define CONDITION3 (read()==’3’)
STATE wait();
STATE state1();
STATE state2();
void state_machine()
{
STATE state={wait};
while(1) state=(state.fun());
}
STATE wait()
{
STATE ret;
if(CONDITION1)
ret.fun=state1;
else
ret.fun=wait;
return ret;
}
STATE state1()
{
STATE ret;
if(CONDITION2)
ret.fun=state2;
else
ret.fun=wait;
return ret;
}
STATE state2()
{
STATE ret;
if(CONDITION3)
{
signal();
ret.fun=wait;
}
else
ret.fun=wait;
return ret;
}
Fakt osiągnięcia sukcesu jest sygnalizowany poprzez wykonanie funkcji signal ().
W definicji tej funkcji może być kod
sygnalizujący detekcję diodami lub
wywołujący określoną sekwencję sygnałów
wyjściowych.
Zaletą tego rozwiązania jest to, że
niezwykle łatwo prześledzić działanie takiej
maszyny stanów. Przejście z danego stanu
do kolejnego odbywa się tylko w funkcji,
która te przejścia realizuje. Model maszyny Rys. 12. Diagram stanów maszyny
realizowanej przez przykładową funkcję
state_machine().
łatwo jest przedstawić graficznie i analizować jego poprawność. Jest to narzędzie bardzo
użyteczne w trakcie implementacji złożonych protokołów komunikacyjnych, dla których
maszyny stanów są jedną z najlepszych form opisujących działanie odbiornika i nadajnika.
Stosując tę technikę, implementacja danej maszyny jest prawie automatyczna.
4. Uruchamiania programu, usuwanie usterek i praca krokowa w środowisku „Code
Composer Studio”.
Aby uruchomić program znajdujący się w aktywnym projekcie Code Composer Studio,
należy wybrać polecenie „Debug” z menu „Run” (patrz Rys. 13). Można również użyć
klawisza funkcyjnego „F11”. Wówczas projekt jest budowany, wgrywany do pamięci
procesora DSP i czeka na uruchomienie.
W trybie „Debug” środowisko udostępnia dodatkowe opcje w menu „Run” (patrz. Rys.
14). Polecenie „Terminate” z tego menu powoduje zamknięcie trybu „Debug”. Polecenie
„Resume” umożliwia uruchomienie programu z obsługą pułapek. Można zatrzymać program
używając polecenia „Suspend”, które pojawia się w miejsce polecenia „Resume”, gdy
program jest uruchomiony. Podobnie jak w innych środowiskach programistycznych możliwe
jest wykonywanie programu krok po kroku z rozwijaniem i bez rozwijania funkcji. W trakcie
pracy krokowej możemy podglądać stan zmiennych lokalnych (Rys. 14f), wyrażeń
wykorzystujących zmienne lokalne i globalne (Rys. 14g) i rejestrów (Rys. 14h). Istnieje
możliwość dodawania pułapek programowych, na których program zatrzyma swoje działanie.
Aby dodać taką pułapkę, wystarczy kliknąć dwa razy myszką na numer linii, w której chcemy
Rys. 13. Uruchomienie programu i usuwanie usterek – polecenie „Debug” z menu „Run”
wstawić pułapkę. Pułapka jest wtedy widoczna w zakładce pułapek (Rys.14i) i może być
usunięta lub edytowana.
5. Cel ćwiczenia i opis zadania do wykonania
Celem zajęć laboratoryjnych będzie uruchomienie, modyfikacja i kontrola poprawności
działania programu realizującego maszynę stanów odbiornika wiadomości tekstowych.
Maszyna stanów będzie odczytywała wiadomości z wykorzystaniem funkcji read(). Funkcja
ta jest specjalnie przygotowaną atrapą, której zadaniem jest symulacja danych pochodzących
z rzeczywistego urządzenia. Tego typu rozwiązania stosuje się w modnej współcześnie
technice tworzenia oprogramowania o nazwie Test Driven Development (TDD). Maszyna
stanów wykorzystuje funkcję read() do odczytania znaków (wartości typu char). Odczytana
sekwencja znaków spełnia zasady protokołu komunikacyjnego, którego specyfikacja jest
podana poniżej:
1. Wiadomość składa się z dowolnego ciągu znaków
2. Początek ramki danych rozpoczyna się znakiem ‘1’
3. Koniec ramki danych jest sygnalizowany znakiem ‘0’
4. Jeżeli w ciągu wczytywanych danych pojawi się znak ‘1’ lub ‘0’, to musi on zostać
poprzedzony znakiem ‘\’.
Rys. 14. Podstawowe możliwości i polecenia trybu „Debug”: (a) uruchomienie programu lub
zatrzymanie jego działania, (b) wyjście z trybu „Debug”, (c) praca krokowa z rozwijaniem funkcji,
(d) praca krokowa bez rozwijania funkcji, (e) praca krokowa wyjście poziom wyżej z funkcji, (f)
zakładka z możliwością podglądu zmiennych lokalnych funkcji, (g) zakładka, w której można
wpisywać wyrażenia z użyciem zmiennym globalnych i lokalnych dostępnych na danym poziomie
programu, (h) zakładka do podglądu zawartości rejestrów procesora, (i) zakładka do obsługi
pułapek programowych (breakpoints).
5. Jeżeli znak ‘\’ stanowi daną do przesłania, to musi zostać powtórzony.
6. Jeżeli w trakcie odbierania danych pojawi się znak początku ramki, to dotychczas
odbierane dane są pomijane i odbiór ramki rozpoczyna się od początku
Poprawnie odczytane wiadomości powinny zostać przekazane do funkcji write(), która
zapisze je do specjalnego bufora wyjściowego, którego zawartość można podglądać, z
wykorzystaniem narzędzi diagnostycznych środowiska programistycznego.
Poniżej pokazano przykłady poprawnych wiadomości:
„1Ala ma kota0”, „1Mam \0 lat0”,”1Zajalem \1 miejsce w zawodach0”, „1TAK\\NIE0”.
Maszyna stanów odbiór każdej wiadomości sygnalizuje diodami LED za pomocą
makrodefinicji LED(). Argument makrodefinicji jest liczbą, która w kodzie binarnym
wskazuje, która z diod ma zostać zapalona (0xf- wszystkie diody świecą, 0x1 pierwsza dioda
świeci,0x3 dwie pierwsze diody świecą).
Na stronie internetowej laboratorium udostępniany jest projekt programu realizujący
podstawową wersję maszyny stanów odbiornika wiadomości zgodnych z przedstawionym
protokołem komunikacyjnym. W czasie zajęć należy na podstawie programu StateMachine
narysować diagram stanów. Następnie zaproponować diagram stanów dla maszyny, która
będzie odporna na pakiety o długości powyżej 16 znaków (nie licząc znaków początku i
końca ramki oraz znaku ‘\’).
W kolejnym kroku należy taką maszynę zaimplementować, korzystając z techniki
omówionej w rozdziale 3. Po modyfikacji programu należy wykorzystać możliwości
środowiska programistycznego w zakresie wsparcia usuwania usterek oprogramowania (praca
krokowa, podgląd stanu zmiennych, tablic itp.) do przetestowania nowego rozwiązania.
Deklaracje i definicje funkcji, opis parametrów i zwracanych wartości znajduje się w formie
komentarzy w projekcie StateMachine dostępnym na stronie laboratorium.