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

Wstawka asemblerowa do języka c [atmega2560][C+asm]

imaiden 15 Lut 2022 21:19 516 7
  • #1 19886549
    imaiden
    Poziom 4  
    Dzień dobry, witam wszystkich. Mam problem z wstawką asemblerową do języka C. Programuję procesor atmega2560. Nie rozumiem dlaczego nie działa funkcja "asm volatile ("mov r21,MCUSR");". Chcę dzięki niej przenieść wartość rejestru mcusr do rejestru r21. Lista błędów w załączniku. Wiem, że one wprost mogą nie wskazywać na to, że ich źródłem jest ta linijka z 'mov', ale kiedy usuwam tę linijkę, to kod się kompiluje.

    Wstawka asemblerowa do języka c [atmega2560][C+asm]

    Wstawka asemblerowa do języka c [atmega2560][C+asm]
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Wiem, że program może nie mieć praktycznego sensu, ale przyznam się, że to jest na zaliczenie przedmiotu na uczelni.
  • #2 19886812
    excray
    Poziom 41  
    MOV to jest przenoszenie danych między rejestrami. Do pobrania danych spod adresu użyj IN albo LD. w zależności od położenia MCUSR.
  • #3 19886823
    imaiden
    Poziom 4  
    excray napisał:
    MOV to jest przenoszenie danych między rejestrami. Do pobrania danych spod adresu użyj IN albo LD. w zależności od położenia MCUSR.


    Tak, tych komend również próbowałem, ale też wyskakują błędy. Tyle, że inne. Próbowałem czegoś takiego:

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

    oraz
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #4 19886839
    excray
    Poziom 41  
    Zanim zaczniesz używać asemblera wypadałoby poczytać trochę o tych komendach, co one oznaczają i jak ich używać. Jeżeli używasz assemblera jako wstawki w C, to mnemoniki typu MCUSR nic kompilatorowi nie mówią - musisz używać adresów. Z kolei komenda LDn ma z kilkanaście swoich wersji i powinieneś sprawdzić którą używasz i dlaczego. Jeśli już ładujesz dane bezpośrednio spod adresu to powinieneś używać LDS.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    EDIT> LDS...
  • #5 19887504
    imaiden
    Poziom 4  
    excray napisał:
    Zanim zaczniesz używać asemblera wypadałoby poczytać trochę o tych komendach, co one oznaczają i jak ich używać. Jeżeli używasz assemblera jako wstawki w C, to mnemoniki typu MCUSR nic kompilatorowi nie mówią - musisz używać adresów. Z kolei komenda LDn ma z kilkanaście swoich wersji i powinieneś sprawdzić którą używasz i dlaczego. Jeśli już ładujesz dane bezpośrednio spod adresu to powinieneś używać LDS.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    EDIT> LDS...


    Mam dwa pytania. Po pierwsze to podane przez Ciebie komendy działają i bardzo dziękuję za pomoc bo sam bym tego nie wymyślił. Jak to działa? Dlaczego kiedy wpisuję adres 0x34 komenda działa, skoro mi się wyświetla, że adres MCUSR to 0x54? Wstawka asemblerowa do języka c [atmega2560][C+asm]

    Mam jeszcze drugie pytanie. Mianowicie chciałbym porównać wartość w rejestrze r23 ze stałą równą 4. Rejestr ten zwiększa się o 1 za każdym razem, kiedy wystąpi przerwanie od watchdoga. Idea jest taka, żeby po wystąpieniu 4 przerwań (czyli r23 ma wartość 4) uC nie wchodził już w stan uśpienia. Chciałem to zrobić na if'ie, ale to nie będzie raczej działać. Czy masz może pomysł jak to zrobić?
  • #6 19887527
    excray
    Poziom 41  
    imaiden napisał:
    0x34 komenda działa, skoro mi się wyświetla, że adres MCUSR to 0x54

    Jest to specyfika pewnej grupy rozkazów assemblerowych. Takich jak IN, OUT, CBI, SBI, etc:
    Wstawka asemblerowa do języka c [atmega2560][C+asm]
    Tam, gdzie w manualu adres jest podany jako P. Komendy te odwołują się do adresów z zakresu 0-3F:
    Wstawka asemblerowa do języka c [atmega2560][C+asm]
    Wstawka asemblerowa do języka c [atmega2560][C+asm]
    Dlatego odwołując się poprzez IN, OUT z MCUSR używasz 0x34, a poprzez LDS czy LD używasz 0x54. Najlepiej o ile to możliwe (rejestr z adresem<=0x5F) odwoływać się poprzez IN/OUT/CBI/SBI gdyż te komendy są szybsze.

    Dodano po 2 [minuty]:

    imaiden napisał:
    Mam jeszcze drugie pytanie. Mianowicie chciałbym porównać wartość w rejestrze r23 ze stałą równą 4

    Kod: AVR assembler
    Zaloguj się, aby zobaczyć kod
  • #7 19887685
    imaiden
    Poziom 4  
    excray napisał:
    CPI r24, 4BRSH wylacz_usypianie...wylacz_usypianie:CLI..
    excray napisał:
    Kod: avrasm ] CPI r24, 4BRSH wylacz_usypianie...wylacz_usypianie:CLI...


    Powiem szczerze, że nie bardzo rozumiem. Obecny kod wygląda w ten sposób:

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


    Jak widać, rejestr r23 zlicza ilość przerwań od początku działania programu. Przy każdym przerwaniu uC jest wybudzany z trybu uśpienia i ponownie w niego wprowadzany. I teraz chodzi o to, żeby po czwartym resecie watchdoga nie wchodzić już w ten stan uśpienia. myślałem o czymś w stylu może asm volidate ("CPI r23, 4) właśnie tak jak napisałeś, ale co potem zrobić, żeby po spełnieniu tego warunku wykonała się instrukcja w języku C "SMCR |= (0<<SE);"? Może też być asemblerowa, ale w asemblerze nie bardzo wiem jak. Będę wdzięczny za objaśnienie ;)
REKLAMA