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

[atmega328p][asm/c/atm studio] - Własny task scheduler + dzielenie - uc crash

ShadowDancer 01 Gru 2014 12:54 981 5
  • #1 14181603
    ShadowDancer
    Poziom 10  
    Dzień dobry,
    mój problem jest następujący:
    Napisałem task scheduler z wywłaszczaniem, zaprogramowałem na urządzenie (arduino uno programowane bezpośrednio przez isp(bez bootloadera). I dziwne rzeczy zaczynają się dziać gdy próbuję podzielić dwie zmienne typu uint32 (4 bajty).
    Program (dzielenie) napisany jest w c, natomiast przerwanie w assemblerze. Inne operacje (działanie, inkrementacja, itp. itd) działają bez zarzutu.

    Moja procedura przerwania (schedule) działa następująco:
    * pushuje 32 rejestry na stos
    * push SREG
    * zapisuje stack pointer w tablicy
    * wczytuje z tablicy stack pointer kolejnego tasku
    * ustawiam wskaźnik stosu na stos kolejnego tasku
    * pop SREG
    * pop 32 rejestry
    * RETI (do kolejnego tasku)

    Oczywiście wcześniej przygotowuje odpowiednio stosy tasków. Kod przerwania:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Kod w c powodujący problemy:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    val1/2/3 to zmienne uint32. Żadna z tych zmiennych nie jest używana poza taskiem (dopiero potem są one przepisywane do zmiennych volatile, które są używane w innym tasku).

    ASM wygenerowany dla powyższego kodu w c:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Nie ma tu instukcji specyficznych tylko dla tej funkcji, nie mam pomysłu co może być źle. Nie mam też sprzętowego debuggera, żeby sprawdzić co się dzieje na uc, po prostu wszystkie wejścia przechodzą w stan niski - na wyświetlaczach 7 segment pojawiają się 8, jednak multipleksowanie chyba działa, ponieważ nic nie płonie (do uc podpiętych jest 8 cyfr).

    Zastanawiam się, czy nie popełniam jakiegoś oczywistego błędu (brak zapamiętania jakiegoś rejestru z pamięci sram z ukrytym stanem) itp.
  • #2 14181618
    witoldwitoldowicz
    Poziom 28  
    Niewiem jak jest w mikrokontrolerach ale normalnie jak val2==0 to exception divide by 0.
  • #3 14181629
    ShadowDancer
    Poziom 10  
    Val2 na pewno nie jest 0, kod jest poprawny z punktu widzenia tego tasku.
    Poza tym gdyby val2 był zerem, to wyłączenie przerwań by nie pomogło.
  • Pomocny post
    #4 14181705
    michalko12
    Specjalista - Mikrokontrolery
    Po wejściu do przerwania i odłożeniu wszystkich rejestrów na stos wyzeruj R1, a dlaczego to się już domyśl i wyjaśnij innym.
  • #6 14181800
    ShadowDancer
    Poziom 10  
    michalko12
    Bardzo dziękuje za odpowiedź, oczywiście problem rozwiązany.

    JarekC
    Stos był odpowiedno duży, dzięki za dobre chęci.

    No więc wyjasnienie (za notą AT1886):
    Register | Description | Assembly code called from C | Assembly code that calls C code
    r1 | Always zero | Must clear before returning | Must clear before calling

    Always zero mnie zmyliło, ponieważ kompilator c wrzuca tam różne liczby i nie ma szans ich posprzątać w przypadku przerwania.
    Z tego powodu ta instrukcja: CP R16, R1
    nie działała tak jak zaplanowałem i przesuwała rejestr Z w losowe miejsce, a potem program wpisywał tam adres stosu, co skutkowało katastrofą.

    Niestety symulator działa inaczej i nie miałem szans sprawdzić tego na symulatorze, a sam bym pewnie na to nie wpadł.
    Dziękuje bardzo!
REKLAMA