Autor: tmf
Redakcja: Dondu
JTAG dziadka |
Oczywiście można spotkać się z opiniami, że mój dziadek nie używał JTAGa i żył, ja też nie używam i żyję, więc po co mi to?
No cóż, nasi dziadkowie nie mieli też samochodów, a ich dziadkowie używali lamp naftowych. Tak się też oczywiście da, więc jeśli interesuje cię życie jaskiniowca mikrokontrolerowego, to lepiej dalej nie czytaj.
Do rzeczy ...
Interfejs JTAG umożliwia zarówno programowanie procesorów, jak i debugowanie zawartego w nich kodu, a także połączeń elektrycznych mikrokontrolera z resztą układu. Widzimy więc, że możliwości tego interfejsu są spore przez co zajmuje on drugie miejsce na liście najważniejszych kryteriów wyboru mikrokontrolerów przez producentów urządzeń. Warto więc się mu przyjrzeć bliżej.
Musimy pamiętać, że nie wszystkie mikrokontrolery AVR posiadają interfejs JTAG – posiadają go tylko „większe” mikrokontrolery ATMEGA (ATMega16, 32, 64, 128 etc.) oraz mikrokontrolery XMEGA. Te ostatnie posiadają także interfejs PDI udostępniający podobne funkcjonalności.
Inne posiadają interfejs ISP, małe ATTiny posiadają interfejs TPI, a nowsze, w tym XMEGA dodatkowo interfejs PDI, także umożliwiający debugowanie układów.
Po co więc interfejs, który nie występuje we wszystkich mikrokontrolerach?
Przede wszystkim programatory posiadające interfejs JTAG (AVR Dragon, JTAGICE, JTAGICE MkII, JTAGICEIII) są wyposażone w kilka interfejsów – obsługują zarówno JTAG, jak i PDI, ISP, itd. W efekcie przy pomocy takiego programatora możemy programować wszystkie mikrokontrolery, lecz oczywiście nie wszystkie będziemy mogli debugować (debugować można wyłącznie poprzez interfejs JTAG lub PDI).
Drugim powodem jest sposób w jaki możemy tworzyć aplikacje. Nawet tworząc aplikację na ATMega8, która nie posiada JTAG, nic nie stoi na przeszkodzie, aby wykorzystać płytę rozwojową z ATMega128 i potem przenieść gotowy i sprawdzony kod na ATMega8. Takie postępowanie jest nawet łatwiejsze w przypadku rodziny XMEGA – ze względu na zgodność nazw rejestrów i budowę układów peryferyjnych. Dzięki temu piszemy sobie wygodnie program, na „dużym” mikrokontrolerze, debugujemy go, a po zakończeniu prac po prostu rekompilujemy na urządzenie docelowe. Nawet jeśli w efekcie będziemy musieli wprowadzić jakieś poprawki do kodu, to jego pisanie będzie znacznie ułatwione, dzięki możliwości debugowania kodu.
Interfejs
Sam interfejs elektryczny JTAG jest niezwykle prosty. Składa się on zaledwie z kilku sygnałów (z których nie wszystkie są potrzebne):- TDI (ang. Test Data In) – wejście danych,
- TDO (ang. Test Data Out) – wyjście danych,
- TCK (ang. Test Clock) – wejście sygnału zegarowego,
- TMS (ang. Test Mode Select) – wybór trybu pracy,
- TRST (ang. Test Reset) – zerowanie (opcjonalne).
Oprócz tego istnieje kilka innych sygnałów, które należy podłączyć. Widok gniazda JTAG pokazuje poniższy rysunek:
Złącze JTAG |
Oczywiście obowiązkowo należy połączyć masy programowanego układu i programatora (sygnały GND). Podłączenie Vcc jest opcjonalne, umożliwia ono zasilanie programowanego układu z programatora. Zazwyczaj programator ma w tym celu dodatkową zworkę, należy jednak pamiętać, że wydajność prądowa programatora jest niewielka i zwykle ograniczona do 200-300 mA. Należy bezwzględnie pamiętać o podłączeniu pinu nazwanego VREF. Co to takiego? Jest to pin umożliwiający programatorowi określenie napięcia z jakim pracuje programowany układ. Z tego pinu zasilane są bufory wyjściowe programatora, zapewniające konwersję poziomów logicznych – zwykle programator potrafi pracować z urządzeniami zasilanymi napięciami w zakresie 1,6-5 V. W układzie VREF należy podłączyć do Vcc – napięcia zasilającego debuggowany procesor.
Pozostałe sygnały (TMD, TDO, TDI, TCK) należy połączyć z odpowiednimi pinami procesora (o tych samych nazwach), opcjonalnie należy podłączyć także sygnał NSRST do pinu RESET mikrokontrolera – połączenie to nie jest konieczne, ale zalecane.
Pamiętaj, że jeśli mikrokontroler posiada JTAG, to jest on sprzedawany z odblokowanym interfejsem. Ponieważ JTAG przejmuje kontrolę nad odpowiednimi pinami IO procesora, program nie może zmienić ich stanu i ich kontrolować do czasu zablokowania interfejsu JTAG (za pomocą odpowiedniego fusebitu lub rejestru IO).
Dla rodziny ATMega JTAG zajmuje zwykle część pinów portu C mikrokontrolera – jeśli ci one nie działają to przyczyną jest właśnie domyślnie odblokowany JTAG. Więcej na ten temat przeczytasz w artykule: Pułapki AVR: JTAG blokuje piny portu
Dla rodziny ATMega JTAG zajmuje zwykle część pinów portu C mikrokontrolera – jeśli ci one nie działają to przyczyną jest właśnie domyślnie odblokowany JTAG. Więcej na ten temat przeczytasz w artykule: Pułapki AVR: JTAG blokuje piny portu
I to wszystko – jak widzimy sama wtyczka JTAG jest 10-pinowa, analogicznie jak stara wtyczka ISP, stąd też nie zajmuje ona więcej miejsca na PCB niż zwykłe gniazdo ISP.
Daisy chain
JTAG ma jeszcze jedną zaletę, o której często się zapomina. Pisałem o tym w swojej książce „Język C dla mikrokontrolerów AVR. Od podstaw do zaawansowanych aplikacji” więc tu tylko krótko o tym. Interfejs JTAG umożliwia łączenie szeregowe układów posiadających taki interfejs.Jeśli więc w budowanym systemie mamy np. dwa mikrokontrolery z interfejsem JTAG, do tego pamięć z takim interfejsem lub inny układ, to nie musimy wyprowadzać kilku złącz JTAG. Po prostu łączymy je szeregowo, w ten sposób, że sygnał TDO doprowadzamy do wejścia TDI kolejnego układu itd.
W ten sposób tworzymy łańcuszek układów. Pozostałe sygnały prowadzimy równolegle (TMS, TCK). Dzięki temu przy pomocy jednego złącza mamy dostęp do wszystkich układów na płytce. Wystarczy tylko znać ich względne położenie w łańcuchu.
Programowanie z użyciem JTAG
Pierwszą rzeczą do której wykorzystamy JTAG jest programowanie układu docelowego. Tu malkontenci mogą powiedzieć, po co – mogę sobie zaprogramować przy pomocy ukochanego USBAsp. Prawda, mogą :-)Jednak programowanie przy pomocy JTAG ma parę zalet:
- jest szybsze. Zdecydowanie szybsze niż przy pomocy USBasp, ale także ogólnie szybsze niż w trybie ISP. Dla procesorów posiadających niewiele pamięci różnice są bez znaczenia, ale dla procesorów posiadających 64-256 kB FLASH różnice mogą sięgać minut!
- w trybie JTAG da się programować mikrokontroler także z niewłaściwie ustawionymi fusebitami (znany problem „zablokowałem mikrokontroler”). Ponieważ JTAG używa sygnału TCK do taktowania układów wewnątrz mikrokontrolera, konfiguracja zegara wybrana przy pomocy fusebitów jest bez znaczenia. W ten sposób można sobie odblokować zablokowany mikrokontroler. Oczywiście wybierając rodzinę XMEGA raz na zawsze rozwiązujemy problem zablokowanego procesora – w tej rodzinie źródło zegara wybiera się programowo.
Programowanie z wykorzystaniem JTAG wygląda praktycznie tak samo, jak z wykorzystaniem ISP, czy PDI:
Programowanie za pomocą pliku elf |
Warto zwrócić uwagę, że programuję MCU z użyciem pliku elf a nie HEX (nie trzeba generować plików hex i eep co skraca czas kompilacji). Oczywiście mamy również możliwość zmiany z poziomu Atmel Studio fusebitów i innych parametrów mikrokontrolera.
Jeśli korzystamy z trybu daisy chain to należy wcześniej skonfigurować narzędzie:
Konfiguracja Daisy chain |
Na powyższym przykładzie nasz mikrokontroler jest podłączony jako drugie urządzenie w łańcuchu, a po nim są kolejne dwa urządzenia. Jednak w większości przypadków, szczególnie w warunkach amatorskich takiej konfiguracji nie wykorzystujemy, stąd też nie ma potrzeby konfigurowania interfejsu – wystarczy zaznaczenie domyślnej opcji „Target device in not part of a JTAG daisy chain”.
Debugowanie programu
Największe zalety JTAGa ujawniają się w czasie debugowania programu. Ponieważ sam temat debugowania jest szeroki i być może omówimy go w kolejnych artykułach (jeśli będzie takie zapotrzebowanie) tu pokażę tylko kilka marchewek. Co nam daje debugger sprzętowy? Oto jego krótkie możliwości:- zakładanie pułapek – po natrafieniu na nie program zostanie przerwany (ale możliwe jest wznowienie jego pracy),
- podgląd wartości zmiennych w programie oraz rejestrów mikrokontrolera,
- podgląd zawartości pamięci FLASH, EEPROM i SRAM mikrokontrolera,
- modyfikacja zmiennych i pamięci, a następnie wznowienie pracy programu z nowymi wartościami,
- możliwość wykonywania krokowego programu – w tym trybie wykonywane są pojedyncze instrukcje programu (instrukcje języka C lub asemblera),
- możemy także wykonywać całe bloki instrukcji, np. funkcje, po wykonaniu, których program jest wstrzymywany i możemy przeanalizować jakie zaszły zmiany.
Zobaczmy jak to wygląda na prostym przykładzie. Na poniższym rysunku pokazałem fragment programu, na którym wykonanie zostało wstrzymane. Instrukcja, na której program został wstrzymany zaznaczona jest żółtą linią:
Debug |
Jak widzimy program zatrzymał się na instrukcji for. W trakcie wstrzymania jego wykonania w okienku Locals można podglądnąć wartość lokalnych zmiennych w programie, w pokazanym przykładzie zmiennych tmpmenuitem, bmp_height, bmp_width itd.
Oczywiście możemy nie tylko podglądać te zmienne, ale jeśli chcemy możemy w każdej chwili ich wartość zmienić – umożliwia to łatwe przetestowanie fragmentu kodu dla zadanych wartości początkowych. Kolejne instrukcje możemy wykonywać pojedynczo naciskając klawisz F11.
Jeśli natrafimy na funkcję to automatycznie „wskoczymy” w jej ciało, dzięki temu będziemy mogli prześledzić jej wykonanie. Jeśli taka możliwość nas nie interesuje możemy od razu wykonać całą funkcję (np. na naszym przykładzie funkcją jest Menu_GetMenuRows()) naciskając klawisz F10.
Możemy też wykonać program do instrukcji oznaczonej przez bieżącą pozycję kursora naciskając Ctrl+F10. Opcje te są także dostępne w Atmel Studio w menu Debug. W każdej chwili możemy wznowić działanie programu naciskając F5. W takiej sytuacji program będzie normalnie wykonywany aż do chwili, kiedy go nie przerwiemy (Ctrl+F5) lub nie natrafi on na pułapkę (breakpoint).
No właśnie, a jak wygląda zastawianie pułapek? Nic prostszego, wystarczy na interesującej nas linii programu nacisnąć klawisz F9 (Debug/Toggle Breakpoint) i już. Jeśli procesor wykonując program natrafi na pułapkę, zawiesi swoje działanie, a Atmel Studio pokaże nam jego stan w chwili natrafienia na zastawioną pułapkę. Widzimy to na kolejnym zrzucie:
Breakpoint |
Pułapka została zastawiona na linii uint8_t no=Menu_GetMenuItemsNo(); Wykonanie programu zostało przerwane a my możemy sobie sprawdzić co się w programie dzieje, analizując zawartość zmiennych. Akurat debuggowana funkcja jest odpowiedzialna za przeskok do kolejnej pozycji menu, przed jej wykonaniem postanowiłem sprawdzić wartość zmiennych menuindex i no – określających numer pozycji menu i liczbę pozycji. Oczywiście możemy łatwo sprawdzić dowolną zmienną, wpisując ją w oknie Watch – jedyny warunek – zmienna ta musi być w zasięgu widoczności bieżącego fragmentu kodu. Tu reguły widoczności są identyczne jak w języku C – jeśli dana zmienna jest widoczna w danym fragmencie kodu, to możemy jej zawartość podglądnąć.
Od tej reguły istnieją wyjątki związane z faktem, że kompilator mocno optymalizuje kod, usuwając niepotrzebne zmienne. Takich zoptymalizowanych zmiennych, ponieważ nie istnieją w kodzie wynikowym, nie możemy podglądać.
Ktoś powie – ok, fajnie, ale przecież w innym artykule pokazaliście, że to samo można osiągnąć stosując symulator w Atmel Studio. To prawda, posługiwanie się debuggerem sprzętowym daje mniej więcej takie same możliwości jak symulacja. Jak zwykle różnice tkwią w szczegółach.
Musimy pamiętać, że symulator symuluje wyłącznie działanie procesora, natomiast w rzeczywistym układzie stan procesora zależy nie tylko od programu, ale także od jego otoczenia – pozostałych układów elektronicznych znajdujących się na płytce. Symulator oczywiście ich bezpośrednio nie symuluje (ale można tego typu funkcjonalność w pewnym stopniu do niego dodać), natomiast debugger sprzętowy umożliwia śledzenie pracy programu w rzeczywistym układzie. W efekcie te dwie metody debuggowania doskonale się uzupełniają. Ale to nie wszystko. Popatrzmy na kolejny zrzut ekranu:
IO View |
Co na nim widzimy? Przede wszystkim kod asemblerowy pokazanego wcześniej programu. Dzięki temu możemy podglądając wykonanie programu i zobaczyć w jaki sposób kompilator przetłumaczył kod C na asembler oraz możemy wykonywać kolejne instrukcje asemblera. Ze względu na działanie optymalizatora czasami kod C jest przez kompilator bardzo modyfikowany, co utrudnia jego śledzenie. Stąd też przejście do okna disassemblera znacznie ułatwia śledzenie kodu i czasami jest wygodniejsze niż śledzenie kodu w oknie kodu C. Ale nie to jest tu najważniejsze.
Spójrzmy na prawą stronę naszego zrzutu, do okna zatytułowanego IO View. I tu właśnie widać całą potęgę debuggera sprzętowego. Na bieżąco mamy podgląd na wszystkie układy peryferyjne procesora i ich rejestry! Dla przykładu na zrzucie pokazano stan rejestrów układu USARTD) – po rozwinięciu odpowiedniej pozycji możemy uzyskać skrócony, szybki podgląd na stan tego układu peryferyjnego (łącznie z opisem słownym pól konfiguracyjnych):
Widok IO |
Poniżej mamy pokazany stan każdego z jego rejestrów oraz poszczególnych bitów konfiguracyjnych. Jeśli więc konfigurujesz jakiś układ peryferyjny i chcesz sprawdzić czy napisany kod robi to poprawnie (uzyskujesz zamierzony efekt) to wystarczy podglądnąć jego rejestry po wykonaniu kodu odpowiedzialnego za jego konfigurację.
W tym zakresie debugger sprzętowy umożliwia nam uzyskanie tego samego co symulator. Lecz jak zwykle jest różnica. Dla układów peryferyjnych będących wyjściami procesora generalnie w symulatorze uzyskamy to samo. Lecz jeśli jakiś układ zależy od sygnałów doprowadzonych do procesora?
Oczywiście w takiej sytuacji stan układu peryferyjnego nie da się w pełni zasymulować. Przykładem może być rejestr wejściowy portu IO – bity tego rejestru zależą od stanu panującego na wejściach procesora, a nie bezpośrednio od kodu programu! I tu zbliżamy się do kolejnej wspaniałej cechy debuggera sprzętowego…
Debugowanie połączeń elektrycznych na PCB
Tak samo jak w przypadku zmiennych możemy nie tylko podglądać stan rejestrów IO procesora, ale także możemy ich wartość zmieniać. W ten sposób w trakcie działania programu możemy zmieniać konfigurację układów peryferyjnych! A co jeśli zmiana konfiguracji wpłynie na stan wyjść procesora? Tak będzie np. jeśli zmienimy stan rejestru wyjściowego portu – zmiana jego stanu natychmiast wpłynie na poziom logiczny panujący na odpowiednim pinie IO! I to jest właśnie kolejna fantastyczna cecha debuggera sprzętowego.Lutując układy, szczególnie o gęstszym rastrze nie sposób nie popełnić błędów – np. podczas lutowania możemy doprowadzić do przypadkowego połączenia sąsiednich pinów:
Zwarcie między pinami |
Czasami tego typu błędy są łatwe do wykrycia, lecz często odstępy pomiędzy pinami są mniejsze niż 0,5 mm – nie zawsze takie mostki cynowe znajdziemy. Co więcej trawiąc płytki w domu (ale także jeśli je zamawiamy) może się zdarzyć sytuacja w której dochodzi do nieprawidłowego połączenia sąsiednich ścieżek, lub wręcz odwrotnie, w wyniku podtrawienia dochodzi do przerwania ciągłości ścieżki:
PCB - Uszkodzona ścieżka |
No i chyba najczęstsza sytuacja – tzw. zimny lut. Pozornie wszystko jest ok, jednak zła spoina nie zapewnia połączenia elektrycznego. Poszukiwanie tego typu błędów bywa naprawdę uciążliwe. Czy JTAG może nam w tym pomóc? Zazwyczaj tak. Dlaczego? Jak pamiętamy możemy z poziomu Atmel Studio debugując program zmieniać stan układów peryferyjnych, w tym rejestrów portów IO – w efekcie możemy łatwo klikając myszką zmieniać stan wszystkich wyjść IO procesora.
W efekcie, jeśli podejrzewamy zwarcie dwóch pinów IO to wystarczy zmienić stan jednego i sprawdzić czy jednocześnie nie zmienił się stan drugiego (oczywiście musimy go wcześniej skonfigurować jako wejście – np. klikając myszą na odpowiednie bity rejestru DIR). Możemy też wymusić stan pinu IO a następnie miernikiem sprawdzić czy stosowne napięcie panuje na wejściu układu, którym przy pomocy danego pinu sterujemy. W ten sposób możemy naprawdę szybko znaleźć nieprawidłowe połączenia.
Technika ta jest wygodna jeszcze w jednej sytuacji. Wyobraźmy sobie, że łączymy z MCU np. wyświetlacz LCD. Nawet popularny wyświetlacz alfanumeryczny wymaga w tym celu 6-7 połączeń, co więcej odpowiednie piny IO procesora musimy doprowadzić do odpowiednich wejść LCD. O pomyłkę nietrudno, wystarczy pomylić dwa przewody i już nasz układ nie działa. Początkujący (chociaż nie tylko początkujący) elektronicy zarzekają się, że 100-razy sprawdzili poprawność połączeń, a układ nie działa. Magia? Być może… lecz tu z pomocą ponownie może nam przyjść JTAG/PDI. Wystarczy zmienić stan kolejnych pinów IO i sprawdzić, czy stan spodziewanych wejść LCD również ulega zmianie. W ten sposób szybko zidentyfikujemy problem.
Prawdy i mity – czyli JTAG jest drogi
Mam nadzieję, że udało mi się pokazać istotne zalety JTAG/PDI, pozostaje jeszcze drażliwa kwestia – ceny. Na grupach zwykle przeciwnicy debuggerów sprzętowych piszą, że cena JTAGa jest wysoka i jest on w związku z tym niedostępny dla hobbystów.Nic bardziej błędnego. Tego typu programatory/debuggery można kupić już za kilkanaście złotych. Oczywiście w tej cenie nie dostaniemy nic rewelacyjnego – możemy kupić (lub sami zbudować) debugger JTAGICE współpracujący wyłącznie z AVR Studio 4.19 i wcześniejszymi, umożliwiający debuggowanie w układzie procesorów ATMega. Nie jest to wiele, lecz dla osób zajmujących się wyłącznie starszymi AVRami ciągle jest to atrakcyjna propozycja.
A co z osobami doceniającymi zalety Atmel Studio lub pracującymi z XMEGA? Tu niestety musimy wydać nieco więcej. Naprawdę świetnym programatorem/Debuggerem jest AVR Dragon – jego cena to ok. 240-250 zł. Nie jest to mało, ale jest on wart każdej wydanej złotówki – umożliwia on programowanie wszystkich układów AVR, w tym AVR32 przez wszystkie możliwe interfejsy, oraz… oczywiście sprzętowe debuggowanie układów, które mają taką możliwość.
Czy jest to dużo? Z pewnością jest to istotna pozycja w budżecie, lecz wydatek naprawdę szybko się zwraca i z całą odpowiedzialnością mogę ten debugger polecić. Osoby posiadające większą gotówkę mogą zakupić JTAGICE3 (nie wnosi on w stosunku do Dragonia praktycznie nic poza plastikową obudową), a dla fascynatów JTAGICE MkII, którego cena moim zdaniem jest mocno przesadzona.
Oczywiście zawsze możemy zapolować na okazje i ewentualnie spróbować zdobyć te układy po naprawdę dobrych cenach na różnych szkoleniach organizowanych przez firmę Atmel. Niestety Polska jest traktowana sieroco (wina Atmela, czy dystrybutora na Polskę, który się nie stara?), więc na dobre okazje możemy zapolować u naszych zachodnich sąsiadów :-)
Opis koncentruje się głównie na JTAG dla AVRów, co nie pokazuje wszystkich zalet interfejsu.
OdpowiedzUsuńOpis dość fajny, jednak na wstępie ująłbym ogólny opis JTAGa, a nie czym jest dla rodziny procesorów AVR. Dlaczego?
OdpowiedzUsuń1. JTAG to NIE jest standard Atmelowski, ale globalny standard używany w wielu innych rodzinach procesorów, układach FPGA i innych, niekoniecznie programowalnych układach. Daje to nam niesamowite możliwości debugowania całego wielkiego urządzenia zawierającego kilka(naście) układów za pomocą jednego interfejsu.
2. Opisałbym jak działa sam JTAG, jak wpływa on na piny mikrokontrolera, jego pamięć, dlaczego pozwala debugować, dlaczego JTAG może się nawet pojawić w układach nieprogramowalnych i do czego by wtedy służył i dlaczego łączenie kilku urządzeń w daisy chain JTAGiem jest i wadą i zaletą (prędkość magistrali jest ograniczona, im więcej mamy na niej urządzeń tym wolniej możemy odpytywać jedno konkretne, bo wszystko przechodzi przez wszystkie urządzenia).
3. Również przydałoby się nadmienić, że nie musimy wcale używać interfejsów JTAG (programator to chyba trochę zła nazwa, debugger też... to jest bardziej połączenie jednego i drugiego + dopchanie kilku rzeczy) firmy Atmel, możemy użyć również innych, bo każdy JTAG wygląda tak samo. Również te od Atmela możemy użyć z innymi układami.
To są rzeczy, które dużo bardziej zachęcają do używania JTAGa.
Odpowiem od razu na dwa powyższe komentarze, bo są zbieżne. Oczywiście JTAG nie dotyczy tylko mikrokontrolerów Atmela, ani w ogóle mikrokontrolerów. Niemniej jesteśmy na blogu poświęconemu AVRom, stąd też w tym kontekście JTAG nas interesuje. Jeśli kolega chce się podzielić innymi zastosowaniami, czy wnikać w działanie JTAGa to Dondu zapewne chętnie opublikuje stosowny artykuł.
OdpowiedzUsuńJakkolwiek sam intefejs JTAG jest standardem, to niestety nie oznacza to, że programatory/debuggery Atmela z JTAG możemy wykorzystać z innymi układami, lub też inne interfejsy JTAG z mikrokontrolerami Atmela. W pierwszym przypadku przeszkodą jest fakt, że interfejsy te mają swoje mikrokontrolery i oprogramowanie realizujące z jednej strony połączenie z debuggowanym mikrokontrolerem, a z drugiej udostępniające zastrzeżone API dla programów typu Atmel Studio. Tak więc nie będą one "rozumiały" innych układów niż wspierane układy Atmela i nie będą się dały prosto połączyć z "obcym" frontendem na PC. Z drugiej strony inne JTAGi z mikrokontrolerami Atmela też nie do końca będą działać, bo co prawda sam JTAG jest standardowy, lecz każdy producent ma możliwość wprowadzania dodatkowych poleceń i zwykle z niej korzysta. W efekcie korzystając z "obcych" JTAGów nie uzyskamy pełnej funkcjonalności jaką mają oryginalne JTAGi Atmela. Zresztą dla innych producentów sytuacja jest podobna. No i też pojawia się problem frontendu, który musi znać układ z którym się łączymy, żeby zinterpretować uzyskane dane. W przeciwnym przypadku uzyskamy tylko nic nie mówiące ciągi bajtów.
Brakuje mi tu wzmianki o boundary scanie :)
UsuńNa około chyba zostało to wspomniane - przy okazji testowania połączeń elektrycznych. Tu też artykuł z EP: http://ep.com.pl/files/2277.pdf
UsuńLiterówka się wkradła
OdpowiedzUsuń"Dzięki temu piszemy sobie wygodnie program, a „dużym” mikrokontrolerze,"
Dziękuję - poprawione :-)
UsuńCzy jest gdzieś cykl o debugowaniu? Przeszukałem ale coś nie potrafię znaleźć.
OdpowiedzUsuńNiestety na razie nie ma takiego artykułu.
UsuńCześć. Mam pytanie odnośnie odczytywania stanów I/O w trybie debugowania.
OdpowiedzUsuńKorzystam z Atmel ICE i Atmel Studio v. 6.2, na płytce stykowej mam Atmegę32A z minimalnym podłączeniem pinów - nic więcej. Kiedy wchodzę w tryb debugowania i w oknie I/O view ręcznie ustawiam bit DDRA.0 a następnie PORTA.0, w rejestrze PINA pojawia mi się wartość 0x03. Czasem zdarzało mi się, że dostawałem wartość 0x07, jakby było zwarcie między pinami portu A. Oczywiście sprawdziłem to i nie ma to miejsca. Z resztą sytuacja ma się podobnie gdy zrobię taki eksperyment na porcie B. Próbowałem odświeżać widok przez "Refresh values" ale nie pomogło. Wystarczy, że wykonam 2-3 "nop'y" i w I/O view widzę faktyczny stan wyprowadzeń. Nie jestem w stanie sam znaleźć przyczyny a nie chce mi się wierzyć, że po prostu tak kulawo to działa... szczególnie, że wujek google na ten temat milczy.
Jest ktoś w stanie mi pomóc? Z góry dziękuję za podpowiedzi.
Jeśli zostawiasz niepodłączone piny wejściowe to zbierają one śmieci. Wymuś na nich określony stan logiczny z problem zniknie. Druga sprawa to synchronizator na wejściu portu - żeby zobaczyć stan pinu sygnał musi przejść przez synchronizator, co zajmuje ok. 1,5 taktu zegara.
UsuńBardzo dziękuję za odpowiedź. Faktycznie całe zamieszanie było spowodowane tym, że wejścia sobie "wisiały". Zupełnie się nie spodziewałem, że niczym nienieobiążone mogą aż tak siać. Ale ze mnie osiołek :/ Pozdrawiam!
UsuńOczywiście miałem na myśli niczym nieobciążone wyjścia ;)
UsuńCześć. Używam AS6.2.1563 SP2 i AS7.0.943, posiadam również programator JTAGICE3 i płytę uruchomieniową ZL9AVR+ZL7AVR (ATmega128A) . Mam problem z ustawieniem breakpoint'ów w kodzie źródłowym w różnych projektach. Po włączeniu debugowania w symulatorze jak i z użyciem JTAGICE3 próba ustawienia breakpointa zawsze kończy się ! i komunikatem: "The breakpoint will not currently be hit. Unable to set requestet breakpoint on target. Note: The current selected device is unable to set breakpoint during runtime." Zmiana w symulatorze typu mikrokontrolera nic nie dała. Próbowałem zmieniać poziom optymalizacji na -O0 i poziom debugowania na -g3 - bez skutku. Próbowałem również ustawić poziom optymalizacji na -Og - również nic to nie dało. Zauważyłem, że mogę bez problemu ustawić breakpoint'y w kodzie asemblerowym. Poprzednio używałem AVR Studio 4.18 i nie miałem żadnych problemów z ustawianiem breakpoint'ów w kodzie źródłowym. Bardzo proszę o pomoc w rozwiązaniu tego problemu. Może jest jakieś nieznane mi rozwiązanie. Z góry dziękuję za pomoc.
OdpowiedzUsuńNajlepiej załóż temat na elektrodzie, bo coś czuję, że dojście do rozwiązania będzie wymagało większej ilości informacji. Breakpointy stawiasz przed rozpoczęciem sesji debugera? Może to być kwestia konfiguracji gcc, pamiętaj też, że nie w każdym miejscu kodu c da się breakpointa wstawić, ze względu na tłumaczenie kodu na asembler.
UsuńDziękuję za odpowiedź, zaraz spróbuję założyć temat na elektrodzie. Breakpointy stawiam po rozpoczęciu sesji debugera. Próbowałem je postawić przed rozpoczęciem, ale wówczas po rozpoczęciu sesji również na breakpointach pojawia się ten komunikat. Próbowałem stawiać breakpointy na innych (mniej istotnych dla mnie liniach), za każdym razem to samo. Wcześniej napisałem, że nie ma problemu z postawieniem breakpointów w asemblerze. Zastanawiam się tylko jak to było rozwiązane w AVR Studio i we wcześniejszych wersjach Atmel Studio. Tam jeśli w jakiejś linii nie można było postawić breakpointa wystarczyło wyłączyć optymalizacje (-O0) i problem znikał.
UsuńWszedłem w tryb debugowania w atmel studio i ni jak nie wiem jak z niego wyjść koszmar. Procesor się nie programuje, bo ciągle jest w debug. Start without debugging też nie pomaga
OdpowiedzUsuń