Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[STM32F1][C/Eclipse] - Zawieszający się program: wielkość stosu, zajętości RAM'u

Co_pat 09 Apr 2014 18:21 1632 9
  • #1
    Co_pat
    Level 15  
    Witam!

    Eclipse Kepler
    Sourcery CodeBench Lite 2011.09-69
    OpenOCD 0.6.1
    STM32F103ZET6
    Szablon projektu - Freddie Chopin

    Do tej pory wszystkie projekty na STM32 działały dobrze jednak teraz buduję większa aplikację i pojawiają się problemy. Objawia się to losową zmianą wartości zmiennych np. zadeklarowanych jako const czy przerwaniem __Default_Handler.
    Przejrzałem cały program dokładnie kilkanaście razy, sprawdziłem wszystkie operacja na wskaźnikach, ale niestety to nie rozwiązało problemu.
    Stąd moje pytania:



    W jaki sposób dokładnie określić rozmiar __main_stack_size i __process_stack_size w skrypcie linkera?
    Do tej pory wiedziałem, że dla "bardziej rozbudowanych" aplikacji process_stack_size ma być 1-2kB, a main_stack_size niezerowy ( ale jaki? ) gdy używam przerwań.

    Jak oszacować ilość potrzebnego RAM'u przed zmianą kontrolera na mniejszy? Czytałem, że jednym ze sposobów jest wypełnienie RAM'u znanymi wartościami i podczas działania programu np. za pomocą debugera zobaczyć jak daleko zaszły zmiany. Tylko nie mam pomysłu jak to zrobić w Eclipse.

    Jak określić zajętość RAM podczas działania programu, czytałem o porównywaniu wskaźnika stosu i wskaźnika sterty, ale nie wiem do tego się dobrać? Czy wystarczy __get_PSP() - __get_MSP() z core_cm3 CMSIS'a?

    W projekcie wykorzystuje w wielu funkcjach duże tablice, podobno lepiej jest je deklarować dynamicznie lub globalnie. Jakia jest różnica przy tego typu deklaracjach:
    Code: c
    Log in, to see the code
  • #2
    alagner
    Level 26  
    Main stack o ile pamiętam jest używany w przerwaniach, ale może tutaj po prostu źle Ci się napisało.

    Freddie doradzał kiedyś zrobienie iluś różnych handlerów i przeniesienie stosu na dół ramu - wtedy przy jego przekroczeniu wybije Cię bezpśrednio do odp. wyjątku. A co do sprawdzania zajętości pamięci - jak możesz, to zaglądnij do 2giej książki M. Kardasia, tam co prawda jest to pokazane na AVRach ale zasada jest ta sama.

    Pzdr.
  • #3
    Freddie Chopin
    MCUs specialist
    Co_pat wrote:
    W jaki sposób dokładnie określić rozmiar __main_stack_size i __process_stack_size w skrypcie linkera?

    Nie da się - nawet jak sobie to sprawdzisz metodami o których piszesz to i tak jest to wartość "na oko". Co do wypełnienia stałymi danymi i podglądania, to samo podglądanie można wykonać przy użyciu zakładki Memory, a wypełnianie najlepiej zrobić w startupie.

    Jak już wcześniej pisałem, takie analizy i tak są zawsze "na oko", bo jeśli inaczej "pobudzisz" program (wyślesz przez jakiś interfej inne dane, inaczej naciśniesz przyciski, działania będą w innej kolejności/ilości, ...) to użycie stosu może się zmienić, czasem diametralnie. Do tego jakaś zmiana w kodzie i znów ilość użytej pamięci na stos się zmienia. Czasem szczytowe "zużycie" stosu występuje tylko w specyficznych przypadkach, po długim działaniu programu itd. - prościej więc po prostu powiększyć stos dwukrotnie i już (; Jak problem zniknie, to wiesz co było powodem. Jeśli nie zniknie, to znaczy że problem jest gdzie indziej.

    W większych aplikacjach spokojnie można myśleć o stosach rzędu 4kB, choć faktycznie w większości przypadków 2kB to dosyć sporo.

    Co_pat wrote:
    Jakia jest różnica przy tego typu deklaracjach:

    Taka że pierwsza zajmuje 256 bajtów stosu, a druga 4 (na wskaźnik) - reszta jest ze sterty. No i oczywiście do tego inne przyjemności typu fragmentacja pamięci itd.

    4\/3!!
  • #4
    Co_pat
    Level 15  
    Dzięki za odpowiedzi.
    alagner pomyliłem się kolejnością odnośnie stosów ( zmienione w pierwszym poście )

    Freddie według Twojej wskazówki zmieniam wartości stosów i sprawdzę czy problem się pojawi ponownie.

    Mam pytanie jeszcze odnośnie samej sztuki programowania.
    Mam duże bufory nadawczo[500]/odbiorcze[500] uzupełniane danymi w przerwaniach. Czy dobrym pomysłem jest tworzenie dynamicznej tablicy w funkcji, następnie kopiowanie z wykorzystaniem memcpy do niej wartości bufora do ostatnio odebranego bajtu i później operowanie na tej dynamicznej tablicy?
  • #5
    BlueDraco
    MCUs specialist
    Jest to zupełnie zły pomysł - zbędne powielanie danych skutkujące trudną do określenia, ale dużą zajętością pamięci.
  • #6
    Co_pat
    Level 15  
    BlueDraco no i tu może być problem.
    Czyli lepiej operować na tych globalnych tablicach, ale na czas ich wykorzystywania wyłączyć przerwania czy to nie wpłynie znacząco jeżeli będę "używał" tylko początku bufora?
  • #7
    Freddie Chopin
    MCUs specialist
    Zrób dwa bufory i operuj na nich w trybach "ping-pong". Jeden wypełniasz w przerwaniu, na drugim sobie coś robisz w programie głównym. Jak skończysz, to go "zwalniasz" i czekasz aż przerwanie "przydzieli" Ci ten drugi, jednocześnie biorąc dla siebie ten pierwszy.

    4\/3!!
  • #8
    Co_pat
    Level 15  
    Freddie Chopin cenna wskazówka!
    A z innej strony. Jest możliwość dynamicznej zmiany rozmiaru tych buforów?
    Chodzi mi o to, że czasami wystarczy mi tylko 100B, a czasami potrzebuję nawet 2kB.
  • #9
    Freddie Chopin
    MCUs specialist
    Zgodnie z nazwą ten problem da się rozwiązać jedynie poprzez dynamiczną alokację pamięci (; Niemniej jednak nie musi to być koniecznie malloc() czy new, wystarczy np. jeden wielki bufor, z którego w swoim programie "odcinasz" potrzebne Ci kawałki - to po prostu byłaby Twoja sterta. Niemniej jednak zbyt wiele nie zyskasz tak czy siak... Może prościej zrobić duże FIFO i tyle?

    4\/3!!
  • #10
    Co_pat
    Level 15  
    Freddie Chopin, FIFO jest dobrym rozwiązaniem, myślałem, że uda się to zrobić w prostszy sposób. Niestety muszę przebudować wszystkie funkcje z tym związane, bo chcę zamienić aktualne rozwiązanie czyli dwie zmienne tablica i licznik danych w buforze na strukturę z tablicą, wskaźnikiem na ostatnio odczytany element i licznikiem danych w buforze. Mam nadzieję, że dzięki temu program będzie też efektywniejszy.