Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[STM32][C++] - Polimorfizm i nagły hardfault

23 Sie 2016 21:40 1398 25
  • Poziom 20  
    Witam
    piszę w eclipse na ARM, toolchain Freddiego bleeding-edge-toolchain. Problem mam gdy chcę wykorzystać polimorfizm, tzn. gdy program napotka metodę ze słowem virtual to wpada od razu do hardfault. Czym to może być spowodowane? Kod jest na pewno poprawny. Czy trzeba jakoś aktywować polimorfizm?
    Pozdrawiam
  • Specjalista - Mikrokontrolery
    Bardzo dziwny problem, ale musisz podać więcej informacji o swoim projekcie. Np. to jakiego używasz startupa, skryptu linkera, jakie są opcje kompilacji? Czy problem dotyczy zarówno obiektów globalnych jak i takich zadeklarowanych na stosie? Może jesteś w stanie wrzucić tutaj najprostszy możliwy przykład (kompletny projekt)?

    Osobiście podejrzewam, że problem dotyczy globalnych konstruktorów i jest spowodowanym tym, że startup ich nie uruchamia. Wtedy problem nie pojawiałby się dla obiektów na stosie i takich we flash (ale one muszą być ROMable).
  • Poziom 20  
    Dziękuję za szybką odpowiedź Freddie. Powiem szczerze, że ten STM32 w tytule napisałem z rozpędu. Dokładnie to stworzyłem prosty projekt bazując na Twoich (np. stm32f4_blink_led) ale dla procesora NRF51822 firmy Nordic (z wbudowanym BLE i Corex M0) Startup i skrypt linkera mam od Nordica z małymi poprawkami. Makefile jest Twój, ale także z drobnymi poprawkami. Programuję i debuguję poprzez openocd i stlinka z discovery. Kurcze przykład, startup i skrypt linkera wrzucę jutro, bo nie mam przy sobie mojego komputera.
  • Pomocny post
    Specjalista - Mikrokontrolery
    To sprawdź od razu czy problem występuje dla obiektu na stosie. Aby to zweryfikować trzeba wymusić użycie przez wskaźnik, np. tak:

    Code:
    int main()
    
    {
        Derived object;
        Base* volatile pointer = &object;
        pointer->function();
        ...


    Jeśli powyższe zadziała, a dla obiektu globalnego nie, to znaczy że problem jest w globalnych konstruktorach. Zauważ, że w moich przykładach był specjalny kod umożliwiający wyłączenie ich (dla programu w C++ są zbędne, a kod jest wtedy mniejszy) - zarówno w makefile jak i w startupie. Kluczowe jest uruchomienie w startupie funkcji __libc_init_array(), oraz _NIE_użycie opcji "-nostartfiles" przy linkowaniu. Przykłady domyślnie miały wyłączone wsparcie dla C++.
  • Poziom 20  
    Kurcze niestety dopiero jutro rano będę mógł to sprawdzić. Nie jestem teraz u siebie:/ Ale sprawdzę i od razu napiszę.
  • Poziom 20  
    Masz jak zwykle rację:) Dla obiektu na stosie bez żadnych zmian w makefile i startupie działa.
    Więc zabrałem się za zmiany. Makefile mam Twój więc linijkę
    Kod: c
    Zaloguj się, aby zobaczyć kod

    zamieniłem na:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    W startupie dodałem fragment:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    bezpośrednio przed wywołaniem funkcji main. No i niestety nie działa, tzn program się nie wykrzacza (nie wchodzi do hardfault) ale też uart nie działa(to jest właśnie cel kodu wysyłanie tekstu przez uart, a ten polimorfizm wykorzystuję przy funkcjach wypisujących tekst itp.) Wydaje mi się, że nie działają przerwania bo właśnie ten uart mam na nich zrobiony. Czuję że błąd jest gdzieś w startupie, niestety nie jest on taki przejrzysty jak Twój, a jeszcze na końcu niego są wektory przerwań.
    W załączniku makefile i startup, musiałem spakować bo były niedozwolone rozszerzenia.
    Dziękuję za pomoc i pozdrawiam.
  • Specjalista - Mikrokontrolery
    Zrób clean całego projektu, a następnie go skompiluj. Wrzuć tutaj log kompilacji, a do załącznika dodaj pliki .lss, .dmp i .map. Albo po prostu wrzuć cały projekt.

    Istnieje pewna szansa, że problem może być też inny (np. taki, że obiekt używa innego obiektu który jest jeszcze nieskonstruowany), a objaw byłby dosyć podobny. Z tego względu zobaczenie kodu z którym jest problem (może być zminimalizowany do najprostszej postaci z którą jest problem) pozwoliłoby wyeliminować inne opcje.
  • Pomocny post
    Specjalista - Mikrokontrolery
    Dziwne te niektóre pliki, ale z grubsza wszystko wygląda jak należy... Wiele rzeczy mogłoby spokojnie być we flash, ale w skrypcie linkera są umieszczone w RAM.

    Niemniej jednak zacznij od dodania "__STARTUP_CLEAR_BSS" do AS_DEFS w Makefile i zobacz czy może dzięki temu problem zniknie.

    Masz debugger?
  • Poziom 20  
    Bardzo Ci dziękuję po dodaniu "__STARTUP_CLEAR_BSS" do AS_DEFS problem zniknął. Wszystko działą jak należy:)
    A debugger mam programuję to identycznie przez stlinka i openocd jak w Twoich projektach dla stm32.
  • Specjalista - Mikrokontrolery
    No właśnie, czyli problem niezwiązany z C++ czy polimorfizmem - dane które miały być wyzerowane miały po prostu losową wartość.

    Jakbyś chciał nieco zmniejszyć użycie RAM, to możesz rozważyć użycie moich skryptów linkera, tyle że one muszą być "zgrane" ze startupem.
  • Poziom 20  
    Pewnie, żebym chciał. Na razie nie czuję takiej potrzeby ale w niedługiej przyszłości na pewno się to przyda:)
    Tylko jeszcze nie wiem jak się do tego zabrać. Jak polecasz, wziąć Twój startup i skrypt linkera np. z LPC1114 i próbować je przerobić pod NRF51822 czy zmieniać te których aktualnie używam. Ty masz jeszcze dodatkowo wektory przerwań w osobnym pliku vectors.c, a tutaj są wkomponowane w startup (tak mi się przynajmniej wydaje:)).
  • Specjalista - Mikrokontrolery
    Najprościej będzie chyba wziąć pliki z projektu dla LPC1114 i poprawić w nich stosowne rzeczy (rozmiary pamięci, ich adresy i rozmiary stosów w skrypcie linkera, przerwania w tablicy wektorów). Nie jest to dużo roboty, choć jest dosyć nudna.
  • Poziom 20  
    Freddie mam jeszcze jeden problem z debuggerem. Aby odpalić wbudowany BLE to muszę mieć stacka BLE. Nordic udostępnia takiego skompilowanego i mówi, że trzeba dla niego zarezerwować początkowe bajty ROMa i RAMa, a dopiero za tym można wgrywać swój program który coś tam robi. No i to mi działa ale jedynie gdy wgrywam oba kody poprzez openocd z cmd. Nie działa mi natomiast debugger który bym bardzo potrzebował do dalszego tworzenia kodu. Może miałbyś jakiś pomysł jak to naprawić? Przy normalnym skrypcie linkera, tzn z całą pamięcią zarezerwowaną dla mojego kodu debugger działa normalnie. A gdy najpierw wgram ble poprzez openocd z cmd i następnie w eclipsie odpalę openocd i próbuję wgrywać mój kod ale już pod kolejne adresy w pamięci to po wgraniu wyświetla to co w załączniku.
    Z góry dzięki za pomoc:)
  • Specjalista - Mikrokontrolery
    Tu Ci chyba wiele nie pomogę... W takich sytuacjach trzeba experymentować - czasem np. pomaga programowanie w osobnym kroku, a potem tylko uruchomienie GDB bez wgrywania (odznaczona opcja "load executable" czy jakoś tak). Czasem trzeba kombinować bardziej, czasem mniej...
  • Poziom 20  
    Udało mi się zrobić tak, że raz na początku wgrywam stacka ble prze openocd i cmd. A później już normalnie mogę wgrywać mój program przez openocd z eclipsea. Miałem ustawione czyszczenie flasha przy każdym wgrywaniu w eclipsie i dlatego wywalał mi stacka i mi nie chodziło. Czy krok naprzód:) Niestety w dalszym ciągu debugowanie nie działa. A umiałbyś jakoś prosto mi wytłumaczyć gdzie może leżeć problem, bo nie bardzo właśnie wiem gdzie go szukać. Ja to rozumiem tak, że mam plik .elf i przy debugowaniu on jest wykorzystywany, no i właśnie co jest tutaj nie tak? Nie zgadzają się adresy flasha w elfie i debugerze, elf zaczyna się od jakiegoś tam adresu a debuger chce zaczynać od 0? No ale przecież w skrypcie linkera ma podane dokładnie w jakich obszarach może się poruszać:/
    Dzięki za dotychczasową pomoc.
    Pozdrawiam
  • Specjalista - Mikrokontrolery
    No właśnie problem jest tego typu, że tu może wszystko nie grać <: Próbowałeś uruchamiać debuggowanie bez programowania (oczywiście po wcześniejszym wgraniu firmware'u w dowolny sposób)? Jaki masz teraz błąd lub jak objawia się problem?
  • Poziom 20  
    Przede wszystkim program po wgraniu pod eclipsem i przejściu do perspektywy Debug jest od razu wystartowany. To chyba nie jest zdrowy objaw, bo jak debugowanie działa poprawnie to zawsze program jest zatrzymany na początku funkcji main. No i jak dam pause to staje w tym miejscu jak pokazałem na screenie. Kurcze no niestety dopiero jutro z rana będę mógł sprawdzić jak się zachowuje jak tylko debuguje bez ponownego wgrywania, bo nie sprawdzałem tego wcześniej.
    Pozdrawiam
  • Pomocny post
    Specjalista - Mikrokontrolery
    A.T. napisał:
    Przede wszystkim program po wgraniu pod eclipsem i przejściu do perspektywy Debug jest od razu wystartowany. To chyba nie jest zdrowy objaw, bo jak debugowanie działa poprawnie to zawsze program jest zatrzymany na początku funkcji main.

    To jest mało istotny problem i tym bym się akurat nie przejmował.

    Daj znać jak wyjdzie test z uruchamiania GDB bez programowania.
  • Poziom 20  
    Zrobię jeszcze jutro screena z konsoli w eclipsie podczas programowania bo tam coś pisze i szybko znika i nie przyuważyłem co to za informacja.

    Dodano po 1 [minuty]:

    Oki jutro z rana napisze, dzięki:)
  • Użytkownik usunął konto  
  • Poziom 20  
    działa, nawet jak go wgram eclipsem z uzyciem openocd to przechodzi do debugowania, które nie działa, daje stop, restartuje procesor i program chodzi.
  • Użytkownik usunął konto  
  • Pomocny post
    Poziom 33  
    @A.T. Debugowanie nie zadziała Ci z Soft Devicem (to co masz na początku flasha). Stos działa mniej więcej tak w przypadku niespełnienia zależności czasowych (które pojawiają się podczas debugowania przykładowo). Więc jeżeli chcesz debugować to:
    a) bez Soft Device
    b) możesz ręcznie wyłączyć przerwanie od SD

    W obu przypadkach nie będziesz miał oczywiście funkcjonalności SD.

    Cytat:

    Zainstaluj AC6 albo eclipse-a z jakimś toolchainem instalowanym automatycznie i wgraj swój projekt. Jak zadziała to będzie znaczyło że żle skonfigurowaleś toolchaina.


    AC6 to naprawdę idealnie środowisko dla NRFxxx.
  • Poziom 20  
    Dziękuję wszystkim za pomoc. Pomysł Freddiego działa, umiem debugować. Muszę najpierw raz wgrać softdevice poprzez openocd z cmd. A później już normalnie kompiluję, wgrywam mój program poprzez eclipsa i openocd i teraz muszę dać stop i włączyć same debugowanie bez ponownego ładowania programu. W pętli głównej mam miganie diodą i parę delay. No i jak pauzuję to program zatrzymuje się w poprawnych miejscach kodu. Jedynie co to myślę, że mogą nie działać opcje Step Over i Step Into bo jak nagle wskoczy do IRQ od SD to kiepsko. Na szczęście te delaye są teraz na tyle ogroamne (0.5s), że zawsze w nie umiem trafić przy zatrzymywaniu. Zawsze to coś:)

    Dodano po 17 [minuty]:

    W sumie jak zacząłem dokładnie się przyglądać temu ble stackowi to SD Handler jest że tak powiem na zewnątrz tego .hexa z całym stackiem, i funkcje które są wywoływane w nim także znajdują się w moim kodzie. Ogólnie to bardzo dziwnie jest ten kod napisany:/

    Dodano po 14 [minuty]:

    Grko widzę, że już miałeś do czynienia z tymi układami:) Może mógłbyś mi poradzić jakiej opcji(trybu) BLE użyć, żeby wymieniać krótkie wiadomości radiowo pomiędzy takimi dwoma NRFkami. Chcę je wykorzystać do zrobienia czegoś podobnego do Atmelowskiego RKE PEPSa (Passive Entry / Passive Start). Aktualnie używam Sofdevice S130 czyli central i peripheral mode. Dotychczas odpaliłem iBeacon i widzę go na telefonie. Czy umiałbyś polecić jakiś profil, który będzie się do tego nadawał. Najlepiej, żeby nadajnik nie musiał ciągle nadawać wiadomości, aby nie zużywać baterii. Wiem że jest coś takiego jak NUS(podobne do UARTa) ale może jest też coś bardziej odpowiedniego, czego jeszcze nie znalazłem:)
  • Specjalista - Mikrokontrolery
    Czyli masz podobne zachowanie jakie ja obserwuję używając bootloaderów. Nie przejmowałbym się tym specjalnie (;