eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.misc.elektronika › Pamięć nadpisuje stos (choć powinno być mnóstwo miejsca)
Ilość wypowiedzi w tym wątku: 14

  • 1. Data: 2020-09-29 21:35:19
    Temat: Pamięć nadpisuje stos (choć powinno być mnóstwo miejsca)
    Od: Atlantis <m...@w...pl>

    Walczę teraz z pewną dziwną zagadką, która teoretycznie nie powinna mieć
    miejsca. Chodzi o jeden z moich projektów retro na 6502, ale
    teoretycznie nie powinno mieć to nic wspólnego z procesorem.

    Oprogramowanie napisane w C i skompilowane kompilatorem CC65.
    Kod źródłowy jest dostępny tutaj:
    https://github.com/marekw1986/RetroEG/tree/master/co
    de

    Wszystko zaczęło się od tego, gdy dodałem do projektu funkcje do obsługi
    przycisków - funkcje, które w innym projekcie (na takiej samej płytce,
    tylko z nieco innymi peryferiami) działały bez problemu, a tutaj nie
    chciały. Po ich dodaniu układ zaczął się zachowywać skrajnie nie
    stabilnie - samoczynne resety co kilkadziesiąt sekund, co chwilę
    detekcja fałszywych wciśnięć przycisków itp.

    Dość długo szukałem błędu w kodzie, ale nie mogłem go znaleźć. Upewniłem
    się, że winy nie ponosi uszkodzony RAM albo procesor. Aż w końcu
    zacząłem eksperymentować ze zmiennymi - zmniejszyłem rozmiar niektórych
    buforów, część zmiennych zmieniłem z globalnych na lokalne. Pomogło!
    Samoczynne resety ustały, fałszywe wciśnięcia przycisków występują, ale
    bardzo rzadko.

    Sprawa jest jednak bardzo dziwna, bo wygląda to tak, jakbym teraz był na
    skraju maksymalnego wykorzystani RAM-u. A tak nie powinno być. Układ ma
    8kB pamięci RAM, więc naprawdę dużo jak na taki "kontroler". W pamięci
    nie ma za dużo zmiennych globalnych. Są tylko dwa większe bufory (po 256
    bajtów każdy), poza tym parę mniejszych buforów, trochę stosunkowo
    niewielkich struktur i umiarkowna ilość zmiennych. Nie ma szansy, żeby
    to nagle zajęło zdecydowaną większość RAM-u. Nie widzę też niczego, co
    mogłoby pożerać stos - nie używam nigdzie rekurencji ani nie stosuję
    większych zmiennych globalnych, zbyt zagnieżdżonych wywołań funkcji też
    nie ma.

    Gdyby ktoś wpadł na pomysł, że to wina niewielkiego sprzętowego stosu
    6502 (zaledwie 256 bajtów w pierwszej stronie pamięci) to tłumaczę, że
    CC65 korzysta z programowego stosu, który działa tak, jak we
    współczesnych MCU, zapisując dane od końca pamięci w dół.

    Fragment pliku .map wygenerowanego podczas linkowania projektu
    potwierdza, że zmienne globalne zajmują bardzo małą część pamięci:

    Segment list:
    -------------
    Name Start End Size Align
    ----------------------------------------------------
    ZEROPAGE 000000 000019 00001A 00001
    DATA 000200 00024A 00004B 00001
    BSS 00024B 0004FF 0002B5 00001
    STARTUP 00804B 008066 00001C 00001
    ONCE 008067 008072 00000C 00001
    CODE 008073 00A022 001FB0 00001
    RODATA 00A023 00A1D6 0001B4 00001
    VECTORS 00FFFA 00FFFF 000006 00001

    Plik cfg wygląda następująco:

    MEMORY {
    ZP: start = $0, size = $100, type = rw, define = yes;
    RAM: start = $200, size = $1E00, define = yes;
    ROM: start = $8000, size = $8000, file = %O;
    }

    SEGMENTS {
    ZEROPAGE: load = ZP, type = zp, define = yes;
    DATA: load = ROM, type = rw, define = yes, run = RAM;
    BSS: load = RAM, type = bss, define = yes;
    HEAP: load = RAM, type = bss, optional = yes;
    STARTUP: load = ROM, type = ro;
    ONCE: load = ROM, type = ro, optional = yes;
    CODE: load = ROM, type = ro;
    RODATA: load = ROM, type = ro;
    VECTORS: load = ROM, type = ro, start = $FFFA;
    }

    FEATURES {
    CONDES: segment = STARTUP,
    type = constructor,
    label = __CONSTRUCTOR_TABLE__,
    count = __CONSTRUCTOR_COUNT__;
    CONDES: segment = STARTUP,
    type = destructor,
    label = __DESTRUCTOR_TABLE__,
    count = __DESTRUCTOR_COUNT__;
    }

    SYMBOLS {
    # Define the stack size for the application

    __STACKSIZE__: value = $0200, type = weak;
    }

    Ktoś ma jakiś pomysł co do tego, gdzie można szukać przyczyny? Na chwilę
    obecną urządzenie działa w miarę stabilnie, jednak chciałem dodać
    jeszcze kilka funkcji, które będą wymagały trochę RAM-u, więc przedtem
    muszę rozwiązać ten problem.


  • 2. Data: 2020-09-29 22:12:56
    Temat: Re: Pamięć nadpisuje stos (choć powinno być mnóstwo miejsca)
    Od: heby <h...@p...onet.pl>

    On 29/09/2020 21:35, Atlantis wrote:
    > Dość długo szukałem błędu w kodzie, ale nie mogłem go znaleźć.

    Nie myślałeś aby napisać mały emulator cpu (ba, ukraśc gotowca, jest ich
    zilion) + trywialny emulator hardware (tych przycisków) i debugować in
    vitro, co tam się dzieje? Jak już masz transakcje cpu typu "zapisz bajt"
    i "odczytaj bajt" to napisanie kawałka kodu który udaje że jest
    przyciskiem, nie jest chyba jakieś strasznie trudne.

    Powoli myslę nad zrobieniem małego komputera na CP/M (i mam nadzieje
    GEMa, jak mi się uda), ale wiem że pracę zaczne *wirtualnie*, czyli
    piszać emulator cpu, hardware i to będzie moje miejsce do debugu, nie
    fizyczne hardware, ono powstanie później lub równolegle...


  • 3. Data: 2020-09-29 22:36:30
    Temat: Re: Pamięć nadpisuje stos (choć powinno być mnóstwo miejsca)
    Od: heby <h...@p...onet.pl>

    On 29/09/2020 21:35, Atlantis wrote:
    > zacząłem eksperymentować ze zmiennymi - zmniejszyłem rozmiar niektórych
    > buforów, część zmiennych zmieniłem z globalnych na lokalne. Pomogło!

    To może wskazywać np. na to że nie wracasz z przerwania (masz jakieś?)
    lub się nie wyrabiasz i po jakims czasie przekręca się stos sprzętowy.
    Taka luźna myśl. Co prawda widzę CLI na początku maina, ale może cos
    przeoczyłem.

    Jeszcze jedno: nie przestawiasz gdzieś procesora w tryb BCD?

    I jeszcze jedno: Masz gdzieś podpięte SO (pin cpu)?

    Sorry, ale review kodu nie zrobie... za duży :)


  • 4. Data: 2020-09-29 23:04:13
    Temat: Re: Pamięć nadpisuje stos (choć powinno być mnóstwo miejsca)
    Od: Atlantis <m...@w...pl>


    On 29.09.2020 22:36, heby wrote:

    > To może wskazywać np. na to że nie wracasz z przerwania (masz jakieś?)

    Systemy na 6502 mają tylko jeden wektor przerwań. Linia INT jest
    zwierana do masy przez poszczególne urządzenia zgłaszające przerwania,
    za pomocą wyjść typu OC. W kodzie obsługi przerwania trzeba po kolei
    odpytać wszystkie urządzenia i zdjąć flagi. Jest więc tylko jedna
    procedura obsługująca przerwanie, zakończona instrukcją RTI, więc
    program wraca z przerwania.
    Na początku procedury zapisuję na stosie zawartość rejestrów A oraz X
    (tylko z nich korzystam) a przed powrotem je przywracam.

    Wszystkie funkcjonalności związane z przerwaniami działają poprawnie.


    > lub się nie wyrabiasz i po jakims czasie przekręca się stos sprzętowy.

    Co masz na myśli?


    > Co prawda widzę CLI na początku maina, ale może cos przeoczyłem.

    W 6502 CLI to instrukcja "clear interrupt DISABLE", natomiast SEI
    oznacza "set interrupt DISABLE". Czyli CLI włącza przerwania, SEI je
    wyłącza. Odwrotnie niż w AVR-ach czy PIC-ach.


    > Jeszcze jedno: nie przestawiasz gdzieś procesora w tryb BCD?

    Świadomie nie. Cały program zawiera tylko kilka asemblerowych fragmentów
    (m.in. procedura obsługi przerwań) i jestem pewien, że w żadnym z nich
    nie stosowałem instrukcji SED.


    > I jeszcze jedno: Masz gdzieś podpięte SO (pin cpu)?

    Podciągnięty do plusa.


  • 5. Data: 2020-09-29 23:19:55
    Temat: Re: Pamięć nadpisuje stos (choć powinno być mnóstwo miejsca)
    Od: heby <h...@p...onet.pl>

    On 29/09/2020 23:04, Atlantis wrote:
    >> lub się nie wyrabiasz i po jakims czasie przekręca się stos sprzętowy.
    > Co masz na myśli?

    Przerwanie jest przerywane przerwaniem. Dośc częsta wpadka generująca
    rózne problemy, podobne do opisanych.

    >> Co prawda widzę CLI na początku maina, ale może cos przeoczyłem.
    > W 6502 CLI to instrukcja "clear interrupt DISABLE", natomiast SEI
    > oznacza "set interrupt DISABLE". Czyli CLI włącza przerwania, SEI je
    > wyłącza. Odwrotnie niż w AVR-ach czy PIC-ach.

    Wiem, ale nie byłem pewny czy z przerwań korzystasz.


  • 6. Data: 2020-09-29 23:27:08
    Temat: Re: Pamięć nadpisuje stos (choć powinno być mnóstwo miejsca)
    Od: heby <h...@p...onet.pl>

    On 29/09/2020 23:04, Atlantis wrote:
    > Systemy na 6502 mają tylko jeden wektor przerwań.

    No niezupełnie, ogólnie rzecz biorąc jest IRQ i NMI, mają osobne wektory.


  • 7. Data: 2020-09-29 23:50:15
    Temat: Re: Pamięć nadpisuje stos (choć powinno być mnóstwo miejsca)
    Od: Atlantis <m...@w...pl>

    On 29.09.2020 23:19, heby wrote:

    > Przerwanie jest przerywane przerwaniem. Dośc częsta wpadka generująca
    > rózne problemy, podobne do opisanych.


    Nawet w przypadku 6502? Jest jedno wejście INT. Jeśli kolejne urządzenie
    zgłosi przerwanie przed skasowaniem flagi poprzedniego nic się nie
    stanie, bo system nie będzie miał jak wiedzieć, że przyszło kolejne
    przerwanie. Dopiero po opuszczeniu procedury obsługi przerwania zostanie
    ona wywołana ponownie.

    Nie jestem pewien co do sytuacji, kiedy kolejne przerwania przychodzi
    dopiero po zdjęciu flagi poprzedniego (urządzenie peryferyjne odłącza
    wejście INT od masy) ale przed wykonaniem RTI.

    Kwestię NMT pomijam, bo wcale z niego nie korzystam.

    Swoją drogą, jest jakiś prosty sposób na ocenienie użycia stosu
    sprzętowego 6502 przez wywołania funkcji C? Może faktyczne mam za dużo
    zagnieżdżeń? Niby argumenty i zmienne lokalne są przechowywane na stosie
    programowym, ale jednak dresy powrotu ciągle trafiają na sprzętowy...

    Tylko z drugiej strony w takim wypadku manipulowanie rozmiarem buforów
    nie miałoby wpływu na sytuację...


  • 8. Data: 2020-09-30 07:24:18
    Temat: Re: Pamięć nadpisuje stos (choć powinno być mnóstwo miejsca)
    Od: heby <h...@p...onet.pl>

    On 29/09/2020 23:50, Atlantis wrote:
    > Nie jestem pewien co do sytuacji, kiedy kolejne przerwania przychodzi
    > dopiero po zdjęciu flagi poprzedniego (urządzenie peryferyjne odłącza
    > wejście INT od masy) ale przed wykonaniem RTI.

    Codzi o zagnieżdzenie NMI/IRQ. Jeśli nie używasz jednego z nich to może
    to fałszywy trop.

    Ale oceń jaki możesz mieć najdłuższy stos głównego programu i jaki
    możesz miec najdłuższy stos w przerwaniu, shit happens.

    > Swoją drogą, jest jakiś prosty sposób na ocenienie użycia stosu
    > sprzętowego 6502 przez wywołania funkcji C?

    Emulatorem, własnym.

    Np, jeden z ziliona:

    https://github.com/redcode/6502

    Weryfikacja formalna, jesli masz przerwania, jest skrajnie kłopotliwa,
    ale weryfikacja runtime, przez unit testy na emulatorze, raczej prosta i
    odwdzięczy się na wiele różnych sposobów poźniej.

    Narzędzi do formalnej weryfikacji stosu na 6502 nie znam, wydaje mi się
    jednak że widziałem takie do clanga jako ciekawostkę. Ale to Ci się nie
    przyda, poza jakimiś hobbystycznymi eksperymentami nie ma backendu do
    6502 w clangu.

    > Tylko z drugiej strony w takim wypadku manipulowanie rozmiarem buforów
    > nie miałoby wpływu na sytuację...

    Możliwe że problem tylko tak się objawia, to nie jest przyczyna.

    Na ile ufasz, że kod generowany przez kompilator, jest prawidłowy?


  • 9. Data: 2020-09-30 11:29:20
    Temat: Re: Pamięć nadpisuje stos (choć powinno być mnóstwo miejsca)
    Od: a...@h...invalid (Arnold Ziffel)

    Atlantis <m...@w...pl> wrote:

    > Sprawa jest jednak bardzo dziwna, bo wygląda to tak, jakbym teraz był na
    > skraju maksymalnego wykorzystani RAM-u.

    Też tak myślę. Zupełnie nie znam 6502 ani tego, jak Twój kompilator
    alokuje pamięć, ale jesteś w stanie zrobić i wpleść w newralgiczne miejsca
    test, który wypluje na dowolne wyjście informację, jeśli stos (wskaźnik
    stosu) niebezpiecznie zbliży się do wskaźnika sterty?

    Używasz tam w ogóle dynamicznej alokacji pamięci, czy wszystko jest
    statycznie? Jeśli używasz dynamicznej alokacji, to masz pewność, że nie
    masz żadnych wycieków?

    Takie problemy, o jakich mówisz (wszystko działa, dodaję prostą
    funkcjonalność i wszystko zaczyna się losowo sypać), miałem w niewielkim
    projekcie na AVR i wynikały właśnie z nadpisywania sterty przez stos.
    Projekt niewielki, ale okazało się, że wystarczający.

    --
    Po wybuchu jądrowym na uschniętym kikucie ocalałego drzewa siedzą
    dwa szympansy.
    - Masz cos do jedzenia? - pyta samiec.
    Samica podaje mu jabłko.
    - O nie, - protestuje samiec - nie będziemy tej idiotycznej historii
    powtarzać od początku!


  • 10. Data: 2020-09-30 16:47:33
    Temat: Re: Pamięć nadpisuje stos (choć powinno być mnóstwo miejsca)
    Od: Atlantis <m...@w...pl>

    On 30.09.2020 11:29, Arnold Ziffel wrote:

    > Takie problemy, o jakich mówisz (wszystko działa, dodaję prostą
    > funkcjonalność i wszystko zaczyna się losowo sypać), miałem w niewielkim
    > projekcie na AVR i wynikały właśnie z nadpisywania sterty przez stos.
    > Projekt niewielki, ale okazało się, że wystarczający.

    Ok. Wygląda na to, że udało mi się namierzyć źródło problemu.
    Kod obsługujący przerwanie wywoływał funkcję. która zawierała polecenia
    rozkazy SEI/CLI (zabezpieczenie przed uszkodzeniem zawartości zmiennej
    przez przerwanie). Jednak w przypadku 6502 użycie tych rozkazów w
    trakcie obsługi może spowodować wystąpienie kolejnego przerwania, a w
    efekcie nadpisanie stosu sprzętowego i niestabilne działanie.

    Przepisałem kod w ten sposób, żeby pozbyć się wywołania tej funkcji, a
    więc i SEI/CLI. Teraz urządzenie zdaje się działać poprawnie.

    W drugim projekcie tego kodu nie było, więc działało poprawnie.

strony : [ 1 ] . 2


Szukaj w grupach

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: