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

STM32F0 - STM32F0Discovery Przerabianie przykładu, wywala błąd w core_cmInstr.h

SeerKaza 11 Paź 2013 21:10 4284 24
  • #1 12833516
    SeerKaza
    Poziom 20  
    Posty: 468
    Pomógł: 17
    Ocena: 6
    Witam

    Dostałem zadanie od wykładowcy wy wykonać pewien projekt na STM32f0 jako że KEILA nie trawie próbuje zmienić przykład freediego tak by pasował do tej płytki.
    Wstawiłem pliki:
    core_cm0.h
    core_cmFunc.h
    core_cmInstr.h
    stm32f0xx.h
    system_stm32f0xx.h
    Plus startup eddiego od LPC1114 oraz zmiany w linkerze rozmiarów pamięci plus zmiany w funkci main i chyba gpio by pasowały do peryferów tego układu. Niestety mam problem wywala mi błąd w core_cmInstr.h
    Description Resource Path Location Type
    sorry, unimplemented: Thumb-1 hard-float VFP ABI	core_cmInstr.h	/stm32f4_blink_led/inc	line 539	C/C++ Problem


    Nie podoba mu się otwarcie nawiasu tej funkcji:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Jesli usunę tą funkcje błąd pojawia się w kolejnej. Nie wiem co robić zaktualizowałem EDGA ale to nie pomaga. Może jakieś sugestie ??
  • Pomocny post
    #4 12833701
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Wrzuć pełen log kompilacji po zrobieniu clean. Log kompilacji z zakładki "console", a nie jakieś nic nie mówiące obrazki.

    4\/3!!
  • #5 12833722
    SeerKaza
    Poziom 20  
    Posty: 468
    Pomógł: 17
    Ocena: 6
    make all
    Assembling file: startup.S
    arm-none-eabi-gcc -x assembler-with-cpp -c -mcpu=cortex-m0 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -ffast-math -g -ggdb3 -Wa,-amhls=out/startup.lst -DSTM32F0XX -MD -MP -MF out/startup.d -I. -Iinc startup.S -o out/startup.o

    Compiling file: gpio.c
    arm-none-eabi-gcc -c -mcpu=cortex-m0 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -ffast-math -O0 -ffunction-sections -fdata-sections -Wall -Wstrict-prototypes -Wextra -std=gnu89 -g -ggdb3 -fverbose-asm -Wa,-ahlms=out/gpio.lst -DSTM32F0XX -MD -MP -MF out/gpio.d -I. -Iinc gpio.c -o out/gpio.o
    In file included from inc/core_cm0.h:95:0,
    from inc/stm32f0xx.h:246,
    from gpio.c:32:
    inc/core_cmInstr.h: In function '__REV':
    inc/core_cmInstr.h:539:1: sorry, unimplemented: Thumb-1 hard-float VFP ABI
    make: *** [out/gpio.o] Error 1

    -------------------------EDIT--------------------------------------
    # core flags
    CORE_FLAGS = -mcpu=$(CORE) -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -ffast-math
    czyżbym w tej cześci makefila powinienem coś zmienic odnośnie math i float ??
    ------------------------EDIT-----------------------------------------
    zwróciliście mi uwagę na consolę i znalazł się błąd zmieniłem powyższa linijke na same
    CORE_FLAGS = -mcpu=$(CORE) -mthumb
    i działa
    DZIĘKI
  • Pomocny post
    #6 12833744
    michcior
    Poziom 30  
    Posty: 1132
    Pomógł: 159
    Ocena: 462
    -mfloat-abi=hard

    chyba nie-bardzo.

    Cytat:
    -mfloat-abi=name
    Specifies which floating-point ABI to use. Permissible values are: ‘soft’, ‘softfp’ and ‘hard’.

    Specifying ‘soft’ causes GCC to generate output containing library calls for floating-point operations. ‘softfp’ allows the generation of code using hardware floating-point instructions, but still uses the soft-float calling conventions. ‘hard’ allows generation of floating-point instructions and uses FPU-specific calling conventions.

    The default depends on the specific target configuration. Note that the hard-float and soft-float ABIs are not link-compatible; you must compile your entire program with the same ABI, and link with a compatible set of libraries.
  • #7 12833753
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Wziąłeś przykład dla STM32F4 i przerabiasz go dla STM32F0, naprawdę prościej byłoby przerobić przykład z LPC1114 na taki dla STM32F0, bo przynajmniej opcje kompilatora i kilka plików nagłówkowych byłoby od razu OK.

    4\/3!!
  • #8 12833780
    SeerKaza
    Poziom 20  
    Posty: 468
    Pomógł: 17
    Ocena: 6
    Ale LPC to inny producent więc czy niebyło by więcej przerbiania z gpio itd
  • #11 12833852
    SeerKaza
    Poziom 20  
    Posty: 468
    Pomógł: 17
    Ocena: 6
    Kompilacja poszła teraz problemiki z uruchomieniem
    STM32F0 - STM32F0Discovery Przerabianie przykładu, wywala błąd w core_cmInstr.h
  • #12 12833972
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Zacznij od użycia czegoś nowszego niż OpenOCD sprzed 1.5 roku i przestań wrzucać obrazki na których nic nie ma, zamiast logów z programów i Twoich konfiguracji.

    4\/3!!
  • #13 12834991
    SeerKaza
    Poziom 20  
    Posty: 468
    Pomógł: 17
    Ocena: 6
    OpenOCD zaktualizowanie tak jak kompilator wcześniej.

    Przerabiam przykład od początku teraz na bazie tego o którym mówiłeś LPC Będe wklejał tutaj co dokładnie przerabiam. Jeśli coś robię źle to mam nadzieje że mnie poprawicie. Jeśli dobrze to mam nadzieje że komuś się przyda.

    1.Import projektu lpc1114_blink_led i rename na stm32f0_blink_led
    2. Zmiany w makefile:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    3. Rename i zmiany w linkerze:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    4. Zmiana plików do LPC na
    stm32f0xx.h
    system_stm32f0xx.h
    5. Wstawienie przerobionej od STM32f4 tablicy wektorów:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    ciąg dalszy za kilka godzin

    Chce podmienić pliki z folderu hdr oraz config gpio i main na poprzerabiane od przykładu stm32f1

    Dodano po 3 [godziny] 59 [minuty]:

    6. Zmiana plików w folderze HDR
    hdr_gpio_masked_access.h
    hdr_syscon.h
    na
    hdr_bitband.h
    hdr_gpio.h (EDIT/ZMIANA --- GPIO f0 ma podobne z f4 a nie z f1
    hdr_rcc.h
    Wklejone bez zmian i mam małe pytanko czy bitband jest taki sam (po przejrzeniu dokumentacji organizacja pamieci w STM32F jest bardzo podobna ) I co z hdr_special_registers.h który użyć i czy trzeba przerabiać ??

    7. Wstawienie przerobionego configa z STM32F1
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    8.Wstawienie plików GPIO z f4 z f1 się nie nadaje bo tam GPIO są pod APB a tutaj jak i w f4 pod AHB
    W gpio.h zmiana tylko includa na
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    w gpio.c zmiana includa i zamiast AHB1 samo AHB wszędzie plus usunięcie nadmiarowych GPIO (E G H)
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    9. No to main
    Przerobiony od f4 który jest bardziej podobny do f0 od f4 (szczególnie jeśli chodzi o peryferia) Jednak flash wait states i pll_start wzięty od f1. W wait states przerobiona maksymalna wartośc na 1 a nie 2 a w pll start usunięty dzielnik na ahb (idzie tyle ile wyszło z plla)
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    I to chyba wszystko z kodu co muszę przerobić. Mam nadzieje że ktoś mnie utwierdzi w przekonaniu i zrobię pierwszy build i wkleję wynik kompilacji( czekam z tym by nie narobić śmieci w projekcie. ) Co do openOCD wystarczy zmienić f4 na f0 w argumencie a w debugger config chyba tylko jak się nie mylę nazwę projektu. Ale tym się już będe głowił jak przejdzie kompilacja

    Dodano po 15 [minuty]:

    17:03:24 **** Incremental Build of configuration Default for project stm32f0_blink_led ****
    make all 
    Assembling file: startup.S
    arm-none-eabi-gcc -x assembler-with-cpp -c -mcpu=cortex-m0 -mthumb -g -ggdb3 -Wa,-amhls=out/startup.lst  -MD -MP -MF out/startup.d -I.  startup.S -o out/startup.o
     
    Compiling file: gpio.c
    arm-none-eabi-gcc -c -mcpu=cortex-m0 -mthumb -O0 -ffunction-sections -fdata-sections -Wall -Wstrict-prototypes -Wextra -std=gnu89 -g -ggdb3 -fverbose-asm -Wa,-ahlms=out/gpio.lst  -MD -MP -MF out/gpio.d -I.  gpio.c -o out/gpio.o
     
    Compiling file: main.c
    arm-none-eabi-gcc -c -mcpu=cortex-m0 -mthumb -O0 -ffunction-sections -fdata-sections -Wall -Wstrict-prototypes -Wextra -std=gnu89 -g -ggdb3 -fverbose-asm -Wa,-ahlms=out/main.lst  -MD -MP -MF out/main.d -I.  main.c -o out/main.o
     
    Compiling file: vectors.c
    arm-none-eabi-gcc -c -mcpu=cortex-m0 -mthumb -O0 -ffunction-sections -fdata-sections -Wall -Wstrict-prototypes -Wextra -std=gnu89 -g -ggdb3 -fverbose-asm -Wa,-ahlms=out/vectors.lst  -MD -MP -MF out/vectors.d -I.  vectors.c -o out/vectors.o
     
    Linking target: out/stm32f0_blink_led.elf
    arm-none-eabi-g++ -mcpu=cortex-m0 -mthumb -TSTM32F0x1_rom.ld -g -Wl,-Map=out/stm32f0_blink_led.map,--cref,--no-warn-mismatch -Wl,--gc-sections -nostartfiles  out/startup.o out/gpio.o out/main.o out/vectors.o    -o out/stm32f0_blink_led.elf
     
    Creating extended listing: out/stm32f0_blink_led.lss
    arm-none-eabi-objdump -S out/stm32f0_blink_led.elf > out/stm32f0_blink_led.lss
     
    Creating memory dump: out/stm32f0_blink_led.dmp
    arm-none-eabi-objdump -x --syms out/stm32f0_blink_led.elf > out/stm32f0_blink_led.dmp
     
    Creating IHEX image: out/stm32f0_blink_led.hex
    arm-none-eabi-objcopy -O ihex out/stm32f0_blink_led.elf out/stm32f0_blink_led.hex
     
    Creating binary image: out/stm32f0_blink_led.bin
    arm-none-eabi-objcopy -O binary out/stm32f0_blink_led.elf out/stm32f0_blink_led.bin
     
    Size of modules:
    arm-none-eabi-size -B -t --common out/startup.o out/gpio.o out/main.o out/vectors.o   
       text	   data	    bss	    dec	    hex	filename
        100	      0	      0	    100	     64	out/startup.o
        376	      0	      0	    376	    178	out/gpio.o
        344	      0	      0	    344	    158	out/main.o
        160	      0	      0	    160	     a0	out/vectors.o
        980	      0	      0	    980	    3d4	(TOTALS)
     
    Size of target .elf file:
    arm-none-eabi-size -B out/stm32f0_blink_led.elf
       text	   data	    bss	    dec	    hex	filename
       1140	      0	   1024	   2164	    874	out/stm32f0_blink_led.elf
     
    
    17:03:26 Build Finished (took 2s.104ms)


    Dodano po 12 [minuty]:

    Jest ok po prostu się nie odświeżyło z automatu mamy pliki out. Czas wgrać na płytkę.

    Dodano po 18 [minuty]:

    Sprawa wygląda tak program załadowany. Debuguje go prok po kroku. System init i gpioinit przechodzi nastpenie wchodzi do pllstart i zaraz po HSE_on wchodzi do default handler i w kolejnym kroku się wiesza i jest że nie może odczytać pamięci

    Dodano po 38 [minuty]:

    Kolejny problem nie działa bitband pomimo że cortex0 z tego co wiem też go obsługuje. Dodatkowo w pll start nie chce wyliczyć mul chyba nie da rady podzielić ulongów

    Dodano po 21 [minuty]:

    Znalazłem w ARM information centre rozwiązanie. Cortex M0 nie ma bitbandu. Ale jest
    3.11. AHB bit-band wrapper for Cortex-M0 processor
    The AHB bit-band wrapper, ahb_bitband.v, provides the bit-band functionality for the Cortex-M0 processor. Figure 3.19 shows the AHB bit-band wrapper module for the Cortex-M0 processor.
    który emuluje bitbandy tylko jak go zaimplementować ??

    Dodano po 13 [minuty]:

    Pomyłka ten wrapper to tylko w Cortex-M System Design Kit a to chyba jest projektowanie fizyczne układu a nie programowe. Czyli musze cały bitbanding usunąc z projektu i tradycyjnie zmieniac rejestry

    Dodano po 17 [minuty]:

    EUREKA!!!! Działa wystarczyło wywalić bitbandy.

    Poprzerabiam komentarze i myślę jutro lub pojutrze wstawię paczuszkę.
  • #14 12836212
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    SeerKaza napisał:
    hdr_bitband.h

    Cortex-M0 nie obsługuje bitbandingu. Tak wiec wszystkie operacje na "zmiennych" bitband na 99% spowodują hard-fault. Rozchodzi się więc o WSZYSTKIE dostepy do rejestrów i dostęp do LEDa.

    SeerKaza napisał:
    Co do openOCD wystarczy zmienić f4 na f0 w argumencie a w debugger config chyba tylko jak się nie mylę nazwę projektu.

    Tak jest.

    No widzę że w sumie sam sobie odpowiedziałeś (;

    4\/3!!
  • #15 12836383
    SeerKaza
    Poziom 20  
    Posty: 468
    Pomógł: 17
    Ocena: 6
    No pozostał problem z podzieleniem
    mul = frequency / crystal;
    musiałem wpisać na sztywno 6. Czy m0 nie da rady podzielić 2 liczb 32 bitowych ??

    Dodano po 6 [minuty]:

    Can't find a source file at "/home/freddie/bleeding-edge-toolchain/x64/src/gcc/libgcc/config/arm/lib1funcs.S"
    Locate the file or edit the source lookup path to include its location.
  • #16 12836543
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    SeerKaza napisał:
    No pozostał problem z podzieleniem
    mul = frequency / crystal;
    musiałem wpisać na sztywno 6. Czy m0 nie da rady podzielić 2 liczb 32 bitowych ??

    Na jakiej podstawie stwierdzasz, że tego nie robi? Bo jeśli na podstawie debuggowania programu który ma włączoną optymalizację, to niestety nie ma to żadnej wiarygodności.

    SeerKaza napisał:
    Can't find a source file at "/home/freddie/bleeding-edge-toolchain/x64/src/gcc/libgcc/config/arm/lib1funcs.S"
    Locate the file or edit the source lookup path to include its location.

    Jak chcesz debuggować kod bibliotek to chyba logiczne jest, że kod tychże bibliotek musisz debuggerowi dostarczyć? (; Albo zadowolić się assemblerem.

    4\/3!!
  • #17 12836595
    SeerKaza
    Poziom 20  
    Posty: 468
    Pomógł: 17
    Ocena: 6
    # optimization flags ("-O0" - no optimization, "-O1" - optimize, "-O2" -
    # optimize even more, "-Os" - optimize for size or "-O3" - optimize yet more)
    OPTIMIZATION = -O0
    Optymalizacja z tego co rozumiem jest wyłączona
    Freddie Chopin napisał:

    SeerKaza napisał:
    Can't find a source file at "/home/freddie/bleeding-edge-toolchain/x64/src/gcc/libgcc/config/arm/lib1funcs.S"
    Locate the file or edit the source lookup path to include its location.

    Jak chcesz debuggować kod bibliotek to chyba logiczne jest, że kod tychże bibliotek musisz debuggerowi dostarczyć? (; Albo zadowolić się assemblerem.


    No w include mam link do bleeding edge w pathu tak samo więc jak mam dodać te biblioteki
  • #18 12836644
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    SeerKaza napisał:
    No w include mam link do bleeding edge w pathu tak samo więc jak mam dodać te biblioteki

    W ścieżce toolchaina znajdują się tylko nagłówki i skompilowane pliki. Jak chcesz debuggować biblioteki, to musisz mieć na dysku ŹRÓDŁA tychże bibliotek - gcc i newlib.

    SeerKaza napisał:
    Optymalizacja z tego co rozumiem jest wyłączona

    Ponownie więc pytam na jakiej podstawie twierdzisz, że układ "nie potrafi tego podzielić".

    4\/3!!
  • #19 12836674
    SeerKaza
    Poziom 20  
    Posty: 468
    Pomógł: 17
    Ocena: 6
    bo jak jest mul = frequency / crystal; to się wykrzacza a jak napisze mul = 6 to jest ok

    Dodano po 2 [minuty]:

    mea culpa program idzie jednak dalej tylko że podglądu niema a wyglądało jak warning temu mnie zmyliło
  • #20 12860872
    SeerKaza
    Poziom 20  
    Posty: 468
    Pomógł: 17
    Ocena: 6
    Próbuje uruchomić przerwania:
    vector.c wygląda tak
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Uruchomiłem timer. Jest on w trybie PWM miga sobie diodą działa i jest szczęśliwym timerem. Chciałem zobaczyć czy działają przerwania. A tu pupa wywala mnie do default handlera main wygląda tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Czy o czymś zapomniałem oczywiście main stack jest ustawiony na 1024 dokładnie tyle samo co drugi
  • #21 12861180
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    A tablica wektorów na 100% poprawna? Jak podejrzysz w pliku .lss wektory, to pod właściwym adresem jest adres Twojej funkcji obsługi?

    P.S. Ten plik na pewno jest main.c, a nie main.cpp? Bo w tym drugim przypadku faktycznie uruchomienie przerwań wymaga kilku wciśnięć klawiszy więcej.

    4\/3!!
  • #22 12861210
    SeerKaza
    Poziom 20  
    Posty: 468
    Pomógł: 17
    Ocena: 6
    tablica wektorów sprawdzana kilka razy

    Kod: text
    Zaloguj się, aby zobaczyć kod


    z tego co widzę to 19 przerwanie czyli moje prowadzi pod inny adres niż wszystkie

    Dodano po 3 [minuty]:

    Kod: text
    Zaloguj się, aby zobaczyć kod

    wskazuje na adres pomiędzy dwoma rozkazami
  • Pomocny post
    #23 12861593
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    SeerKaza napisał:
    z tego co widzę to 19 przerwanie czyli moje prowadzi pod inny adres niż wszystkie

    No tak, tyle ze to przerwanie jest "19-te", tyle że przed nim jest kilka systemowych. Wg tabelki w manualu tych układów, adres wektora przerwań dla TIM14 to 0x8c, natomiast u Ciebie wektor jest pod 0x68...

    Błąd masz taki, że za bardzo w nią zaingerowałeś... Zwróć uwagę, że u Ciebie pomiędzy HardFault a SVCall nie ma nic. W rzeczywistości jest tam 7 zarezerwowanych wektorów (popatrz na adresy w tabelce i priorytety)... Początek tablicy wektorów (do SysTick włącznie) jest IDENTYCZNY dla każdego Cortexa - jedyna różnica jest taka, że niektóre układy niektórych przerwań nie obsługują, co nie znaczy że pozycja przez nie używana "znika". Innymi słowy - SysTick _M_U_S_I_ mieć wektor na adresie 0x3c.

    4\/3!!
  • #24 12861645
    michcior
    Poziom 30  
    Posty: 1132
    Pomógł: 159
    Ocena: 462
    Cytat:
    Note
    Vector table entries are ARM/Thumb interworking compatible.
    This causes bit [0] of the vector value to load into the EPSR T-bit on exception entry. Creating a table entry with bit [0] clear generates an INVSTATE fault on the first instruction of the handler corresponding to this vector.


    Binarnie 5 to 101, czyli bit 0 jest 1. Jak widać z informacji to wcale nie jest "adres pomiędzy"! W ARMach to zawsze był trik na zmianę trybu pomiędzy 16 a 32 bitowym.
    Jeśli myślisz poważnie o programowania ARM-ów, to lektura "Technical Reference Manual" może być dobra inwestycja. [/quote]
  • #25 12862018
    SeerKaza
    Poziom 20  
    Posty: 468
    Pomógł: 17
    Ocena: 6
    Dzięki freedi miałeś racje. Patrzyłem na kolejność przerwań w tabeli f0 ale nie na adresy. Aby zapełnić luki i poprzesuwać adresy dodałem brakujące reserved handler

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


    Dodano po 11 [minuty]:

    Teraz tylko muszę rozwiązać skąd mi przerwań multum nadchodzi i w nierównych odstępach od timera. Bo pwm wyprowadzone jest na jedną diodę a przerwanie zmienia stan innej diody. I działa tak że 2 diody się zapalają razem raz jedna szybciej gaśnie raz druga. a raz ta na przerwaniu zapala się razem z tą od PWMu i w ułamku sekundy gaśnie. A ma tą taką sekwencje:
    Przerwaniowa gaśnie pierwsza>PWM gaśnie pierwsza>przerwaniowa zapala się na chwile i od początku.
    Więc oprócz przerwania wtedy kiedy dioda się zapala czyli timer załadował ponownie rejestry Pomiędzy z różną prędkością pojawia się dodatkowe przerwanie

    Dodano po 14 [minuty]:

    Przez przypadek wyklikałem by debug szedł dalej mimo błędu jak to ponownie załączyć by pytało

    Dodano po 22 [minuty]:

    Dobra znalazłem winnego. w pętli głównej użyłem ! zamiast ~ przy modyfikowaniu rejestru GPIO i to wpływało na gaszenie diody. Znalazłem tez jak przywrócić ustawienia więc wszystko jest ok.

Podsumowanie tematu

✨ Użytkownik napotkał problem podczas przerabiania przykładu dla STM32F0, próbując dostosować kod z STM32F4 oraz LPC1114. Błąd w pliku core_cmInstr.h związany z funkcją __REV wskazuje na nieobsługiwaną ABI dla hard-float. Użytkownicy sugerują, aby sprawdzić opcje kompilatora, w tym flagę -mfloat-abi=hard, oraz rozważyć użycie przykładu z LPC1114 jako bazy. Po kilku próbach i aktualizacjach narzędzi, użytkownik zaczął przerabiać projekt od podstaw, wprowadzając zmiany w makefile oraz tablicy wektorów, co doprowadziło do dalszych postępów w projekcie. Problemy z przerwaniami i dostępem do rejestrów również były omawiane, z naciskiem na poprawność tablicy wektorów.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA