środa, 13 marca 2019

PIC32MM - Tutorial part 3 - Hello World

W tej części tutoriala zajmiemy się wreszcie czymś konkretnym i namacalnym. Spróbujemy ożywić dwie diody LED na naszej płytce developerskiej Curiosity, które będą migać niezależnie ,każda z inną częstotliwością. I tak zdefiniujemy sobie nasze Hello World. Przy okazji poznamy obsługę timera sprzętowego i konstrukcję timera programowego. Najpierw musimy zlustrować schemat płytki Curiosity aby poszukać na niej dwóch diod LED i uzyskać informację do jakich pinów mikrokontrolera są przyporządkowane.


Schemat płytki znajdziemy pod tym linkiem : LINK .Ze schematu wynika, że w sumie mamy do dyspozycji 5 diod LED , dwie opisane jako General Purpose LEDs i trzy w postaci jednej fajnej diody RGB. My skorzystamy z dwóch diod ogólnego przeznaczenia. Piny na których są podpięte nasze wybrane diody LED to RD3 i RC13. Zatem do boju. W MPLABX-IDE tworzymy nowy pusty projekt o nazwie pic32mm_tutorial_part3 , mikrokontroler jakim się posługujemy w projekcie to PIC32MM0256GPM064. Za pomocą wtyczki konfigurujemy zegar na 24 MHz. Jak to zrobić i jak utworzyć projekt znajdziemy w Tutorialu nr 2
Zakładam , że projekt mamy utworzony i uruchomiliśmy dla tego projektu wtyczkę MCC. Zatem obrazek do jakiego musimy dojść wygląda jak poniżej :




Zegar mamy ustawiony jak powyżej na 24 MHz. Teraz czas zająć się konfiguracją pinów RD3 i RC13. To co musimy zrobić to upewnić się , że piny nie są podłączone do sekcji analogowej bo jeśli tak to musimy ten związek przerwać :). Piny opisane jako AN w datasheet w tabelce z opisem pinów wymagają odłączenia sekcji analogowej w przypadku kiedy chcemy je używać jako piny cyfrowe. Kolejną czynnością będzie ustawienie pinów RD3 i RC13 jako wyjścia. Oczywiście wszystkie te czynności wygodnie wykonamy w MCC. Otwieramy zatem okienka pomocne przy konfiguracji pinów. Na górze okienka z konfiguracją zegara klikamy zakładkę Pin Module. Otrzymamy obrazek jak poniżej :


Okienko na które się przełączyliśmy pokazuje wszystkie aktualnie użyte piny i ich konfigurację. Dla rozjaśnienia  skrótów np. WPU (oznacza pull up) a WPD (oznacza pull down) czyli podciągnięcie np wejścia do plusa lub do masy. Jeśli w kolumnie Analog ptaszek jest odznaczony to znaczy, że pin jest odłączony od sekcji analogowej. Widzimy na liście tylko dwa piny RB0 i RB1, piny te po starcie są przyporządkowane do programatora ale musimy to zmienić bo płytka Curiosity ma na pinach RA0 i RA1 podpięty programator jak to zrobić to zachwilę.
Teraz otworzymy sobie fajowe okienko z wizualizacją wszystkich pinów. W tym celu na górze dolnego okienka klikamy zakładkę Pin Manager Grid View. Naszym oczom ukaże się obrazek jak poniżej :



W okienku tym widzimy las kłódeczek. Kłódka zamknięta oznacza wykorzystanie pinu. Aby ustawić nasze piny jako wyjścia (Output) RD3 i RC13 poruszamy się w wierszu przyporządkowanym do output i zamykamy kłódeczki dla tych pinów. Efektem będzie obrazek jak poniżej :



Teraz zerknijmy co się zmieniło po zamknięciu kłódeczek dla RD3 i RC13. Na obrazku reprezentującym mikrokontroler przy pinie np.RD3 widzimy taką sekwencję RD3|IO_RD3|GPIO , przy czym IO_RD3 to label za pomocą którego możemy odwoływać do pinu w programie. Możemy zmienić ten label na inną  nazwę dowolnie w/g własnego uznania. Zmiany labela dokonujemy w okienku Pin Module w kolumnie Custom Name. GPIO oznacza , że pin został przyporządkowany do tego modułu. Kolejne zmiany po zamknięciu naszych kłódeczek widzimy w okienku Pin Module, gdzie wskoczyły nasze dwa piny RD3 i RC13 . Widzimy tam ,że w kolumnie Analog nie ma dla nich przewidzianych okienek do zaptaszkowania, oznacza to, że piny te nie podlegają odłączeniu od sekcji analogowej i nie musimy się tym martwić. Gdyby te okienka jednak były to trzeba je wtedy odptaszkować.

Mając na uwadze, że programator w naszej płytce jest podłączony do pinów RA0 i RA1 a nie tak jak zastaliśmy w MCC do RB0 i RB1, musimy to zmienić. W tym celu klikamy na otwartą kłódeczkę na pomarańczowym tle na pinie RA0 lub RA1, obie kłódeczki się synchronicznie zamkną tak jak na obrazku poniżej :


W sumie to konfigurację pinów mamy zakończoną. Gdybyśmy chcieli zerknąć jak to od strony rejestrów wygląda to w okienku Pin Module klikamy zakładkę Registers, wtedy w łapkę bierzemy datasheet i rozszyfrowujemy znaczenie poszczególnych rejestrów. I to jest w sumie fajna droga nauki rejestrów bo mamy na tacy podane wszystkie rejestry przyporządkowane do danego modułu.

Aby zrealizować nasz zamiar czyli miganie niezależne dwoma diodami LED musimy mieć w programie "tykacz" , który będzie odmierzał nam czas. Mechanizm "tykacza" fizycznie zrealizować można za pomocą timera, który po odmierzeniu ustawionego czasu wygeneruje nam przerwanie. No ale jak taki mechanizm stworzyć ? Patrzymy na lewe środkowe okienko nazwane Device Resources i wyszukujemy tam moduł Timer ,rozwijamy go i naszym oczom powinien pokazać się widok jak poniżej :


Mamy jak widać do dyspozycji cztery timery w tym jeden opisany jako CORETIMER, który jest odpowiednikiem SYSTICK-a w ARM-ach. My wybieramy TMR2 jako nasz "tykacz", klikamy w jego nazwę . Otworzy nam się okienko konfiguracyjne i jednocześnie moduł TMR2 pojawi się w okienku Project Resources co oznacza , że MCC doda ten moduł do naszego projektu po kliknięciu zakładki Generate. No ale zanim to zrobimy musimy ustawić nasz "tykacz". Przyjmijmy, że chcemy ustawić aby nasz "tykacz" generował przerwanie co np. 10 ms . Skupiamy się zatem na okienku konfiguracyjnym  TMR2. Na początku aby nam nie umknęło to stawiamy ptaszka w opcji Enable Timer Interupt. Gdybyśmy tego nie zrobili to aby uruchomić timer w programie nie wystarczyłaby sama funkcja inicjalizacji ale trzeba by było dodatkowo włączyć jeden bit ON w rejestrze T2CON lub użyć funkcji TMR2_Start() wygenerowanej przez MCC.


Chcemy ustawić wartość np. 10 ms ale widzimy , że w okienku Timer Period można ustawić maksymalnie 2,73 ms. Musimy zatem zmienić Prescaler na mniejszą wartość np. 1:8 i wtedy bez problemu wpiszemy wartość 10 ms w okienko Timer Period. Okienko z wprowadzonymi zmianami będzie wyglądać jak poniżej :


Na tym etapie mamy wyczerpane wszystkie aspekty związane z konfiguracją sprzętową czyli skonfigrowaliśmy piny RD3 i RC13 oraz TMR2. Klikamy zatem zakładkę Generate w okienku Project Resources. Zamykamy MCC klikając jeden raz w ikonkę MCC na górnej belce narzędziowej MPLABX-IDE. W lewym górnym okienku klikamy zakładkę Projects aby przełączyć widok na drzewo projektów. Wszystkie pliki jakie generuje MCC znajdują się w katalogu MCC Generated Files.
Tutaj mała dygresja , jeśli chcemy w dowolnym momencie wrócić do MCC aby coś np. zmienić w konfiguracji sprzętowej to najlepiej zrobić to tak, wchodzimy do katalogu Important Files, który znajduje się w drzewie katalogów projektu. I tam klikamy w MyConfig.mc3. Uruchomimy w ten sposób konfigurator MCC dla naszego, projektu.

Zanim przejdziemy dalej do realizowania naszego zamiaru Hello World czyli niezależnego mrugania dwoma diodami LED, przyjrzymy się plikom konfiguracyjnymi wygenerowanym przez MCC a w szczególności dotyczącymi konfiguracji pinów i timera TMR2. Zaglądamy najpierw do pliku pin_manager.h widzimy tutaj definicje makr np. dla pinu RC13

#define IO_RC13_SetHigh()         ( LATCSET = (1 << 13) )
#define IO_RC13_SetLow()           ( LATCCLR = (1 << 13) )

Przy każdej definicji jest zakomentowany opis jak tego używać i do czego to służy . Microchip daje nam do ręki proste definicje z których możemy skorzystać lub nie np. do operacji na pinach. Tak dla ciekawości zapis LATCSET = (1 << 13) oznacza atomowe ustawienie bitu nr 13 w rejestrze LATC (czyli ustawiamy pin RC13 w stan wysoki za pomocą rejestru zatrzaskowego LATC) a zapis LATCCLR = (1 << 13) to ustawienie atomowe zera na pozycji 13 w rejestrze zatrzaskowym LATC (czyli pin RC13 ustawiamy na 0 za pomocą rejestru zatrzaskowego LATC). Atomowo to znaczy nie podzielnie z punktu widzenia operacji czyli żadne przerwanie tego procesu nie zakłóci. Z pojęciem tym często spotkamy się w przypadku mikrokontrolerów 32-bitowych. To jakie mamy dostępne sposoby ustawiania pinów w naszym mikrokontrolerze odsyłam do mojego artykułu PIC32MM I/O podstawy. i PIC32MM - dostęp ATOMOWY do rejestrów peryferyjnych
No dobrze wiemy, że w pliku pin_manager.h wygenerowanym przez MCC znajdują się proste definicje , których możemy używać do pierwszych zabaw z pinami. Kolejnym plikiem w który warto zajrzeć to pin_manager.c  mamy tutaj w ładnie uporządkowany sposób przedstawione ustawienie poszczególnych rejestrów związanych z konfiguracją pinów.



W sumie nawet nie musimy zaglądać w datasheet aby zrozumieć co reprezentują rejestry. Wszystko jest czytelnie opisane. W pliku tym mamy żywe rejestry ale nadal wszystko jest banalnie proste.
Wszystkie definicje rejestrów naszego mikrokontrolera są zawarte w jednym pliku nagłówkowym p32mm0256gpm064.h ale nie znajdziemy go w drzewie naszego projektu, jest on widziany przez kompilator w tle. Fizyczną lokalizację tego pliku w Linux pokazuje poniższy obrazek :


Jeśli chcemy ten plik wyświetlić w MPLABX-IDE możemy zrobić to szybko tak. Znajdujemy obojętnie jaką nazwę rejestru ja np. posłużyłem się nazwą rejestru TRISA w pliku pin_manager.c. Prawym klawiszem myszki klikam w nazwę rejestru TRISA, otwiera się menu z którego wybieram Navigate --> Go to Declaration/Definition i po chwili wyskoczy nam plik p32mm0256gpm064.h i miejsce z definicją naszego rejestru TRISA


Widzimy od razu w jaki sposób można posłużyć się zdefiniowaną w pliku nagłówkowym strukturą aby dokonać zapisu na konkretnym bicie rejestru TRISA . I przykładowo zapis TRISAbits.TRISA13 = 0 oznacza ustawienie w rejestrze kierunku (TRISx) na porcie A bitu nr 13 na 0 czyli pin RA13 ustawiamy jako wyjście (Output). W PIC32 taka konwencja zapisu obowiązuje dla wszystkich rejestrów. Przeglądając pliki wygenerowane przez MCC i jeden plik nagłówkowy p32mm0256gpm064.h oraz konsultując to z datasheet można bardzo szybko nauczyć się PIC32MM. Datasheet to tylko 358 str co w porównaniu do dokumentacji ARM jest pikuś.

Przejdźmy teraz do zawartości pliku tmr2.c, znajdziemy tam konfigurację naszego timera , funkcję obsługi przerwania i gotowe funkcje do obsługi timera i wszystko pięknie opisane. 



Należy czerpać garściami naukę z tych wygenerowanych przez MCC plików bo to jest źródło bezcennych informacji. Weźmy prosty przykład. Zerknijmy na funkcję obsługi przerwania dla timera :

void __attribute__ ((vector(_TIMER_2_VECTOR), interrupt(IPL1SOFT))) TMR2_ISR()

Tak wygląda konwencja zapisu każdej funkcji wywołującej przerwanie. Może na pozór wygląda to groźnie ale zapewniam , że tak nie jest. Szkielet funkcji jest ten sam to co należy tylko zmienić to w sumie dwie istotne rzeczy oznaczone na czerwono i jedną mniej istotną oznaczoną na niebiesko. _TIMER_2_VECTOR to nazwa wektora wskazującego od którego peryferium chcemy mieć przerwanie. Skąd te nazwy wziąć ? Podpowiem, są w pliku nagłówkowym p32mm0256gpm064.h a jak do nich konkretnie dotrzeć ? klikamy prawym klawiszem myszki w nazwę _TIMER_2_VECTOR wybieramy Navigate --> Go to Declaration/Definition i wskakujemy do sekcji z nazwami wektorów przerwań.


Kurcze ludzie jakie to jest proste :).  Drugim elementem , który musimy podać w nazwie przerwania to IPL1SOFT i tu kluczowa jest tylko cyferka w tym przypadku 1. Tak podajemy w nazwie numer priorytetu przerwania, ten numer musi być zgodny z tym co zostało podane w konfiguracji priorytetów dla przerwania. Konfigurację te znajdziemy w pliku interrupt_manager.c



Interesuje nas tutaj cyferka w wierszu :  IPC4bits.T2IP = 1;

Ostatnim elementem który podajemy w nazwie funkcji to nazwa funkcji :) dla naszego Timera nr 2 wygląda ona tak TMR2_ISR() ale jaką nazwę tu podamy to obojętne w sumie.

Teraz bardzo ważna informacja . W  każdym przerwaniu, obojętnie od czego, musimy na końcu wyzerować flagę przerwania i to jest charakterystyczna cecha wszysytkich PIC. Zapis zerowanie flagi w przypadku naszego przerwania od TMR2 wygląda tak : IFS0CLR = _IFS0_T2IF_MASK; Rejestr w którym dokonujemy zerowania bitu nazywa się IFS0, od razu powinniśmy skoczyć i poszukać tego rejestru w datasheet. Dodanie  CLR po nazwie rejestru oznacza , że robimy zapis atomowy. Skąd wziąć definicje _IFS0_T2IF_MASK ,oczywiście z pliku p32mm0256gpm064.h , prawy klawisz myszki na nazwie _IFS0_T2IF_MASK wybieramy Navigate --> Go to Declaration/Definition i wskakujemy do sekcji z definicjami masek.



Innym sposobem zerowania flagi w przerwaniu jest zastosowanie zapisu w tej prostej postaci : IFS0bits.T2IF = 0;  ale  miejmy na uwadze, że to jest operacja nie atomowa . Jak już to pisałem lub nie jedną z konwencji zapisu wartości do dowolnego rejestru jest format : NazwaRejestrubits.NazwaBitu = wartość
Bardzo proste i łatwo zapamiętać.

Teraz rozpoznamy jak użyć tych dobrodziejstw związanych z obsługą timera w pliku tmr2.c, czyli krótko mówiąc jak to obsługiwać w naszym programie.
Kod użytkownika czyli to co chcemy aby w przerwaniu od TMR2 się wykonywało wpisujemy do funkcji TMR2_CallBack() w pliku tmr2.c Poniżej na obrazku zaznaczyłem to miejsce.


Aby uruchomić nasz timer w programie musimy w pliku main.c  wpisać następującą sekwencję :

TMR2_Start();

Na tym zakończę , krótkie omówienie wybranych plików wygenerowanych przez MCC. Pokazałem , że za pomocą MCC i wygenerowanych przez to narzędzie plików możemy w szybki sposób nauczyć się programowania PIC32MM ale nie tylko bo również eleganckich konwencji języka C.

Przejdę teraz do esencji tutoriala czyli jak zrealizować niezależne miganie dwoma diodami LED podłączonymi do płytki developerskiej Curiosity. Przy czym nie będziemy używać delay'i.

Ogólna koncepcja jest taka. Timer sprzętowy będzie nam co 10ms napędzał dwa timery programowe , które ustawimy na dwa różne interwały np 0.5s i 1s czyli 0.5 Hz i 1 Hz. Każdy z timerów programowych przyporządkujemy do naszych dwóch diod LED. Na razie może to nie być za bardzo zrozumiałe ale nie przejmować się pokażę dokładnie co i jak . Na początek dodamy sobie w pliku main.c definicje togglowania :


#define LED1_TOG PORTC ^= (1<<_PORTC_RC13_POSITION) /*zmienia stan bitu na przeciwny dla RC13*/
 

#define LED2_TOG PORTD ^= (1<<_PORTD_RD3_POSITION) /*zmienia stan bitu na przeciwny dla RD3*/

Posłużyłem się celowo zapisem przyjaznym dla AVR-owców. Oczywiście jak mamy ochotę skorzystać z propozycji wygenerowanej przez MCC to użyjemy funkcji , które znajdziemy w pliku pin_manager.h

IO_RC13_Toggle();

IO_RD3_Toggle();

Ja osobiście staram się nie używać abstrakcyjnych zapisów wolę zapisy w których pojawiają się nazwy rejestrów :)
Dodajemy zatem nasze definicje do pliku main.c co wygląda następująco :


W pliku main.c powołujemy sobie dwie zmienne reprezentujące dwa timery programowe SoftTimer1 i SoftTimer2. Zmienne są z przedrostkiem volatile ponieważ będą obrabiane w przerwaniu. Dodajemy również zapis , który wystartuje nam nasz timer sprzętowy. Naniesione zmiany w pliku main.c wyglądają jak poniżej :


Na koniec dodajemy w pętli głównej  zapisy , które fizycznie realizują nam miganie diodami LED z interwałem 0.5s dla LED1 i 1s dla LED2.


Plik main.c mamy już gotowy. Teraz przechodzimy do pliku tmr2.h gdzie deklarujemy zmienne dla naszych timerów programowych ale tym razem z przedrostkiem extern , zmienne te muszą być widziane w pliku tmr.c i main.c



Ostatnią czynnością będzie wpisanie kodu do funkcji TMR2_CallBack() w pliku tmr2.c , funkcja ta jest automatycznie wywoływana w przerwaniu od TMR2 co 10 ms. Nasza rola sprowadza się tylko do wypełnienia kodem tej funkcji. Kod jaki wpisuję do niej zobaczymy poniżej :




Przedstawiony mechanizm timerów programowych jest bardzo sprytnym i prostym mechanizmem, który w "cudowny" sposób rozmnaża nam ilość timerów normalnie tak jak Pan Jezus rozmnożył chleb i ryby na pustyni. Proponuję w ramach pracy domowej prześledzić "na palcach" jak to działa.

Teraz czas na wgranie programu do naszej płytki , podłączamy kabelek do gniazda USB1 na płytce Curiosity. Klikamy ikonkę młoteczka na belce narzędziowej MPLABX-IDE 

 , uruchamia się kompilator. Jeśli kompilacja się powiedzie i nie zrobiliśmy jakiegoś babola to na dole w okienku Output zobaczymy napis BUILD SUCCESSFUL (total time: ....ms)



Aby uruchomić programator i proces wgranie wsadu do mikrokontrolera klikamy w ikonkę :

wyskoczy okienko wyboru programatora, zaznaczamy opcję dokładnie jak na obrazku poniżej :


Po chwili mielenia i wgrywania wsadu nasze diody LED ożyją, LED1 będzie migać co 0.5s a LED2 co 1s.

Spróbujmy teraz zmienić ustawienia timera sprzętowego TMR2 - Timer Period na inną wartość np 5ms.

Uruchamiamy ponownie MCC a robimy to klikając na plik MyConfig.mc3, który znajdziemy w lokalizacji jak na obrazku poniżej :


Po uruchomieniu MCC otwieramy okno ustawień TMR2 i zamiast 10ms tak jak wcześniej ustawiliśmy ustawiamy 5 ms 


Po zmianie ustawień Timer Period na 5ms , klikamy Generate. Wyskoczą nam takie dziwne dwa okienka z kolorowymi strefami.


Lewe okienko reprezentuje to co zostało aktualnie wygenerowane przez MCC w pliku tmr2.c bo tu docelowo nasze zmiany zostaną naniesione. Prawe okienko reprezentuje to co jest aktualnie w naszym programie. Naszym zadaniem jest dodanie tylko tych zmian , które nas interesują. A interesuje nas tylko zmiana konfiguracji w funkcji inicjalizującej nasz timer dotycząca wartości PR2 .Aby dodać tę zmianę klikamy w niebieską strzałeczkę Replace, znajdującą się na obrzeżu lewego okienka.
 

Zmiana wartości PR2 zostanie przeniesiona z lewego okienka do prawego. Klikamy zapisz na ikonkę z dwiema dyskietkami. Następnie raz klikamy w ikonke MCC na górnym pasku narzędziowym i zamykamy w ten wielce kulturalny sposób MCC. Zamykamy okienko Merge MCC co by nas w oczy nie raziło a w wyskakującym okienku wybieramy YES. Przełączamy się zakładką Projects na widok z drzewem projektów. Kompilujemy nasz program klikając ikonkę młoteczka i wgrywamy wsad ikonką strzałeczki w dół . Sprawdzamy analizatorem czasy migania LED1 i LED2. Teraz jest tak jak powinno być czyli LED1 miga co 0.025s a LED2 co 0.5s. W sumie warto może wspomnieć, że timer TMR2 jest automatycznie zerowany jeśli wartość TMR2 = PR2 , w 8 bitowcach chyba to trzeba było manulnie robić bo timer leciał dalej do góry.

W ramach pracy domowej proponuję dokonfigurować (ustawić piny na Output i odłączyć je od sekcji analogowej czyli odptaszkować w kolumnie Analog jeśli jest kwadracik do tego)  dodatkowo 3 piny  dołączone do diody RGB na płytce i każda z nich niech miga z inną częstotliwością. W tym celu w programie należy powołać trzy kolejne SoftTimer-y i zrobić dyskotekę na płytce Curiosity. Ale jeśli w wyniku tej zabawy spalicie dom swój lub sąsiada to ja nie biorę za to odpowiedzialności.

W linkach poniżej znajduje się projekt , który powiesiłem na GitHub. Sciągamy go do MPLABX-IDE za pomocą Team --> Remote --> Clone lub w konsoli Linuxa :

git clone https://github.com/PICmajster/PIC32MM_Tutorial_Part3.git


I cieszymy się z migających diod LED.

Informacja z ostatniej chwili, już niedługo zostanie wydany nowy PIC32 oparty o najwydajniejszy obecnie rdzeń Cortex M7. Konstrukcja ta będzie posiadała peryferia PIC32 , którymi Microchip obudował Cortexa M7. Będzie to na pewno spore wydarzenie na rynku. Nowe mikrokontrolery pojawiły się już w spisie MPLABX-IDE ver 5.15 i tam będziemy mogli je programować. Ludzie będzie się działo :)


Pozdrawiam
picmajster.blog@gmail.com



Linki :

PIC32MM Curiosity Board - schemat
PIC323MM0256GPM064 - datasheet 
PIC32 - Timers 
pic32mm_tutorial_part3 na GitHub

3 komentarze:

  1. Właśnie tego dotąd mi brakowało Dla rodziny PIC32 , porządnych "tutków"! i prostego łopatologicznie tłumaczonego postępowania co jak i z czym.
    Trzymaj tak Dalej PICmajstrze

    OdpowiedzUsuń
  2. Really excellent tutorials! I've been looking everywhere for some tutorials to get me started programming this device, without any luck until I stumbled across your blog. You've done an excellent job of explaining everything in detail so that even I can't mess it up. I have the PIC32MM0064GPL036 version of this Curiosity board and was able to make your programs work on it just fine. I have ordered the PIC32MM0256GPM064 Curiosity board, and look forward to going through more of your tutorials, learning as I go. I am hoping that somewhere up the line you will give us a tutorial on programming the USB interface. I hope to ultimately learn to program this as a HID device, and I also have plans to create some devicelink instruments.
    Thanks again!

    Rob

    OdpowiedzUsuń
  3. The PIC32MM series is gaining more and more fans :).It's cheap and much simpler to use than the ARMs. It's the perfect choice for those starting out with the 32-bit MCU. Microchip tools are simple and beginner-friendly. I wish you quick progress in learning.

    OdpowiedzUsuń