logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Eclipse- deklaracja zmiennych globalnych i zewnetrznych

ninja_zlomiarz 28 Gru 2011 22:16 3741 27
REKLAMA
  • #1 10316190
    ninja_zlomiarz
    Poziom 10  
    Posty: 35
    Hej,
    mam taki ciężki do przejścia dla mnie problem.

    Piszę program w którym wykorzystuję przerwanie od timera i nie mogę sobie poradzić z deklaracją zmiennych. Mam dwa pliki main.c i stm32f10x_it.c.

    W pliku main deklaruję zmienne globalne:

    #include "stm32f10x.h"
    #include "fatfs/src/ff.h"
    #include "fatfs/src/diskio.h"
    #include <stdio.h>
    
    void RCC_Conf(void);
    void NVIC_Conf(void);
    void SysTick_Conf(void);
    void GPIO_Conf(void);
    
    FATFS g_sFatFs;
    DIR g_sDirObject;
    FILINFO g_sFileInfo;
    FIL g_sFileObject;
    
    WORD zapisanych_bajtow;
    
    uint16_t ADC1Val = 0;
    
    FRESULT fresult;
    FIL plik;
    FILINFO plikInfo ;
    DIR Dir;
    FILINFO *p;
    
    int main(void)
    {
       	RCC_Conf();
      	SysTick_Conf();
      	NVIC_Conf();
    	GPIO_Conf();
    
      	GPIO_SetBits(GPIOC, GPIO_Pin_12);
    
        fresult = f_mount(0, &g_sFatFs);
    
    	// Tworzenie pliku na karcie
    	fresult = f_open (&plik,"plik.txt", FA_CREATE_ALWAYS | FA_WRITE);



    a w pliku stm32f10x_it.c. chciałbym je wykorzystać w przerwaniu
    
    void TIM1_CC_IRQHandler(void)
    {
    	extern FRESULT fresult;
    	extern FIL plik;
    	extern FILINFO plikInfo ;
    	extern DIR Dir;
    	extern FILINFO *p;
      	if (TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET)
      	{
        	TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);
    		ADC_ExternalTrigConvCmd(ADC1, ENABLE);
    		fresult = f_write(&plik, "zawatosc pliku", 15, &zapisanych_bajtow);
      	}
    }
    


    to dodałem przed nazwami plików extern żeby sobie szukał program tego w innym pliku ale wyskakują błędy:

    
    Description	Resource	Path	Location	Type
    unknown type name 'DIR'	
    unknown type name 'FIL'	
    unknown type name 'FILINFO'	
    unknown type name 'FILINFO'	
    unknown type name 'FRESULT'	
    



    wie ktoś może w czym leży problem?
  • REKLAMA
  • Pomocny post
    #2 10316249
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    Przecież kompilator sam wywala ci błąd nieznany typ. Brak dołączonej deklaracji typu.
  • Pomocny post
    #3 10316256
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Gdzie masz zadeklarowane typy z którymi masz problem.
    Plik stm32f10x_it.c musi znać te typy (DIR,FIL...). Dołącz do pliku stm32f10x_it.c nagłówek z deklaracjami tych typów.
  • REKLAMA
  • #4 10316851
    ninja_zlomiarz
    Poziom 10  
    Posty: 35
    dzięki działa, a mam teraz jeszcze inne pytanie odnośnie deklaracji i odwoływania się do zmiennych.

    W pliku main.c mam stworzoną zmienną globalną :
    
    uint16_t ADC1Val = 0;
    

    chciałbym jej wartość wykorzystać w funkcji ale w innym pliku.

    więc w tym pliku wpisuję:

    
    extern uint16_t ADC1Val
    


    i jeżeli chcę się odwołać do jej wartości w funkcji to wystarczy że napiszę takie coś?

    fresult = f_write(&plik, ADC1Val, 6, &zapisanych_bajtow);


    tylko że funkcja oczekuje wartości char i nie wiem jak to rozwiązać
  • Pomocny post
    #5 10317013
    stanleysts
    Poziom 27  
    Posty: 838
    Pomógł: 115
    Ocena: 2
    konwersja - polecam zajrzec do tablic ascii, i z tego co pamietam to drugi argument to wskaznik na dane ktore maja byc zapisane i jest on typu void
  • #6 10317823
    ninja_zlomiarz
    Poziom 10  
    Posty: 35
    próbowałem zrobić jakoś tak:

    
    	extern uint16_t ADC1Val;
    	unsigned char tab[20];
    	sprintf(tab,"%d",ADC1Val);
    	write_text(tab);
    


    ale pojawiają mi się takie błędy:

    Eclipse- deklaracja zmiennych globalnych i zewnetrznych

    hmm nie wiem co mogę, może brakuje mi jakiejś biblioteki? albo pliki nagłówkowego?
  • REKLAMA
  • Pomocny post
    #7 10318026
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Gdzie masz funkcję write_text(); ?
    Tworzysz w ogóle jakieś pliki nagłówkowe?


    extern możesz też zastosować do tej funkcji

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    lub nawet nie musisz wystarczy, że w tym pliku zadeklarujesz ją i tez będzie działać.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    a co do sprintfa to rzutowanie potrzebne

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    i jeszcze jedno...
    Potrzebujesz pliku syscalls.c który współgra ze skryptem linkera
    a o tym poczytaj na stronie Freddiego http://www.freddiechopin.info/
  • #8 10318968
    ninja_zlomiarz
    Poziom 10  
    Posty: 35
    sorry trochę źle się określiłem co do mojego problemu.

    Problem wygląda tak że zczytuję dane z przetwornika ADC i dane zczytywane są w momencie przerwania od timera co 5s.
    Typ danych zczytywanych z ADC to w programie main zmienna globalna:
    
    uint16_t ADC1Val;
    


    Teraz kiedy funkcja wchodzi do przerwania to chciałbym zapisać wartość tej zmiennej na kartę SD do tego służy funkcja f_write

    Definicja funkcji f_write:
    
    FRESULT f_write (FIL*, const void*, WORD, WORD*);    /* Write data to a file */
    


    Funkcja f_write oczekuje na wartość cont void*


    np. mogę wpisać takie coś i taki kod działa, wpisuje do pliku ciąg znaków "zawartosc pliku":
    fresult = f_write(&plik, "zawartość pliku", 15, &zapisanych_bajtow)




    i muszę teraz zamiast "zawartość pliku" jakoś wartość ADC1Val wstawić, próbowałem dla przykładu kombinować z charem tzn zrobiłem takie coś:

    
    char c[2];
    c[0]='a';
    c[1]='b';
    c[2]='c';
    
    fresult = f_write(&plik, c, 3, &zapisanych_bajtow)
    


    ale takie coś mimo że się kompiluje to przy debugowaniu program wchodzi w pętlę HardFault
  • #9 10327063
    kriss68
    Poziom 20  
    Posty: 369
    Pomógł: 40
    Ocena: 37
    Michalko12 podał Ci gotowe rozwiązanie, sprintifem zamieniasz wartość konwersji na tekst a potem tablice do której zapisywał sprintif przekazujesz do f_write i tyle. To co podałeś nie dziala bo tablica c ma dwa elementy a Ty operujesz na trzech.
  • #10 10327127
    ninja_zlomiarz
    Poziom 10  
    Posty: 35
    kriss68 napisał:
    Michalko12 podał Ci gotowe rozwiązanie, sprintifem zamieniasz wartość konwersji na tekst a potem tablice do której zapisywał sprintif przekazujesz do f_write i tyle. To co podałeś nie dziala bo tablica c ma dwa elementy a Ty operujesz na trzech.



    1. dziękuję za zainteresowanie :)

    2. niestety nie w tym leży problem, tu jest oczywiście błąd powinno być c[3] tak też robiłem tylko tu źle skopiowałem

    Tak wielkie podziękowania dla Michalko12 dzięki niemu działa mi sprintf tylko że właśnie nawet go nie wykorzystywałem skoro najprostsza tablica mi nie działa, najdziwniejsze jest to że jak wpiszę normalnie tekst w cudzysłowach to działa a jak podam zmienną tablicową to wchodzi w tą pętlę HardFault

    jedynie jak odwołam się bezpośrednio przez referencję do zmiennej ADC1Val czyli wykonam kod:

    fresult = f_write(&plik, &ADC1Val, sizeof(uint16_t), &zapisanych_bajtow);
    


    to coś zapisuje do pliku tylko nie są to liczby a jakieś dziwne symbole

    próbowałem ustawić tablicę c jako zmienną globalną ale również nie działa tzn kompiluje się ale wchodzi w pętlę HardFault

    jest tu jakiś dobry człowiek który mi udzieli odpowiedzi ? :) stawiam piwo w Krakowie ! za dobrą odpowiedź :)
  • #11 10327350
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    ninja_zlomiarz napisał:
    to coś zapisuje do pliku tylko nie są to liczby a jakieś dziwne symbole

    Bo zapisujesz BINARNĄ wartość, więc raczej ciężko oczekiwać, żeby ładnie wyglądała przedstawiona w postaci znaków odpowiadających tym wartościom, które akurat się trafiły.

    Skoro masz debugger, to w czym problem, żeby sobie podejrzeć w którym miejscu się wysypuje?

    A zamiast sprintf() polecam itoa() (np na mojej stronce do pobrania) - wielokrotnie mniejsze, wielokrotnie szybsze, nie wymaga 10000x innych rzeczy. Jeśli komuś nie potrzebne liczby zmiennoprzecinkowe to jak znalazł. Jest też do ściągnięcia uproszczony printf/sprintf() - obsługuje tylko liczby całkowite, znaki i stringi.

    4\/3!!
  • #12 10328192
    ninja_zlomiarz
    Poziom 10  
    Posty: 35
    Freddie Chopin napisał:

    Skoro masz debugger, to w czym problem, żeby sobie podejrzeć w którym miejscu się wysypuje?

    A zamiast sprintf() polecam itoa() (np na mojej stronce do pobrania) - wielokrotnie mniejsze, wielokrotnie szybsze, nie wymaga 10000x innych rzeczy. Jeśli komuś nie potrzebne liczby zmiennoprzecinkowe to jak znalazł. Jest też do ściągnięcia uproszczony printf/sprintf() - obsługuje tylko liczby całkowite, znaki i stringi.

    4\/3!!


    dzięki funkcje o których wspomniałeś już zassałem wcześniej i na pewno będą bardzo pomocne tylko jak rozwiążę zagadkę dlaczego mi się to wysypuje. Napisałem możliwie najprostszą funkcję dla przerwania czyli:

    void TIM1_CC_IRQHandler(void)
    {
    
    	extern FRESULT fresult;
    	extern FIL plik;
    	extern FILINFO plikInfo ;
    	extern DIR Dir;
    	extern FILINFO *p;
    	extern WORD zapisanych_bajtow;
    
    	char c[] = {'a','b','c'};
    
      	if (TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET)
      	{
    		ADC_ExternalTrigConvCmd(ADC1, ENABLE);
    		GPIO_WriteBit(GPIOC, GPIO_Pin_12,
    						(BitAction) ((1 - GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_12))));
    
    		fresult = f_write(&plik, c, sizeof(c), &zapisanych_bajtow);
    		//czyszczenie flagi
        	TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);
    
      	}
    }



    i wysypuje się podczas debugowania już w startupie bo nawet nie mogę programu włączyć.

    Taki komunikat wyświetlił mi debugger:

    Eclipse- deklaracja zmiennych globalnych i zewnetrznych


    czyli praktycznie niewiele, nie wiem co jeszcze mogę zrobić :/
  • #13 10328265
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    No ale czemu nie spróbować najpierw zapisu z innego miejsca niż przerwanie? A jak Ci się wysypuje przed wejściem do main(), to raczej problem jest zupełnie gdzie indziej...

    4\/3!!
  • #14 10329048
    ninja_zlomiarz
    Poziom 10  
    Posty: 35
    Freddie Chopin napisał:
    No ale czemu nie spróbować najpierw zapisu z innego miejsca niż przerwanie? A jak Ci się wysypuje przed wejściem do main(), to raczej problem jest zupełnie gdzie indziej...

    4\/3!!


    no nie wiem dlaczego tego wcześniej nie zrobiłem ... rzeczywiście masz racje problem leży gdzie indziej jeżeli w pliku main zadeklaruję tablicę i w pliku main następuje zapis to wszystko jest ok, problem zaczyna się kiedy chcę zapis przeprowadzić w przerwaniu.

    Jeżeli w przerwaniu zapisuje zwykły ciąg znaków w cudzysłowach do funkcji f_write to jest ok, ale jeżeli w przerwaniu deklaruję tablicę i chce ją zapisać do funkcji f_write to już mu się nie podoba. Może jest coś nie tak z deklaracją? Istnieje w Eclipsie możliwość podglądnięcia zmiennych lokalnych? bo globalnych to wiem że wystarczy dodać zmienną globalną i się już ją widzi.

    i czy istnieje taka możliwość że w przerwaniu od timera nie mogę robić takich rzeczy? i dlatego wpada w Hard Faulta?
  • Pomocny post
    #15 10329128
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Żeby widzieć zmienne lokalne trzeba być po pierwsze w danej funkcji, a pozatym dobrze ustawić optymalizację na 0 i wyłączyć usuwanie niepotrzebnego kodu i zmiennych.

    4\/3!!
  • Pomocny post
    #16 10334796
    kriss68
    Poziom 20  
    Posty: 369
    Pomógł: 40
    Ocena: 37
    Nie łatwiejsze i optymalniejsze będzie użycie f_printf z FatFs'a? Wystarczy włączyć jego obsługę w configu(_FS_READONLY == 0 _USE_STRFUNC == 1). I odpalasz to tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    W tym przerwaniu co podałeś to jakieś dziwne rzeczy robisz też :)
  • #17 10334944
    ninja_zlomiarz
    Poziom 10  
    Posty: 35
    kriss68 napisał:
    Nie łatwiejsze i optymalniejsze będzie użycie f_printf z FatFs'a? Wystarczy włączyć jego obsługę w configu(_FS_READONLY == 0 _USE_STRFUNC == 1). I odpalasz to tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    W tym przerwaniu co podałeś to jakieś dziwne rzeczy robisz też :)



    kriss68 dziękuję za radę, nie znałem tej funkcji, a odnośnie przerwania co konkretnie wydaje się dziwne? mówisz o zmiennych zewnętrznych?
  • REKLAMA
  • Pomocny post
    #18 10335805
    kriss68
    Poziom 20  
    Posty: 369
    Pomógł: 40
    Ocena: 37
    Chodzi mi o wyzwalanie konwersji ADC w przerwaniu - można do tego użyć timera bez przerwań ;) No i te wszystkie externy można by przenieść nad funkcję obsługi przerwania.
  • #19 10336888
    ninja_zlomiarz
    Poziom 10  
    Posty: 35
    dobra uporałem się z jednym problemem, trzeba było ustawić tablicę c globalną. Już tak robiłem ale miałem jeszcze inny błąd. Chyba chodzi o ustawienia stosów w linkerze?

    Czyli teraz moje przerwanie wygląda tak:

    void TIM1_CC_IRQHandler(void)
    {
    
      	if (TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET)
     	{
    
    		ADC_ExternalTrigConvCmd(ADC1, ENABLE);
    
                    fresult = f_write(&plik, c, 5, &zapisanych_bajtow);
    
        	        TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);
    
      	}
    }
    


    i działa jeżeli tablica c jest zmienną globalna i jest stała,

    tylko że ja potrzebuję do tablicy c wpisywać wartość z przetwornika analogowego która jest zmienna, do zamiany wartości z przetwornika na ciąg znaków zastosowałem funkcję itoa ze stronki freddiego w programie głównym main:

     	while(1)
      	{
    		ADC1Val = ADC_GetConversionValue(ADC1) * 0.807;
    		itoa( ADC1Val, c, 10 );
    		}
      	}



    no i teraz chcę żeby zapis na kartę następował cyklicznie czyli w tym przerwaniu od timera, tylko że jak tak zrobię to program wpada w HardFaulta

    jeżeli zapis na kartę następuje w pętli programu głównego czyli:

      	while(1)
      	{
    		ADC1Val = ADC_GetConversionValue(ADC1) * 0.807;
    		itoa( ADC1Val, c, 10 );
                    fresult = f_write(&plik, c, 5, &zapisanych_bajtow);
    		}
      	}


    to wszystko jest wporządku,


    ma ktoś pomysł ja to rozwiązać? muszę zmienić jkieś ustawienia w skrypcie Linkera? skrypt Linkera mam ze strnki freddiego
  • #21 10337794
    ninja_zlomiarz
    Poziom 10  
    Posty: 35
    Freddie Chopin napisał:
    Ustaw rozmiar stosu na przerwań - domyślnie w przykładzie jest 0, bo nie ma tam przerwań.

    4\/3!!



    dzięki teraz śmiga ale w sumie i tak to inaczej rozwiązałem ustawiam flagę w przerwaniu i sprawdzam w mainie ifem,

    mam jeszcze jeden mały problemik z funkcją itoa, moja funkcja wygląda tak:

      	while(1)
      	{
    		ADC1Val = ADC_GetConversionValue(ADC1);
    		if(data_ready)
    		{
    		itoa(ADC1Val, c, 10);
    		fresult = f_write(&plik, c, 5, &zapisanych_bajtow);
    		data_ready = 0;
    		}
      	}


    i teraz nie wiem dlaczego, ale jak debuguje krok po kroku to
    funkcja itoa prawidłowo odczytuje wartość ze zmiennej ADC1Val a jak
    puszcze 'play' i zatrzymam w jakimś miejscu to tablica c ma inną
    wartość niż aktualna wartość ADC1Val, wiecie co mogę na to poradzić?
    jakieś opóźnienie trzeba wstawić?
  • Pomocny post
    #22 10338117
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Wartość z ADC odczytujesz ciągle, a powinieneś ją odczytywać tak samo wewnątrz if'a. Do tego zależnie od tego w którym miejscu się zatrzymasz, może być już po nowym odczycie, ale przed nową konwersją - wtedy masz w zmiennej nową wartość, w tablicy starego stringa.

    4\/3!!
  • #23 10338971
    ninja_zlomiarz
    Poziom 10  
    Posty: 35
    Freddie Chopin napisał:
    Wartość z ADC odczytujesz ciągle, a powinieneś ją odczytywać tak samo wewnątrz if'a. Do tego zależnie od tego w którym miejscu się zatrzymasz, może być już po nowym odczycie, ale przed nową konwersją - wtedy masz w zmiennej nową wartość, w tablicy starego stringa.

    4\/3!!



    dobra wszystko działa, rzeczywiście namieszałem z tymi timerami

    mam ostatnie głupie pytanie :) obiecuję :)


    jak ustawić ten stos dla przerwań bo patrze na ten skrypt linkera i nie mam pojęcia co mógłbym zmienić?

    z góry dziękuję za odpowiedź :)
  • Pomocny post
    #24 10339841
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    /*
    +=============================================================================+
    | stacks sizes
    +=============================================================================+
    */
    
    /* Handler mode (core exceptions / interrupts) can use only main stack */
    /* Thread mode can use main stack (default) or process stack - selected in CONTROL special register */
    
    __main_stack_size = 0;
    __process_stack_size = 1024;


    Rozmiar w bajtach oczywiście.

    4\/3!!
  • #25 10344719
    ninja_zlomiarz
    Poziom 10  
    Posty: 35
    dzięki Freddie Chopin to już się wyjaśniło dlaczego tego nie widziałem: już to miałem ustawione na 1024. Problem miałem gdzie indziej i już go w sumie rozwiązałem.

    Mam jeszcze takie pytanie odnośnie sprawdzenia ile czasu zajmuje przerwanie. Mam takie przerwanie wyzwalane TIM1:

    void TIM1_UP_IRQHandler(void)
    {
    		// Start przetwarzania przetwornika ADC
    		ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    		ADC1Val = (ADC_GetConversionValue(ADC1));
    		itoa(ADC1Val, c, 10);
    		//znaki końca linii
    		//c[5]='\t';
    		c[5]='\r';
    		c[6]='\n';
    		//zapis stringa do pliku
    		fresult = f_write(&plik, c, 7, &zapisanych_bajtow);
    		//zapis danych z bufora
    		fresult=f_sync(&plik);
    TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
    ile_czasu=(TIM_GetCounter(TIM1));
    }
    



    no i ile czasu zajmuje przerwanie sprawdzam tak że na końcu przerwania pobieram sobie aktualną wartość licznika TIM1 (tak mi się wydaje) do zmiennej ile_czasu dobrze myślę? co myślicie o takim sprawdzeniu ile czasu zajmuje przerwanie? Da się to jakoś optymalniej zrobić?

    Robię to w celu obliczenia czy mikrokontroler wyrobi z zapisywaniem danych na kartę przy próbkowaniu około 166 MHz.
  • #27 10345295
    ninja_zlomiarz
    Poziom 10  
    Posty: 35
    Freddie Chopin napisał:

    Przerwanie czy odczyt ile ono trwa?
    4\/3!!



    a sorki trochę się nie sprecyzowałem, chodzi mi oczywiście o odczyt, no jak teraz na to patrze to głupio to jest zrobione, bo ja to sprawdzałem przez ustawienie breakpointa po zmiennej ile czas i sprawdzałem ile aktualnie wynosi wartość tej zmiennej (czyli countera licznika). W sumie robiłem to też przez debugger więc pewnie to też spowolniło proces.

    Jak to najelpiej zrobić? Może poprzez wysyłanie informacji przez UART? i czy wogóle robić to tym GetCounter czy jest jakiś sprytniejszy sposób?
  • #28 10345983
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Tak jak robisz jest OK - szybciej już nie będzie. Miej tylko świadomość, że jak układ zostaje zatrzymany przez debugger (stoi na breakpoincie), to liczniki nadal się kręcą - da się to przestawić w którymś rejestrze.

    4\/3!!

Podsumowanie tematu

✨ W dyskusji poruszono problem deklaracji zmiennych globalnych i zewnętrznych w programie napisanym dla mikrokontrolera STM32, w kontekście obsługi przerwań od timera. Użytkownik miał trudności z dostępem do zmiennych globalnych w różnych plikach źródłowych, co prowadziło do błędów kompilacji. Udzielono wskazówek dotyczących użycia słowa kluczowego `extern` do deklaracji zmiennych w innych plikach oraz konwersji wartości zmiennych na format tekstowy do zapisu na karcie SD. Zasugerowano również użycie funkcji `f_printf` z biblioteki FatFs do uproszczenia zapisu danych. Problemy z pętlą HardFault były związane z niewłaściwym zarządzaniem pamięcią i ustawieniami stosu. Użytkownik ostatecznie rozwiązał problemy z przerwaniami i konwersją danych, a także uzyskał pomoc w zakresie ustawień stosu w linkerze.
REKLAMA