Programowanie mikrokontrolerów: JTAG, SPI, USB oh my !?


52

Zauważyłem, że w odniesieniu do mikrokontrolerów istnieje kilka sposobów ich programowania. Jestem trochę zaznajomiony z USB, ponieważ moje Arduino można programować przez USB.

Co to jest interfejs JTAG lub SPI?

W końcu wiem, że te interfejsy umożliwiają flashowanie układu nowymi instrukcjami, ale czym się różnią? Czy są jakieś zalety jednego nad drugim?

Odpowiedzi:


39

Mikrokontrolery ATMEGA, takie jak arduino, które pochodzą prosto z fabryki, można programować tylko za pomocą interfejsu SPI lub JTAG.

SPI oznacza Serial Peripheral Interface i jest sposobem dla mikrokontrolerów na komunikowanie się ze sobą lub ze światem zewnętrznym. Czasami jest również nazywany 3-przewodowym, ponieważ wykorzystuje trzy przewody do komunikacji. Aby zaprogramować układ, potrzebujesz specjalnego programatora, który odczytuje polecenia z USB w celu sterowania liniami SPI w celu zaprogramowania układu. Popularnym wydaje się być USBTinyISP od Adafruit . Bardzo dobre wprowadzenie do programowania SPI znajduje się w SparkFun. Najpopularniejszymi aplikacjami do programowania układów AVR Atmel są avrdude (linia cmd), ponyprog (nie działa z nowszymi programistami), aw niektórych przypadkach AVR Studio (jeśli twój programista to obsługuje). Zaletą programowania SPI jest to, że możesz zaprogramować dowolny układ Atmel prosto z fabryki, więc nie zawsze potrzebujesz Arduino w swoich projektach.

Gdy SPI jest „tylko kolejnym” protokołem szeregowym, JTAG jest protokołem zaprojektowanym specjalnie do programowania i debugowania mikrokontrolerów. Nie wszystkie Atmel micro obsługują JTAG, ale takie, które są używane w Arduino. Protokół JTAG może być używany do fajnych rzeczy, takich jak „emulacja obwodu” i debugowanie, co oznacza, że ​​pozwala zobaczyć stan programu w mikrokontrolerze podczas jego działania. Aby to zrobić, potrzebujesz specjalnego programisty. Widziałem moją odpowiedź na kolejne pytanie .

Aby zaprogramować układ za pomocą USB, musisz najpierw zaprogramować go za pomocą „bootloadera” za pomocą SPI lub JTAG. Po załadowaniu bootloadera system będzie programowalny z dowolnego komputera PC za pomocą konwertera USB-Serial. Minusem jest to, że bootloader zajmuje trochę miejsca w pamięci, a ta metoda nie pozwala zobaczyć stanu układu podczas jego działania.


10
Wprawdzie trafny jest pomysł, że szeregowy moduł ładujący nie jest dostępny w nowym ATMEGA (chociaż jest on dostępny w wielu innych mikrokontrolerach), jednak twierdzenie, że należy użyć SPI lub JTAG, jest błędne. ATMEGA obsługują również tryb programowania równoległego wysokiego napięcia, który ma zdolność do wyprzedzania niektórych ustawień bezpieczników, co uniemożliwiłoby zastosowanie bardziej popularnych metod programowania w obwodzie. JTAG nie został zaprojektowany do programowania mikr, ale do testowania płyt PC poprzez taktowanie wartości do i z rejestrów styków IO. Rozszerzenie go na programowanie lub debugowanie podstawowych funkcji było późniejszym hackem.
Chris Stratton

SPI i programowanie systemowe / programowanie szeregowe są różne. Ja również byłem przyzwyczajony do faktu, że wiele mniejszych mikrokontrolerów Atmega miało szeregowe piny do programowania na interfejsie SPI, ale byłem przygryziony faktem, że na niektórych większych mikroprocesorach Atmega, szeregowe piny do programowania nie były na interfejsie SPI.
fest

30

Chociaż chciałbym zagłębić się w różne dostępne metody programowania, ktoś inny już to ma. Oto samouczek Dean Camera na temat AVRFreaks, metod programowania AVR :

Istnieje wiele sposobów programowania mikrokontrolerów AVR. Ponieważ wiele osób pyta o różne w tym samym czasie, pomyślałem, że przedstawię je tutaj, aby szybko i skutecznie odpowiedzieć na ich pytania. Proszę wybacz mi, jeśli przegapię metodę lub popełniam błąd.

METODA 1: Programowanie systemu (ISP)

Obsługiwane przez: Ogromna większość AVR (patrz poniższe posty)
Obsługiwani programiści: AVRISP MKI / II, JTAG MKII, STK500, STK600, Dragon, AVRISP klony, Programatory AVR910, AVRONE

W programowaniu systemu jest prawdopodobnie najczęstszą metodą programowania pamięci flash, pamięci EEPROM, bezpiecznika i blokad całej linii AVR. ISP może programować AVR z ekstremalnie wysoką częstotliwością taktowania (zakładając, że docelowy AVR działa z wysoką częstotliwością, a programista to obsługuje) i jest metodą wybieraną przez prawie wszystkich hobbystów AVR. Na rynku jest wiele, wiele klonów AVRISP i programistów AVR910, a także proste klucze sprzętowe do samodzielnego podłączenia, które są podłączone do portu równoległego komputera.

Najnowsze nowe klucze sprzętowe mogą wykorzystywać port szeregowy komputera, jednak niepotwierdzone dowody wskazują, że ta metoda jest bardzo powolna z powodu ograniczeń technicznych.

ISP wymaga, aby docelowy AVR działał z częstotliwością zegara co najmniej czterokrotnie większą niż zegar ISP. Jest to częsta pułapka i źródłem zamieszania dla wielu nowych użytkowników AVR.

METODA 2: JTAG

Obsługiwane przez: Zobacz pomoc AVRStudio Narzędzia do obsługi urządzeń MKI i MKII
Obsługiwane programiści: JTAG-ICE, JTAG-ICE MKII, klony Dragon, JTAG-ICE, AVRONE, STK600 (tylko programowanie)

Technicznie JTAG jest systemem debugowania, a nie metodą programowania. Mimo to interfejs JTAG umożliwia programowanie AVR, który go obsługuje.

JTAG to wbudowane w system narzędzie do debugowania, które pozwala manipulować i sprawdzać status obsługiwanego AVR podczas pracy w obwodzie. JTAG pozwala użytkownikowi zatrzymać wykonywanie w dowolnym momencie, manipulację wewnętrznymi rejestrami AVR i wiele więcej.

Oficjalne jednostki JTAG-ICE firmy ATMEL zostały zastąpione przez JTAG-ICE MKII, który obsługuje nowsze i szerzej obsługiwane protokół debugowania AVR z zakresu AVR, a także programowanie metodą ISP (patrz wyżej).

Klony JTAG-ICE są dostępne w niskich cenach, jednak ich ograniczona kompatybilność z tylko kilkoma AVR ogranicza ich przydatność. Niezależnie od tego, jeśli twój AVR obsługuje interfejs JTAG, JTAG-ICE pozostaje bardzo ładną i skuteczną metodą debugowania i programistą.

METODA 3: DebugWire

Obsługiwane przez: Wiele mniejszych AVR
Obsługiwanych programistów: JTAG-ICE MKII, Dragon, AVRONE

Znowu DebugWire to raczej interfejs debugowania niż interfejs programowania, ale można go użyć do załadowania programów do obsługiwanych AVR. Interfejs dW wykorzystuje pojedynczy pin AVR (linia / RESET) do całej komunikacji, dzięki czemu idealnie nadaje się do urządzeń AVR o niskiej liczbie pinów.

METODA 4: Bootloader

Obsługiwane przez: Większość nowszych AVR
Obsługiwani programiści: nie dotyczy

Z technicznego punktu widzenia nie jest to metoda programowania. Bootloader to mały program AVR, który znajduje się w ustawianej przez użytkownika zarezerwowanej części zwykłego flasha. Programy ładujące wykorzystują funkcje autodopasowania flash dostępne w nowszych AVR, aby umożliwić AVR programowanie się za pomocą danych programu załadowanych z zewnętrznego źródła. Bootloadery mogą pozyskiwać swoje dane z dowolnej lokalizacji (np. Zewnętrzna pamięć flash lub karta SD), jednak zdecydowanie najpopularniejszy typ Bootloadera komunikuje się z komputerem PC przez port RS-232 (szeregowy) AVR.

Programy ładujące są ograniczone, ponieważ zajmują miejsce w pamięci flash (ograniczając rozmiar pamięci flash dostępnej dla aplikacji AVR) i nie są w stanie zmienić bezpieczników AVR.

Programy ładujące są powszechnie dostępne w Internecie do pobrania, ale cierpią z powodu problemu „kurczaka i jajka”; potrzebujesz innego typu programatora wymienionego tutaj, aby programować w bootloaderze. Zwykle jest to rozwiązywane przez budowę prostego klucza równoległego (patrz sekcja ISP) lub przez zakup AVR już wstępnie załadowanego z bootloaderem (np. Płytą AVRButterfly).

METODA 5: Programowanie równoległe wysokiego napięcia (HVPP)

Obsługiwane przez: Większość AVR spoza TINY (z wyjątkami)
Obsługiwani programiści: STK500, STK600, Dragon, Homebrew Dongles, AVRONE

Programowanie równoległe wysokiego napięcia to metoda programowania, która jest rzadko stosowana, ze względu na problemy z konfiguracją. Mimo to programowanie HVPP jest powszechnie stosowane do „wskrzeszenia” AVR-ów, których bezpieczniki zostały źle skonfigurowane za pomocą innej metody programowania.

Zarówno STK500, jak i Dragon obsługują HVPP. Podczas HVPP, pin celu / RESET jest podnoszony do niezwykle wysokiej wartości 12V, która angażuje wewnętrzny równoległy obwód programowania. Pin / RESET jest jedynym pinem AVR (w AVR obsługiwanych przez HVPP), który można bezpiecznie podnieść do tego poziomu.

Możesz stworzyć własny klucz HVPP, korzystając z planów online, takich jak ten.

METODA 6: Programowanie szeregowe wysokiego napięcia (HVSP)

Obsługiwane przez: Wiele TINY AVR (z wyjątkami)
Obsługiwani programiści: STK500, STK600, Dragon, Homebrew Dongles, AVRONE

HVSP jest podobny do HVPP, z tym wyjątkiem, że przesyłanie danych odbywa się raczej szeregowo niż równolegle. Jest to alternatywna metoda programowania stosowana w wielu AVR-ach serii TINY, którym brakuje wystarczającej liczby pinów dla HVPP.

METODA 7: PDI

Obsługiwane przez: XMEGA AVR
Obsługiwane programiści: STK600, AVRONE, JTAG MKII, Dragon, AVRISP MKII

PDI to nowy interfejs programowania oparty na protokole debugWire dla linii AVR XMEGA. Obecnie nie jest używany w żadnym innym 8-bitowym mikrokontrolerze AVR.

METODA 8: TPI

Obsługiwane przez: 6-stykowe AVR-y TINY (ATTINY10 itp.)
Obsługiwani programiści: STK600, Dragon, AVRISP MKII

TPI to bardzo mały interfejs programistyczny dla nowszej linii AVR TINY z ograniczonymi pinami, jak 6-pinowy ATTINY10. Podobnie jak dW, TPI wykorzystuje linię urządzenia / RESET jako część interfejsu komunikacyjnego, ale podobieństwo się kończy. Ponieważ wielkości TINY AVR wielkości kufla nie mają wbudowanego obwodu debugującego, protokół TPI wykorzystuje nowy interfejs programowania trzech pinów w protokole półdupleksowym. Ponieważ linia / RESET musi zostać podniesiona do + 12V do programowania, gdy ustawiony jest pin RSTDSB urządzenia, jest to obecnie obsługiwane tylko przez nowszą płytę programującą STK600.

Bonusowa sekcja FAQ!

  1. Która metoda jest najlepsza?
    Nie ma uniwersalnej metody „najlepszej”. Programowanie przez ISP jest proste i niezwykle popularne, jednak wszystkie powyższe metody będą działać. Dwa tryby programowania wysokiego napięcia (w zależności od tego, które dotyczy danego urządzenia) są najbardziej bogate w funkcje, ponieważ pozwalają na naprawę AVR, którego bezpieczniki zostały źle skonfigurowane. Te metody są jednak trudne w konfiguracji, dlatego większość użytkowników korzysta z usług internetowych.

  2. Zrobiłem klucz do portu równoległego. Czy mogę go używać z AVRStudio?
    Obawiam się że nie. AVRStudio nie może łączyć się z żadnym „głupim” kluczem sprzętowym - wymaga inteligentnego urządzenia programującego - zawierającego sam mikrokontroler - do odszyfrowania wysyłanego protokołu komunikacyjnego. Proste klucze sprzętowe bez mikrokontrolera muszą być „bitowe” (tj. Odpowiednie sygnały symulowane przez klucz sprzętowy za pomocą komputera).

  3. Więc mój klucz jest bezużyteczny?
    Nie. Nadal możesz programować za pomocą domowego klucza sprzętowego za pomocą zewnętrznego oprogramowania do programowania. AVRDude to dobre, znane, bezpłatne narzędzie wiersza poleceń - i jest dołączone do pakietu WinAVR.

  4. Jakie mam opcje, jeśli chcę, aby mój programista współpracował z AVRStudio?
    Wybierz programator korzystający z protokołu obsługiwanego przez AVRStudio. Może to być prosty protokół „AVR910” (przestarzały) lub niestandardowa implementacja protokołu używanego przez STK500 / AVRISP. Zauważ, że ci programiści wymagają w nich mikrokontrolera, co prowadzi do sytuacji catch-22. Można to rozwiązać przez zaprogramowanie AVR programisty w momencie zakupu przy użyciu odpowiedniego oprogramowania wewnętrznego lub przez zaprogramowanie AVR za pomocą bootloadera.

  5. Ok, chcę użyć bootloadera. Jak go tam w ogóle zdobyć ?!
    Aby użyć bootloadera w AVR, najpierw musisz go zaprogramować. Jeśli nie masz istniejącego programatora (wystarczy prosty głupi klucz sprzętowy do programowania początkowego), możesz alternatywnie kupić AVR-y wstępnie zaprogramowane bootloader od kilku dostawców.
    Atmel produkuje również płytkę demonstracyjną Butterfly, której MEGA169 AVR jest fabrycznie wyposażony w bootloader kompatybilny z AVR-Studio.

  6. Wsparcie! Zepsułem bezpieczniki i zepsułem AVR podczas korzystania z ISP! Najczęstszym błędem jest zmiana bezpieczników wyboru zegara na nieprawidłowe ustawienie. Spróbuj umieścić zegar zewnętrzny na pinie XTAL1 AVR i sprawdź, czy to pomoże.
    W przeciwnym razie, jeśli to możliwe, zastosuj jedną z metod wysokiego napięcia. Naprawią one wszelkie błędne konfiguracje, w tym dotyczące źródła zegara, ponieważ metody wysokiego napięcia zapewniają AVR swój własny zegar do programowania.

  7. Jak mogę połączyć się z moim programistą?
    To, jakiego oprogramowania używasz do połączenia z programatorem, zależy od rodzaju programatora, którego używasz.
    Proste „głupie” klucze wymagają oprogramowania innych firm, takiego jak PonyProg lub AVRDude. Mogą to być narzędzia wiersza polecenia lub GUI - rozejrzyj się po Internecie, a dopasujesz je do swoich potrzeb.
    W AVRStudio można używać programistów i programów ładujących opartych na protokole AVR910. Z menu Narzędzia wybierz opcję „AVRProg”, aby otworzyć ekran GUI do połączenia z programatorem. Alternatywnie, narzędzia innych firm, takie jak AVRDude, są również kompatybilne z AVR910.
    Oficjalne narzędzia są ściśle zintegrowane z AVRStudio, szczególnie w przypadku wariantów debugowania (JTAG / Dragon / etc). Z menu Narzędzia AVRStudio wybierz podmenu „Program AVR ...” i kliknij element „Połącz”. W nowym oknie wybierz swoje narzędzie i interfejs połączenia i kliknij OK.
    Podobnie jak w przypadku głupich kluczy sprzętowych i programistów AVR910, oficjalne narzędzia mogą być również używane z oprogramowaniem do programowania innych firm.

(C) Dean Camera, 2009. Wszelkie prawa zastrzeżone. Nie do reprodukcji na stronie internetowej innej niż AVRFreaks.net bez uprzedniej wyraźnej zgody.

Oczywiście powielane za uprzednią wyraźną zgodą!


5

Chciałbym dodać jeszcze jedną rzecz do dyskusji.

SPI jest bardzo popularnym interfejsem dla układów scalonych. Aluzja do 3-przewodowego to tryb SPI, w którym nie używasz pinu wyboru układu.

I2C jest głównym konkursem dla interfejsu, ponieważ wykorzystuje tylko 2 przewody, bez względu na liczbę układów, podczas gdy SPI wymaga innego przewodu na interfejs, ale jest wolniejszy.

Podczas nauczania uważam nauczanie o interfejsach za jedno z najważniejszych zadań.

Wiki społeczności dostępne dla tych, którzy chcą rozwinąć moje informacje.


2
Nigdy nie słyszałem o tym, że I2C jest używany jako natywny interfejs programistyczny flash na mikrokontrolerze, chociaż nie ma powodu, dla którego nie mógłby być punktem wejścia do bootloadera, jak sądzę ...
vicatcu

@vatatcu, właśnie dodałem go jako bardzo popularny interfejs.
Kortuk

3

Z ogólnego punktu widzenia interfejsy te różnią się tylko tym, które programiści i mikrokontrolery je obsługują. Tak długo, jak masz dopasowanie między programatorem a mikrokontrolerem, nie martwiłbym się.

W miarę wnikania w to więcej się przekonasz, że to szpilki, których interfejs używa na mikrokontrolerze, mają większe znaczenie - jeśli używasz tych szpilek do czujników, sygnały mogą zakłócać podczas programowania urządzenia. Najprostszym rozwiązaniem na wypadek problemu jest odłączenie czujników podczas programowania.

Niektóre interfejsy (w tym JTAG) pozwalają na debugowanie urządzenia - ale wtedy potrzebujesz programatora (i oprogramowania do sterowania nim), który również to obsługuje. W poprzednim pytaniu wskazałem Dragonowi na debugowanie urządzeń AVR - zamierzam je zdobyć i grać, gdy moja obecna runda projektów dobiegnie końca.


2

Jak wspomniałeś serial, spi (2 przewody, 3 przewody?), Usb, jtag, swd itp. Są używane.

Tak, są plusy i minusy. Na przykład Jtag dotyczy wszystkich znanych mi przypadków wbudowania w sprzęt, pierwotnie i głównie używanych do czegoś innego niż debugowanie procesora, ale zdarza się, że używają go również do tego. jeśli jtag jest dostępny, jest to ogólnie najlepszy interfejs z tego powodu, ale są wyjątki. Na przykład, jeśli piny nie są dedykowane do jtag, możesz mieć błąd w kodzie i / lub celowo użyć jednego z tych pinów do czegoś innego, co uniemożliwi dostęp do układu za pomocą jtag (jeśli uruchamia to oprogramowanie we flashu zmienia przeznaczenie tych pinów). Innym wyjątkiem jest sytuacja, w której rdzeń procesora może zostać zawieszony przez błąd oprogramowania w pamięci flash, a zawieszonego rdzenia nie można debugować za pomocą narzędzia jtag. Nazwałbym to błędem w projektowaniu sprzętu, ale ostatnio poradziłem sobie z tym w części komercyjnej.

Na AVR na przykład PDI, które, jak myślę, ludzie mogą tutaj nazywać spi, może nie. przynajmniej na Xmega wydaje się, że pdi i zewnętrzny jtag przesyłają wewnętrznie do wspólnego interfejsu pdi. Tak więc piny pdi dają ci bezpośredni dostęp do tego zamiast narzutu jtag. tak długo, jak ten interfejs działa, gdy oprogramowanie we Flashu zawiesiło rdzeń, byłby to idealny interfejs dla tej rodziny. Protokół jest opublikowany i stosunkowo prosty oraz wbudowany w sprzęt. ma wadę dwukierunkowej magistrali danych, takiej jak i2c.

Ramię ma jtag z mniejszą liczbą przewodów zwanych swd, których niekoniecznie chcą jawnie opublikować. jednak implementują go narzędzia typu open source. jest to teoretycznie szeregowy jtag, różne sygnały jtag są wysyłane sekwencyjnie na jednym przewodzie, a nie równolegle na wielu przewodach. zakładam, że wewnątrz części znów jest ona równoległa i zasila normalną logikę jtag. Ma to tę wadę, że ARM chce zachować to w tajemnicy, a debuggery jtag ARM są królewskim bólem w użyciu. To dużo pracy. Jeśli / kiedy openocd zadziała, może to być inna historia. Musisz również martwić się o zmiany przeznaczenia pinów i to, co dzieje się z zawieszonym rdzeniem.

Wielu dostawców korzysta z rozwiązania, w którym mają jeden lub więcej obszarów flashowania rozruchowego, w zależności od tego, w jaki sposób wyciągana jest szpilka lub dwa lub trzy, w zależności od tego, z którego flashowania się uruchamiasz. Możesz więc uruchomić z pamięci flash użytkownika lub z pamięci flash, która przynajmniej z fabryki ma bootloader oparty na porcie szeregowym lub taki, który ma bootloader oparty na usb. Dla każdego dostawcy te rozwiązania programowe mogą się różnić i różnią się, protokół szeregowy zmienia się w subtelny lub bardziej niż subtelny sposób, rozwiązanie USB może się nieco zmienić. Dobrym i złym jest to, że niektóre z tych błysków można uzyskać, więc możesz zdecydować się na zmianę szeregowego programu ładującego, jest to zarówno dobre, jak i złe, dobre, ponieważ możesz wybrać dostosowanie go do swojego produktu, złe, że jest to możliwe aby go przypadkowo skasować i zamurować część, przynajmniej cegłę dla tego interfejsu.

Narzędzia Jtag kiedyś kosztują tysiące dolarów, teraz nie kosztują, za około 15 USD możesz dostać płytkę Breakout Ftdi i zmienić jej przeznaczenie za pomocą Openocd. Za 50 $ plus lub minus niektóre można uzyskać rozwiązanie USB oparte na ftdi, które działa od razu z openocd. Możesz uzyskać niekomercyjny link j za 75-80 USD. A potem są te wielotysięczne, które są szybkie, pewne, ale ogólnie nie warte swojej ceny. Kupujesz je, gdy jesteś wielką korporacją z dużą ilością gotówki do wydania i chcesz zapłacić za wsparcie. Po zapłaceniu tych cen otrzymujesz żądany produkt i natychmiast otrzymujesz odpowiedzi na pytania pomocy technicznej. Podobnie jak na przykład darmowy system Linux vs Windows lub RHEL, obsługa systemu Linux jest bezpłatna, ale dostajesz to, co dostajesz. W każdym razie sprawia to, że jtag jest znacznie bardziej atrakcyjny,

Powinieneś mieć w swoich narzędziach do debugowania i rozwoju arsenał jtag, kiedy i gdzie jest to niedrogie. Sparkfun ma interfejs USB oparty na ftdi na kartach szeregowych, a części ftdi można przekształcić w big bangers, można ich używać do spi lub i2c lub pdi lub jtag lub innych interfejsów. Idealnie jest uzyskać płyty stworzone dla interesującej Cię magistrali / części i korzystać z dołączonego do niej darmowego / otwartego oprogramowania. Korzystając również z tych kart szeregowych, najlepiej mając zasilanie 3,3 V i 5 V (około 15 USD za każdy używany do lillypadów i arduino minis itp.) Do łączenia się z portami szeregowymi dla różnych mikroprocesorów, które mają jakiś protokół szeregowy. Łatwiej jest mi napisać własny moduł ładujący oparty na tych protokołach, zwłaszcza takich jak ludzie arduino / avr, w których publikowane jest źródło modułu ładującego i jest to znaczny podzbiór w stosunku do rzekomego standardu, który obsługuje. YMMV.

Krótko mówiąc, nie ma jednego dobrego rozwiązania, wszystkie mają zalety i wady. Przygotuj się na wsparcie co najmniej dwóch z nich. usb i serial lub usb i jtag lub jtag i serial itp. Wystarczy położyć podkładki lub otwory na szpilki na płycie i niekoniecznie wypełnić. Na potrzeby rozwoju osobistego lub laboratoryjnego dysponuj pełnym zestawem narzędzi i bądź przygotowany na przełączanie się między sobą podczas układania cegieł i odzyskiwania płyt, lub w trakcie opracowywania własnego programu ładującego, oprogramowania układowego USB itp.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.