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

[STM32F4][C/GCC]kompilacja CMSIS DSP w projekcie Makefile

kk.krz 14 Mar 2018 14:09 2436 41
Najlepsze odpowiedzi

Jak poprawnie dołączyć bibliotekę CMSIS DSP w projekcie Makefile dla STM32F4, żeby linker nie zgłaszał błędów?

Biblioteki statyczne muszą być podane na samym końcu linkowania, po wszystkich plikach obiektowych — inaczej linker ich nie podniesie [#17102427] W Twojej komendzie linkera zbędne są też opcje `-I` i `-D`, bo linker nie uruchamia preprocesora, a `-ffast-math` zwykle nie ma tu znaczenia [#17102464] Jeśli używasz `-Wl,--gc-sections`, to przy kompilacji musisz mieć także `-ffunction-sections` i `-fdata-sections`, inaczej odcinanie nieużywanego kodu nie zadziała poprawnie [#17102464][#17102529] Po tej zmianie linkowanie zaczęło działać [#17102427]
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA
  • #1 17102379
    kk.krz
    Poziom 4  
    Posty: 186
    Ocena: 2
    Jest problem z dołączeniem bibliotek DSP z CMSIS. W main jest

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


    Powiedzmy, że chcę użyć:

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


    W Makefile ustawiam min.

    Kod: Bash
    Zaloguj się, aby zobaczyć kod


    ... i otrzymuję:

    Kod: Bash
    Zaloguj się, aby zobaczyć kod


    chociaż:

    Kod: Bash
    Zaloguj się, aby zobaczyć kod


    i

    Kod: Bash
    Zaloguj się, aby zobaczyć kod


    Czy ktoś ma pomysł co jest nie tak?
  • REKLAMA
  • #2 17102399
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    kk.krz napisał:
    CMSIS_LIB=-larm_cortexM4l_math

    kk.krz napisał:
    kk@kk:~/eclipse-workspace/CMSIS/Lib/GCC$ nm --demangle --extern-only --defined-only libarm_cortexM4lf_math.a |grep cfft_f32

    kk.krz napisał:
    nm --demangle --extern-only --defined-only libarm_cortexM4lf_math.a |grep arm_cfft_sR_f32_len1024

    Znajdź różnicę.
  • REKLAMA
  • Pomocny post
    #4 17102427
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Twoja linijka od linkowania jest błędna. Biblioteki _MUSZĄ_ być na samym końcu, po wszystkich plikach obiektowych - tak działa linker. W ogóle to połowa flag które przekazujesz linkerowi nie ma dla niego znaczenia.
  • Pomocny post
    #6 17102464
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    W pierwszym poście wrzuciłeś:

    /usr/local/share/bleeding-edge-toolchain-180127/installNative/bin//arm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -T STM32F446RETx_FLASH.ld -Wl,--gc-sections -lm -mfloat-abi=hard -mfpu=fpv4-sp-d16 -DSTM32F446xx -ffast-math -DARM_MATH_CM4 -I../CMSIS/Include -L../CMSIS/Lib/GCC -larm_cortexM4l_math output/system_config.o output/system_stm32f4xx.o output/main.o output/startup_stm32f446xx.o -o output/program.elf

    Wszystkie -I oraz -D są zbędne, bo linker przecież nie uruchamia preprocesora. Na 99% -ffast-math również. Dodatkowo przekazywane -Wl,--gc-sections nic nie robi, bo przy kompilacji nie masz flag -ffunction-sections i -fdata-sections.
  • REKLAMA
  • #8 17102487
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    kk.krz napisał:
    Dzięki...pomogło. Zrobiłem tak:

    Tak z ciekawości, pod dołączeniu statycznej biblioteki "math", o ile pamięci programu zwiększa się Twój kod?
  • #9 17102529
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    kk.krz napisał:
    Z tym, że brak -Wl,--gc-sections powoduje

    /home/kk/Pobrane/bleeding-edge-toolchain-180127/sources/newlib-3.0.0/newlib/libc/stdlib/exit.c:64: undefined reference to `_exit'

    Bo newlib jest skompilowany z flagami -ffunction-sections -fdata-sections, tak samo powinien być kompilowany Twój program, gdyż te flagi mają same zalety [;
  • #11 17102996
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    kk.krz napisał:
    FCh - tak zrobie. Dzięki za pomoc.

    simw - o której bibliotece mówisz? tę kompilowaną -lm czy z CMSIS - arm_math.h?


    Mam nadzieję, że czegoś nie przekręcam :) ale wpisy:
    "libarm_cortexM4lf_math.a" oraz "-larm_cortexM4l_math" dołączają statyczną bibliotekę matematyczną dla STM32 i wtedy w projekcie nie musisz kompilować całych źródeł (gałęzi) tejże biblioteki. Samo "arm_math.h" to deklaracje funkcji, stałych itp.

    Pytanie moje wzięło się stąd, że moje próby dołączenia tejże biblioteki zawsze kończyły się zajętością ponad 256KB pamięci programu co nawet dla "wypasionego" F103 kończyło się fiaskiem :)

    Dopiero żmudne dostrajanie źródeł i eliminacja niepotrzebnych składowych (głównie nieużywanych tablic) pozwalało na zejście do ok 60 KB - chodziło o poprawne obliczenie transformaty na float32. To były oczywiście takie nieśmiałe próby laika, żeby coś z tego poskładać, dlatego pytam, bo nadal mnie to mocno ciekawi, na ile to była wina nieudolnego użytkownika, a na ile "wina" samej biblioteki, która jak mniemam zorientowana jest na szybkość działania, kosztem objętości kodu.
    Można łatwo podglądnąć pliki źródłowe arm_common_tables.c i zobaczyć wielkości generowanych tablic.
  • #12 17103084
    kk.krz
    Poziom 4  
    Posty: 186
    Ocena: 2
    Nie wiem czy zrobie Ci to profesjonalnie, bo wciąż się uczę, ale
    z dolinkowaną biblioteką -larm_cortexM4lf_math jest tak:

    Kod: Bash
    Zaloguj się, aby zobaczyć kod


    a bez niej jest tak:
    Kod: Bash
    Zaloguj się, aby zobaczyć kod


    Jeśli mogę jeszcze coś dla Ciebie zrobić, to pisz śmiało.
    Nadmieniam, że w moim projekcie nie korzystam z tych bibliotek na razie.
    Zmiana wielkości wynika jedynie z samego dolinkowania.

    Opcje kompilacji wkleiłem powyżej.

    Dodano po 11 [minuty]:

    Też do transformaty ostatnio walczyłem na kiss_fft i tam - jak sądzę - alokacja miejsca na operacje obliczeniowe to była dziesięciokrotna wielkość wejściowej tablicy. Czyli biorąc pod uwagę, że potrzebowałem
    jeszcze ifft dochodziła taka sama druga alokacja. No i oczywiście tablice z danymi...RAMu to to brało sporo. I wcale nie
    było takie szybkie. 256x256 gray obrazek -> fft , 256x256 gray sample -> fft, potem mnożenie tego co wyszło
    a następnie ifft tego co wyszło z mnożenia na 216MHz STM32F7 trwało ok. 1s. Ale tam się przynajmniej FLASHem nie martwiłem...1024 ma to to. Kissem się już pobawiłem...teraz zobacze co umie CMSIS DSP ...albo inaczej, co ja umiem na CMSIS DSP :)
  • #13 17103133
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    kk.krz napisał:
    Nie wiem czy zrobie Ci to profesjonalnie, bo wciąż się uczę, ale
    z dolinkowaną biblioteką -larm_cortexM4lf_math jest tak:

    Kod: Bash
    Zaloguj się, aby zobaczyć kod


    a bez niej jest tak:
    Kod: Bash
    Zaloguj się, aby zobaczyć kod


    Jeśli mogę jeszcze coś dla Ciebie zrobić, to pisz śmiało.

    Dzięki bardzo.
    Wyniki, które podałeś są raczej jasne dla mnie, aczkolwiek podejrzewam, że dopiero w momencie próby wywołania obliczeń transformaty w kodzie, odpowiednie tablice zostaną umieszczone w pamięci programu, zatem dopóki nic z dziedziny obliczeń FFT nie dopiszesz, to objętość kodu będzie znośna. Takie są moje obserwacje przy próbie działania z tą biblioteką.

    Póki co to moje pytanie nie jest jakieś szczególnie istotne obecnie, zapytałem przy okazji, zwróć na to uwagę, bo może jednak jest tak jak napisałem, wiedza ta może i Tobie zaoszczędzić niepotrzebnego zastanawiania się, co tyle "wyżarło" tego miejsca w pamięci :)
  • #14 17103179
    _lazor_
    VIP Zasłużony dla elektroda
    Posty: 3795
    Pomógł: 259
    Ocena: 1132
    Ja mogę dorzucić swoją mapę gdzie używam iar_cortexM4lf_math:
    [STM32F4][C/GCC]kompilacja CMSIS DSP w projekcie Makefile
  • #15 17105080
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    _lazor_ napisał:
    Ja mogę dorzucić swoją mapę gdzie używam iar_cortexM4lf_math:


    Tutaj to już nie za bardzo mogę to zinterpretować. Skoro mamy tutaj bibliotekę statyczną, może ktoś to potwierdzić, że dobrze to nazywam :), to w niej, w module "common_tables.o" powinny już wszystkie tablice być "wpisane". Można podejrzeć arm_common_tables.c w bibliotece CMSIS, a tam są całkiem spore tablice o wielkości 1024 czy nawet 4096 elementów 2 bajtowych:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Wydaje mi się zatem dość mała wartość 304 jest zbyta mała.
    Jest to dla mnie bardzo zagadkowe :)
  • REKLAMA
  • #16 17105093
    Konto nie istnieje
    Konto nie istnieje  
  • #17 17105196
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    Piotrus_999 napisał:
    A czy uważasz że wszystko jest linkowane?

    Twoje pytanie sporo sugeruje.
    Jakoś bylem zafiksowany na to, że w ten sposób dołączany kod musi być "wrzucony" w całości, ale cóż błądzenie to rzecz ludzka, sporo wody jeszcze upłynie zanim takie mechanizmy będą dla mnie zrozumiałe :)
    Cały czas mam przed oczami ten goły kod, który do STM32F103VCTx się nie mieścił, ale tak to jest jak się pracuje z gotowcami, bez zrozumienia.

    Dodano po 1 [godziny] 15 [minuty]:

    Zrobiłem kolejne proste testy. Z biblioteką statyczną oraz z wyrzeźbionymi przeze mnie źródłami DSP Lib. Z biblioteki praktycznie używam tylko 3 funkcji:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Dla opcji statycznej mam:
    text data bss dec hex filename
    98308 140 5564 104012 1964c

    w drugim przypadku:
    text data bss dec hex filename
    65868 140 5564 71572 11794

    Oto logi kompilacji dla opcji statycznej:
    Kod: Ini
    Zaloguj się, aby zobaczyć kod


    i opcji rzeźbionej:
    Kod: Ini
    Zaloguj się, aby zobaczyć kod


    Skrypt linkera domyślny z CubeMX dla STM32F303RET, kod HALA usunięty, Makefile automatyczny, flagi kompilacji dobierane eksperymentalnie :)
    Kod: Ini
    Zaloguj się, aby zobaczyć kod


    Da się jeszcze jakoś zoptymalizować, pod względem kodu, przy zachowaniu szybkości, opcję statyczną?

    Przyznaję od razu, że to wszystko robię na tzw "czuja", w STM32 System Workbench.
  • #18 17105601
    kk.krz
    Poziom 4  
    Posty: 186
    Ocena: 2
    A ja z kolei zachodzę w głowę czemu mi to źle liczy:
    Mam tablice:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    inicjalizuję fft2 instancję

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


    Dostaję a=ARM_MATH_SUCCESS

    Wypełniam sin(i)
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    W input mam: 0.00000, 0.84147, 0.90930..itd

    Octave mi liczy fft tak, że mam :
    -0.12399 + 0.00000i
    -0.11737 - 0.12211i
    -0.09388 - 0.27507i
    itd...

    a CMSIS wyrzuca mi:

    output[0] float32_t -0.123987347
    output[1] float32_t -0.320995361
    output[2] float32_t -0.117369026
    output[3] float32_t -0.122113399

    Wczytując się w dokumentację CMSIS powinienem dostawac r[0], i[0], r[1], i[1] etc
    a tu dostaję real co drugi poprawnie, a imaginy to jakieś dziwne wartości. Nawet output[1] nie jest 0, tylko jakaś z powietrza wartość. Pewnie znów jakiś durny błąd zrobiłem albo źle zrozumiałem dokumentację.

    Dodano po 9 [minuty]:

    Ehh... teraz dojrzałem...tylko i[0] mi się nie zgadza...ale czemu

    Dodano po 2 [minuty]:

    I kolejne pytanie...czemy wykonanie arm_rfft_fast_f32(&S, input, output,0); zmienia mi wartości w tablicy input?
  • #19 17105668
    _lazor_
    VIP Zasłużony dla elektroda
    Posty: 3795
    Pomógł: 259
    Ocena: 1132
    imput powinien wyglądać miej więcej w takiej postaci:

    float32_t input[32][2];

    gdzie element [x][0] oznacza liczbę rzeczywistą a [x][1] liczbę urojoną.
  • #21 17105686
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    kk.krz napisał:


    I kolejne pytanie...czemy wykonanie arm_rfft_fast_f32(&S, input, output,0); zmienia mi wartości w tablicy input?


    Bo akurat ta funkcja tak właśnie działa :) Pracuje tylko na jednej tablicy, wejściowa jest zarazem wyjściową.
    Jeśli wskoczysz na oficjalną stronę CMSIS:
    http://www.keil.com/pack/doc/CMSIS/DSP/html/index.html
    to masz to tam dokładnie opisane.

    Jeśli przeglądniemy zastosowanie właśnie tej metody w przykładowych projektach, chyba właśnie również tych dostarczonych z CMSIS, to właśnie zastosowanie tej metody wymusza kopiowanie tablic przed wyznaczaniem transformaty, bo dane pośrednie właściwie nie są koniecznie potrzebne - tak sobie to tłumacze i nie polemizuję z założeniami twórców :).
  • #22 17105722
    kk.krz
    Poziom 4  
    Posty: 186
    Ocena: 2
    simw - to bysię zgadzało jeśli chodzi o cfft, tam faktycznie opisane jest, że bufor wejściowy jest zarazem wyjściowym. Tu jednak, dla rfft są parametrem funkcji są dwa bufory - input i output.
    vide - http://www.keil.com/pack/doc/CMSIS/DSP/html/g...alFFT.html#ga180d8b764d59cbb85d37a2d5f7cd9799
  • #23 17105723
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    _lazor_ napisał:
    imput powinien wyglądać miej więcej w takiej postaci:

    float32_t input[32][2];

    gdzie element [x][0] oznacza liczbę rzeczywistą a [x][1] liczbę urojoną.

    Jeśli dobrze pamiętam, to w przykładowych projektach zwykle stosowano tablicę jednowymiarową o powiększonej dwa razy wielkości, a dane real i urojone były układane naprzemiennie

    Sam u siebie właśnie dla "arm_rfft_fast_f32" używałem tablic jednowymiarowych, ale z linijką nie liczyłem zwracanych wartości, a same próby robiłem metodą brute force aż otrzymałem to co mi się wydaj, że jest dobre :)
  • #24 17105733
    _lazor_
    VIP Zasłużony dla elektroda
    Posty: 3795
    Pomógł: 259
    Ocena: 1132
    Możiwe, że trzeba dać tylko liczby rzeczywiste, ta dokumentacja jest średnia.

    Jednak zauważ że wynik ma poprawny w output.

    output[2] float32_t -0.117369026
    output[3] float32_t -0.122113399

    jest to para liczb zespolonych. a octave to tak przedstawia:
    -0.11737 - 0.12211i

    W dokumentacji jest też taki zapisek:
    "* Looking more closely we see that the first and last samples are real valued."

    Alee nie wiem jak to do końca interpretować.

    Zdecydowanie output powinien mieć taki format jak pomyliłem się z inputem. Oraz wyzeruj tablicę output przed jej użyciem, może jej drugi element to tylko jakiś śmieć z pamięci, gdyż sam algorytm pod ten adres nic nie pisze z przyczyny powyższego zdania z dokumentacji.
  • #25 17105776
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    kk.krz napisał:
    simw - to bysię zgadzało jeśli chodzi o cfft, tam faktycznie opisane jest, że bufor wejściowy jest zarazem wyjściowym. Tu jednak, dla rfft są parametrem funkcji są dwa bufory - input i output.
    vide - http://www.keil.com/pack/doc/CMSIS/DSP/html/g...alFFT.html#ga180d8b764d59cbb85d37a2d5f7cd9799

    Masz racje pozajączkowało mi się. Swego czasu mocno z tym eksperymentowałem i teraz już mi sie to miesza :)

    Być może ten bufor wejściowy jest po prostu tymczasowy, i być może dlatego ta funkcja jest opisana jako fast, jest szybka, ale właśnie tym kosztem.
    Ja za każdym razem napełniam ten bufor przed wykonaniem funkcji, ale póki co to takie moje próbkowanie tego tematu. Jeśli zajdzie potrzeba to przecież przez DMA można takie dane bezboleśnie "zarchiwizować".
  • #26 17105792
    kk.krz
    Poziom 4  
    Posty: 186
    Ocena: 2
    Hm...zobaczmy..wchodzi 32 sztuki wartości real w tablicy jednowymiarowej. Wychodzi...no zobaczmy w dokumentacji: http://www.keil.com/pack/doc/CMSIS/DSP/html/group__RealFFT.html
    w Description, pod grafami podana jest struktura tablicy output...wychodzi na to że dwuwymiarowa, więc [32][2], ale przecież... funkcja arm_rfft_fast_f32 jako output przyjmuje:

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


    więc jak jej w pOut dam wskaźnik do mojej output, zdeklarowanej tak:

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


    to mi wyrzuci:

    Kod: Bash
    Zaloguj się, aby zobaczyć kod


    chyba, że ja znów jakieś wstydliwe braki w programowaniu ujawniam...

    Output w debugerze mam wyzerowany...hmmm
  • #27 17105805
    _lazor_
    VIP Zasłużony dla elektroda
    Posty: 3795
    Pomógł: 259
    Ocena: 1132
    zrób tak:

    arm_rfft_fast_f32(&S, input, (float*)output,0);

    Ja sobie tworze taką tablicę dwu wymiarową by się potem z danymi nie męczyć, ale faktycznie trzeba rzutować na pointer float
  • #28 17105818
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    Przy okazji polecam świetną książkę w tej dziedzinie:
    "Cyfrowe przetwarzanie sygnałów" Steven W. Smith
    Teoria wyłożona wyjątkowo w przystępny sposób, w sam raz dla praktyków.
    Po przeczytaniu połowy byłem mocno nabuzowany, że już to rozumiem, ale praktyka wszystko zweryfikowała, wiedza szybko wyparowała... :) wiadomo takie książki trzeba studiować, co zamierzam znowu robić.
    Książka nie jest tania, ale uważam, że warta swojej ceny, ja akurat załapałem się na promocję.

    Dodano po 8 [minuty]:

    _lazor_ napisał:
    zrób tak:
    arm_rfft_fast_f32(&S, input, (float*)output,0);

    Ja sobie tworze taką tablicę dwu wymiarową by się potem z danymi nie męczyć, ale faktycznie trzeba rzutować na pointer float

    Ja robię to tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jak widać funkcja jest tak fast, że nawet nie potrzebuje określenia długości buforów :)
  • #29 17105841
    kk.krz
    Poziom 4  
    Posty: 186
    Ocena: 2
    simw - słyszałem o niej...zainteresuję się - pasjonująca dziedzina....podobnie jak uC w ogóle...pożeracze czasu :)

    _lazor_ - sprytnie...poukładało mi wyniki w output[0][0] = r, output[0][1] = i itd...ale... :) ostatnia zapisane pozycja znajduje się w output[15][0] i output[15][1]...Wychodzi na to, ze jak wpuszczam 32 reale, to liczy mi rfft korzystając z "prawa", że fft z reali dla i=0 jest "symetryczna", więc dostaję wyniku o połowę mniej.

    To bym jeszcze zniósł - bo jest poprawne, ale dlaczego pierwszy wynik, który powinienem mieć

    -0.12399 + 0.00000i

    mam real poprawny, a imagine -0.320995361. To jest ewidentny błąd.
  • #30 17105856
    simw
    Poziom 27  
    Posty: 758
    Pomógł: 94
    Ocena: 288
    kk.krz napisał:
    simw - słyszałem o niej...zainteresuję się - pasjonująca dziedzina....podobnie jak uC w ogóle...pożeracze czasu :)


    -0.12399 + 0.00000i

    mam real poprawny, a imagine -0.320995361. To jest ewidentny błąd.


    Jakoś przez mgłę sobie przypominam włąśnie z książki, że poprawna długość bufora to jest SAMPLES/2 + 1, tylko nie do końca pamiętam o co chodziło :)
    Może jak wrócę do lektury to nie będę wymyślał :)

Podsumowanie tematu

✨ Użytkownik napotkał problemy z dołączeniem bibliotek DSP z CMSIS w projekcie opartym na STM32F4. W szczególności, wystąpiły błędy linkowania przy użyciu funkcji z arm_math.h. Po wskazówkach od innych uczestników forum, użytkownik poprawił kolejność linkowania bibliotek w Makefile, co pomogło w rozwiązaniu problemu. Dyskusja obejmowała również optymalizację flag kompilatora oraz różnice w rozmiarze kodu przy użyciu różnych bibliotek matematycznych. Użytkownicy wymieniali się doświadczeniami związanymi z pamięcią programu oraz sposobami na efektywne wykorzystanie funkcji FFT w kontekście obliczeń DSP.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA