Serwis Edukacyjny w I-LO w Tarnowie Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej Autor artykułu: mgr Jerzy Wałaszek |
©2024 mgr Jerzy Wałaszek |
https://www.microchip.com/about-us/legal-information/copyright-usage-guidelines
Poniższe rysunki przedstawiają konfigurację pamięci:
Interfejs złożony jest z:
Bity sterujące interfejsem pamięci zewnętrznej znajdują się w trzech rejestrach: w rejestrze sterującym mikrokontrolerem (ang. MCU Control Register – MCUCR), w rejestrze A sterującym pamięcią zewnętrzną (ang. External Memory Control Register A – XMCRA) i w rejestrze B sterującym pamięcią zewnętrzną (ang. External Memory Control Register B – XMCRB).
Gdy zostanie uaktywniony interfejs XMEM, unieważnia on ustawienia w rejestrach kierunków danych, które odnoszą się do portów przeznaczonych na interfejs XMEM. Interfejs XMEM automatycznie wykrywa, czy dostęp dotyczy pamięci wewnętrznej lub zewnętrznej. Jeśli dostęp jest zewnętrzny, to interfejs XMEM wyprowadzi adres, dane i sygnały sterujące na porty zgodnie z poniższym rysunkiem (przebiegi przedstawiono z pominięciem taktów oczekiwania):
Gdy sygnał ALE (ang. Address Latch Enable) przechodzi ze stanu wysokiego w niski, na liniach AD7:0 jest ważny adres. Podczas przesyłu danych sygnał ALE ma stan niski. Gdy zostanie włączony interfejs XMEM, to również dostęp do pamięci wewnętrznej spowoduje działania na portach adresu, ALE i danych, lecz stroby RD i WR nie zmienią swoich stanów podczas tych operacji.
Gdy interfejs XMEM jest wyłączony, to są używane normalne ustawienia końcówek i ich kierunków przesyłu danych. Zauważ, iż przy wyłączonym interfejsie XMEM przestrzeń adresowa ponad granicą wewnętrznej pamięci SRAM nie jest odwzorowywana w SRAM.
Powyższy rysunek przedstawia sposób podłączenia zewnętrznej pamięci SRAM do mikrokontrolera AVR za pomocą układu ośmiu przerzutników D typu Latch (zwykle jest to układ 74573 lub jego odpowiednik), które przepuszczają dane, gdy wejście bramkujące G ma stan wysoki.
Z powodu dużej prędkości pracy interfejsu XRAM, przerzutniki zatrzaskowe adresu należy wybierać z uwagą dla prędkości systemu powyżej 8 MHz przy 4V i 4 MHz przy 2,7V. Przy pracy w warunkach wykraczających poza te częstotliwości typowe stare serie przerzutników Latch typu 74HC stają się nieodpowiednie. Interfejs pamięci zewnętrznej został zaprojektowany do współpracy z przerzutnikami Latch serii 74AHC. Jednakże można zastosować większość przerzutników Latch pod warunkiem spełniania przez nie następujących parametrów czasowych:
Interfejs pamięci zewnętrznej zaprojektowano z zagwarantowaniem minimalnego
czasu podtrzymania adresu po przejściu G w stan niski równego
Oporniki podciągające na portach AD7:0 można aktywować, jeśli odpowiadający im rejestr portu zostanie zapisany stanem logicznym jeden. Aby zredukować pobór energii w trybie uśpienia, zaleca się wyłączenie oporników podciągających przez zapis zera do rejestru portu przed wejściem w uśpienie.
Interfejs XMEM dostarcza również podtrzymywania magistrali (ang. Bus Keeper) na liniach AD7:0. Podtrzymywanie można włączać lub wyłączać programowo, co podano w opisie rejestru sterującego pamięcią zewnętrzną (ang. External Memory Control Register B – XMCRB). Gdy podtrzymywanie jest włączone, to zapewni zdefiniowany poziom logiczny (zero lub jeden) na magistrali AD7:0, gdy linie te w przeciwnym przypadku zostałyby przełączone w stan wysokiej impedancji przez interfejs XMEM.
Pamięci zewnętrzne posiadają różne wymogi czasowe. Aby je spełnić, interfejs XMEM mikrokontrolera ATmega128A udostępnia cztery różne ustawienia taktów oczekiwania opisane w poniższej tabelce (zobacz do opisu rejestru XMCRA):
SRWn1 | SRWn0 | Takty oczekiwania |
0 | 0 | Bez taktów oczekiwania. |
0 | 1 | Jeden takt oczekiwania podczas strobu odczytu/zapisu. |
1 | 0 | Dwa takty oczekiwania podczas strobu odczytu/zapisu. |
1 | 1 | Oczekiwanie dwóch taktów podczas odczytu/zapisu i jednego taktu przy wysyłaniu nowego adresu. |
Ważne jest rozważenie specyfikacji czasowych zewnętrznej pamięci przed wyborem taktów oczekiwania. Najważniejszym parametrem jest czas dostępu dla pamięci zewnętrznej w porównaniu z wymogiem ustawiania danych mikrokontrolera ATmega128A. Czas dostępu dla pamięci zewnętrznej jest zdefiniowany jako czas liczony od momentu otrzymania sygnałów wyboru/adresu układu do momentu pojawienia się danych spod tego adresu na magistrali. Ten czas dostępu nie może przekraczać czasu od momentu przejścia impulsu ALE w stan niski do momentu, gdy dane muszą być stabilne podczas sekwencji odczytu (czas: tLLRL+ tRLRH - tDVRH wartości tych czasów znajdziesz w parametrach elektrycznych mikrokontrolera ATmega128). Takty oczekiwania są ustawiane programowo. Dodatkową własnością jest możliwość podziału przestrzeni pamięci zewnętrznej na dwa sektory z indywidualnymi ustawieniami taktów oczekiwania. Umożliwia to podłączenie do tego samego interfejsu XMEM dwóch różnych układów pamięciowych o różnych wymaganiach czasowych.
Zauważ, iż interfejs XMEM jest asynchroniczny, a przebiegi czasowe na poniższych rysunkach odnoszą się do wewnętrznego zegara systemowego. Skos (ang. skew) pomiędzy zegarem wewnętrznym a zewnętrznym (XTAL1) nie jest gwarantowany (różni się pomiędzy układami oraz zależy od temperatury i napięcia zasilającego). W konsekwencji interfejs XMEM nie jest przystosowany do pracy synchronicznej.
Cykle zewnętrznej pamięci danych bez taktów oczekiwania(1)
(SRWn1 = 0 i SRWn0 =0)
Cykle zewnętrznej pamięci danych przy SRWn1 = 0 i SRWn0 = 1(1)
Cykle zewnętrznej pamięci danych przy SRWn1 = 1 i SRWn0 = 0(1)
Cykle zewnętrznej pamięci danych przy SRWn1 = 1 i SRWn0 = 1(1)
Ponieważ pamięć zewnętrzna jest odwzorowywana w przestrzeni adresowej za pamięcią wewnętrzną (jak na rysunku powyżej), to pamięć zewnętrzna nie jest adresowana przy dostępie do pierwszych 8704 bajtów przestrzeni danych. Może się wydawać, iż te pierwsze 8704 bajty pamięci zewnętrznej jest niedostępne (adresy pamięci zewnętrznej od 0x0000 do 0x21FF). Jednakże przy dołączaniu pamięci zewnętrznej mniejszej od 64 KB, na przykład 32 KB, te komórki są łatwo dostępne po prostu przez adresowanie od 0x8000 do 0xA1FF. Ponieważ bit A15 nie jest połączony z pamięcią zewnętrzną, to adresy od 0x8000 do 0xA1FF pojawiają się dla pamięci zewnętrznej jako adresy od 0x0000 do 0x21FF. Adresowanie ponad adres 0xA1FF nie jest zalecane, ponieważ zaadresuje komórkę pamięci zewnętrznej, do której jest już dostęp pod innym (niższym) adresem. Dla programu aplikacji zewnętrzna pamięć 32 KB pojawi się jako 32 KB liniowa przestrzeń adresowa od 0x2200 do 0xA1FF. Zilustrowane to zostało na poniższym rysunku.
Ponieważ pamięć zewnętrzna jest odwzorowana w przestrzeni adresowej mikrokontrolera AVR jak na powyższym rysunku, tylko 56KB pamięci zewnętrznej jest standardowo dostępne (przestrzeń adresowa od 0x0000 do 0x21FF jest zarezerwowana na pamięć wewnętrzną). Jednakże możliwe jest wykorzystanie całej pamięci zewnętrznej poprzez maskowanie na zero starszych bitów adresowych. Można to zrobić przez użycie bitów XMM i sterowanych przez program najstarszych bitów adresu. Przez ustawienie portu C na wyprowadzanie wartości 0x00 i zwolnienie najbardziej znaczących bitów do normalnej pracy końcówek portu interfejs pamięci zaadresuje 0x0000 - 0x2FFF. Zobacz na poniższe przykłady.
Przykład w kodzie maszynowym |
; OFFSET jest zdefiniowany na 0x2000 w celu zapewnienia ; dostępu do pamięci zewnętrznej ; Skonfiguruj port C (górny bajt adresu) na ; wyprowadzanie 0x00, gdy końcówki zostaną uwolnione ; do normalnej pracy końcówki portu ldi r16, 0xFF out DDRC, r16 ldi r16, 0x00 out PORTC, r16 ; uwolnij PC7:6 ldi r16, (1<<XMM1) sts XMCRB, r16 ; wpisz 0xAA pod adres 0x0001 pamięci zewnętrznej ldi r16, 0xaa sts 0x0001+OFFSET, r16 ; z powrotem przywróć PC7:6 do pracy z pamięcią zewnętrzną ldi r16, (0<<XMM1) sts XMCRB, r16 ; umieść 0x55 pod adresem (OFFSET + 1) pamięci zewnętrznej ldi r16, 0x55 sts 0x0001+OFFSET, r16 |
Przykład w języku C |
#define OFFSET 0x2000 void XRAM_example(void) { unsigned char *p = (unsigned char *) (OFFSET + 1); DDRC = 0xFF; PORTC = 0x00; XMCRB = (1<<XMM1); *p = 0xaa; XMCRB = 0x00; *p = 0x55; } |
Przy stosowaniu tej opcji należy postępować bardzo ostrożnie, ponieważ większość pamięci jest wymaskowana.
Bit | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | |
0x22 (0x42) | – | – | – | – | EEAR11 | EEAR10 | EEAR9 | EEAR8 | EEARH |
0x21 (0x41) | EEAR7 | EEAR6 | EEAR5 | EEAR4 | EEAR3 | EEAR2 | EEAR1 | EEAR0 | EEARL |
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
Zapis/Odczyt | O | O | O | O | Z/O | Z/O | Z/O | Z/O | |
Zapis/Odczyt | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | |
Wartość początkowa | 0 | 0 | 0 | 0 | X | X | X | X | |
X | X | X | X | X | X | X | X |
Te bity są zarezerwowane i przy odczycie dają zawsze wartość 0.
Rejestry adresowe EEPROM – EEARH i EEARL – określają adres EEPROM (starszy i młodszy bajt adresu) w 4096-bajtowej przestrzeni pamięci EEPROM. Bajty EEPROM są adresowane liniowo od 0 do 4095. Początkowa zawartość rejestru EEAR jest niezdefiniowana. Właściwą wartość należy wpisać przed dostępem do EEPROM.
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x20 (0x40) | MSB | LSB | EEDR | ||||||
Zapis/Odczyt | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | |
Wartość początkowa | X | X | X | X | X | X | X | X |
Dla operacji zapisu w EEPROM rejestr EEDR zawiera dane do zapisania pod adresem podanym przez rejestr EEAR. Dla operacji odczytu z EEPROM rejestr EEDR zawiera dane odczytane z komórki EEPROM o adresie podanym w rejestrze EEAR.
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x1F (0x3F) | – | – | EEPM1 | EEPM0 | EERIE | EEMPE | EEPE | EERE | EECR |
Zapis/Odczyt | O | O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | |
Wartość początkowa | 0 | 0 | X | X | 0 | 0 | X | 0 |
Te bity są zarezerwowane w i zawsze przy odczycie dają zero.
Ustawienie bitów trybu programowania EEPROM definiuje operację programowania, która zostanie zainicjowana przy zapisie bitu EEPE. Możliwe jest programowanie danych w jednej operacji atomowej (wymazanie starej wartości i zaprogramowanie nowej) lub rozdzielenie operacji wymazywania i zapisu na dwie osobne operacje. Czasy programowania w tych różnych trybach pokazuje poniższa tabelka. Gdy EEPE jest ustawione, każdy zapis do EEPMn będzie ignorowany. Podczas resetu bity EEPMn będą zresetowane na 0b00, o ile EEPROM nie jest zajęte programowaniem.
EEPM1 | EEPM0 | Czas programowania | Operacja |
0 | 0 | 3,4 ms | Wymazanie i zapis w pojedynczej operacji (operacja atomowa). |
0 | 1 | 1,8 ms | Tylko wymazanie. |
1 | 0 | 1,8 ms | Tylko zapis. |
1 | 1 | – | Zarezerwowane do użycia w przyszłości. |
Wpisanie jedynki do bitu EERIE włącza przerwania przy gotowości EEPROM, jeśli bit I w rejestrze SREG jest ustawiony. Wpisanie zera do EERIE wyłącza te przerwanie. Przerwanie od gotowości EEPROM jest generowane ciągle, gdy bit EEPE jest wyzerowany.
Bit EEMPE określa, czy ustawienie EEPE na jeden wywoła zapis do EEPROM. Gdy bit EEMPE zostanie ustawiony, to ustawienie EEPE w ciągu czterech następnych taktów zegara zapisze dane do EEPROM pod wybrany adres. Jeśli bit EEMPE ma wartość zero, ustawianie EEPE nie wywołuje żadnego skutku. Gdy program zapisał jedynkę w EEMPE, zostanie ona wyzerowana sprzętowo po upływie czterech taktów zegara. Zobacz na opis bitu EEPE, gdzie znajduje się procedura zapisu w EEPROM.
Bit EEPE jest strobem programowania EEPROM. Gdy zostaną poprawnie ustawione adres i dane, to należy wpisać jedynkę do bitu EEPE, aby dane zapisać w pamięci EEPROM. Przed dokonaniem tego zapisu należy ustawić na jeden bit uaktywnienia programowania EEMPE, w przeciwnym razie zapis do EEPROM nie zostanie wykonany. Należy zastosować poniższą procedurę (kolejność kroków 3 i 4 nie jest istotna):
Pamięć EEPROM nie może być programowana podczas zapisu przez mikroprocesor danych do pamięci FLASH. Program użytkownika musi sprawdzić, czy programowanie FLASH jest ukończone przed zainicjowaniem zapisu do EEPROM. Krok 2 jest tylko wtedy istotny, gdy oprogramowanie zawiera boot loader, który pozwala mikroprocesorowi programować FLASH. Jeśli pamięć FLASH nigdy nie jest uaktualniana przez mikroprocesor, krok 2 można pominąć. Zobacz do rozdziału "Wsparcie bootloadera – odczyt przy zapisie – samoprogramowanie".
Uwaga: przerwanie pomiędzy krokiem 5 a 6 spowoduje porażkę cyklu zapisu, ponieważ bit uaktywniający programowanie EEPROM, EEMPE, straci ważność (zostanie wyzerowany sprzętowo po czterech taktach zegara). Jeśli procedura przerwania uzyskująca dostęp do EEPROM przerwie pracę innemu procesowi dostępu do EEPROM, to rejestr EEAR lub EEDR zostanie zmodyfikowany, powodując porażkę przerwanego procesu dostępu do EEPROM. Zaleca się wyzerowanie globalnego znacznika przerwań I w rejestrze SREG w celu uniknięcia tych problemów.
Gdy upłynie czas przeznaczony na zapis, bit EEPE jest zerowany sprzętowo. Program użytkownika może przeglądać zawartość tego bitu i czekać na zero przed zapisem kolejnego bajtu. Gdy bit EEPE został ustawiony, mikroprocesor zatrzymuje się na dwa cykle przed wykonaniem następnej instrukcji.
Bit EERE jest strobem odczytu EEPROM. Gdy został ustawiony poprawny adres w rejestrze EEAR, należy wpisać logiczną jedynkę do bitu EERE, aby wyzwolić odczyt EEPROM. Odczyt zajmuje jedną instrukcję i zażądane dane są dostępne natychmiast. Gdy jest odczytywana pamięć EEPROM, mikroprocesor zatrzymuje się na cztery cykle przed wykonaniem następnej instrukcji. Użytkownik powinien przeglądać stan bitu EEPE przed rozpoczęciem operacji odczytu. Jeśli trwa operacja zapisu, nie można odczytywać EEPROM ani zmieniać zawartości rejestru EEAR.
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x2B (0x4B) | MSB | LSB | GPIOR2 | ||||||
Zapis/Odczyt | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | |
Wartość początkowa | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x2A (0x4A) | MSB | LSB | GPIOR1 | ||||||
Zapis/Odczyt | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | |
Wartość początkowa | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x1E (0x3E) | MSB | LSB | GPIOR0 | ||||||
Zapis/Odczyt | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | |
Wartość początkowa | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
(0x74) | SRE | SRL2 | SRL1 | SRL0 | SRW11 | SRW10 | SRW01 | SRW00 | XMCRA |
Zapis/Odczyt | O | Z/O | Z/O | O | Z/O | Z/O | Z/O | O | |
Wartość początkowa | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Zapis jedynki do bitu SRE włącza interfejs pamięci zewnętrznej. Funkcje końcówek AD7:0, A15:8, ALE, WR i RD zostają uaktywnione jako funkcje alternatywne końcówek. Bit SRE unieważnia wszelkie ustawienia kierunku działania końcówek w odpowiednich rejestrach kierunku danych. Wpisanie zera do SRE wyłącza interfejs pamięci zewnętrznej i przywraca normalne ustawienia końcówek i kierunku danych.
Możliwe jest skonfigurowanie różnych stanów oczekiwania dla różnych adresów pamięci zewnętrznej. Przestrzeń adresową pamięci zewnętrznej można podzielić na dwa sektory, które posiadają osobne bity stanów oczekiwania. Bity SRL2, SRL1 i SRL0 wybierają podział tych sektorów, co pokazano na poniższym rysunku i w tabelce. Standardowo bity SRL2, SRL1 i SRL0 są ustawione na zero i cała przestrzeń adresowa pamięci zewnętrznej traktowana jest jako jeden sektor. W tym przypadku takty oczekiwania są konfigurowane przez bity SRW11 i SRW10.
SRL2 | SRL1 | SRL0 | Granice sektorów |
0 | 0 | X | Dolny sektor = N/A Górny sektor = 0x2200 - 0xFFFF |
0 | 1 | 0 | Dolny sektor = 0x2200 - 0x3FFF Górny sektor = 0x4000 - 0xFFFF |
0 | 1 | 1 | Dolny sektor = 0x2200 - 0x5FFF Górny sektor = 0x6000 - 0xFFFF |
1 | 0 | 0 | Dolny sektor = 0x2200 - 0x7FFF Górny sektor = 0x8000 - 0xFFFF |
1 | 0 | 1 | Dolny sektor = 0x2200 - 0x9FFF Górny sektor = 0xA000 - 0xFFFF |
1 | 1 | 0 | Dolny sektor = 0x2200 - 0xBFFF Górny sektor = 0xC000 - 0xFFFF |
1 | 1 | 1 | Dolny sektor = 0x2200 - 0xDFFF Górny sektor = 0xE000 - 0xFFFF |
Bity SRWn1 i SRWn0 określają liczbę taktów oczekiwania dla górnego/dolnego sektora przestrzeni adresowej pamięci wewnętrznej. Opis znajdziesz w tabelce poniżej.
SRWn1 | SRWn0 | Takty oczekiwania |
0 | 0 | Bez taktów oczekiwania. |
0 | 1 | Jeden takt oczekiwania podczas strobu odczytu/zapisu. |
1 | 0 | Dwa takty oczekiwania podczas strobu odczytu/zapisu. |
1 | 1 | Oczekiwanie dwóch taktów podczas odczytu/zapisu i jednego taktu przed wysyłaniem nowego adresu. |
n = 0, dolny sektor; n = 1, górny sektor
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
(0x75) | XMBK | – | – | – | – | XMM2 | XMM1 | XMM0 | XMCRB |
Zapis/Odczyt | Z/O | O | O | O | O | Z/O | Z/O | Z/O | |
Wartość początkowa | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Wpisanie jedynki do bitu XMBK uaktywnia opcję podtrzymywania na liniach AD7:0 interfejsu pamięci zewnętrznej. Gdy podtrzymywanie jest włączone, zapewnia poziom logiczny zero lub jeden na liniach AD7:0, gdy w przeciwnym wypadku linie te weszłyby w stan wysokiej impedancji. Wpisanie zera do XMBK wyłącza tę funkcję. Podtrzymywanie nie jest powiązane z bitem SRE, zatem nawet gdy interfejs XMEM jest nieaktywny, podtrzymywanie wciąż działa tak długo, jak bit XMBK ma wartość jeden.
Bity te są zarezerwowane i zawsze zwracają zero przy odczycie. Dla kompatybilności z przyszłymi modelami mikrokontrolera zapisuj te bity stanem zero.
Gdy pamięć zewnętrzna zostaje uaktywniona, wszystkie końcówki portu C są
standardowo używane jako górne bity adresowe. Jeśli nie jest potrzebna pełna
przestrzeń adresowa 56 KB do dostępu do pamięci zewnętrznej, to niektóre lub
wszystkie końcówki portu C mogą zostać uwolnione do spełniania normalnych
funkcji końcówek portu, co opisuje tabelka poniżej. Zobacz do podrozdziału "Używanie
wszystkich komórek pamięci zewnętrznej mniejszej niż 64 KB".
Końcówki portu C zwolnione do swoich normalnych funkcji przy uaktywnieniu pamięci zewnętrznej
XMM2 | XMM1 | XMM0 | Liczba górnych bitów adresu | Zwolnione końcówki portu |
0 | 0 | 0 | 8 (pełna przestrzeń 56 KB) | Żadna |
0 | 0 | 1 | 7 | PC7 |
0 | 1 | 0 | 6 | PC7 - PC6 |
0 | 1 | 1 | 5 | PC7 - PC5 |
1 | 0 | 0 | 4 | PC7 - PC4 |
1 | 0 | 1 | 3 | PC7 - PC3 |
1 | 1 | 0 | 2 | PC7 - PC2 |
1 | 1 | 1 | Bez górnych bitów adresowych | Pełny port C |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2024 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.