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

[at mega 2560] Avr assembler - odczyt z pamięci programu

MaaXX 09 Gru 2008 22:36 4205 8
  • #1 5839741
    MaaXX
    Poziom 2  
    Mecze się już kilka godzin próbując odczytać tablicę umieszczoną w pamięci programu i po kolei umieszczać odczytane wartości w rejestrze np: R0. Oto cześć kodu:


    ldi R28, low(tab) ;adres tablicy
    ldi R29, high(tab)
    lpm R0,R

    .ORG 0x121
    tab: .DB 1,2,3,4,5,0 ; jakaś tablica
    .EXIT

    Oczywiście to nie zadziała . Adres tablicy został poprawnie odczytany i w rejestrach R28 i R29 są jego dwie części ale trzecia linijka jest błędna.
    Jak to powinno poprawnie wyglądać?
  • #2 5839810
    asembler
    Poziom 32  
    Czasami rozkazy LPM,SPM dzialają z rejestrami ZL,ZH (R30,R31)
    ld r30,....
    ld r31..........
    LPM lub LPM r16,Z
  • #3 5839869
    MaaXX
    Poziom 2  
    asembler napisał:
    Czasami rozkazy LPM,SPM dzialają z rejestrami ZL,ZH (R30,R31)
    ld r30,....
    ld r31..........
    LPM lub LPM r16,Z


    No właśnie u mnie "ZL" i "ZH" nie działają. Sam zauważyłem przeglądając inne strony ,że często zamiast nazwami rejestrów ludzie posługują się czymś takim. U mnie gdy próbuje czegoś takiego użyć zamiast nazw rejestrów kompilator wyrzuca błędy.
  • #4 5839889
    asembler
    Poziom 32  
    Jezeli uzywasz ZL,ZH to muszą byc te symbole wczesniej zdefiniowane
    moze uzyj poprostu r30,r31. Tylko te rejestry są uzywane jako wskaznikowe do odczytu/zapisu falsha

    .def zl=R30
    .def zh=r31
  • #5 5839935
    MaaXX
    Poziom 2  
    asembler napisał:
    Jezeli uzywasz ZL,ZH to muszą byc te symbole wczesniej zdefiniowane
    moze uzyj poprostu r30,r31. Tylko te rejestry są uzywane jako wskaznikowe do odczytu/zapisu falsha

    .def zl=R30
    .def zh=r31


    Dzięki coś już zaczęło działać ale nie do końca tak jak powinno.
    Tzn do rejestru R16 trafia wartość ale ciągle jest to FF a powinny być kolejne wartości z tablicy. Kod wygląda teraz tak:

    ldi zl, low(tab) ;adres tablicy
    ldi zh, high(tab)
    lpm R16,z+
    lpm R16,z+

    .ORG 0x121
    tab: .DB 1,2,3,4,5,0 ; nasza tablica :P
    .EXIT

    Podejrzałem pamięć programu i oczywiście tablica jest widoczna na swoim miejscu tzn od pozycji 121h więc nie wiem skąd jest kopiowane to FF :/
  • #6 5839991
    asembler
    Poziom 32  
    Pamietaj ze procesor czyta rozkazy 16 bitowo a ty chcesz odczytac 8 bitowo wiec prawdopodobnie tablice bedziesz mial w miejscu 2xtab
    druga sprawa nie mozesz uzywac nieparzystych "ORG 121' Z TEGO SAMEGO POWODU CO WYZEJ
  • #7 5840011
    zumek
    Poziom 39  
    MaaXX napisał:
    Mecze się już kilka godzin próbując odczytać tablicę umieszczoną w pamięci programu ...

    Gdyby te kilka godzin przeznaczyć na przestudiowanie dokumentacji, a w szczególności listy rozkazów, to nie było by tego tematu.
    Atmel w dokumentacji napisał:

    
    Example:
    
    ldi ZH, high(Table_1<<1)              ; Initialize Z pointer
    
    ldi ZL, low(Table_1<<1)
    
    lpm r16, Z                                   ; Load constant from program
    
    

    Przy korzystaniu z instrukcji LPM, adres komórki pamięci programu, MUSI być pomnożony przez 2 i umieszczony w parze rejestrów "Z" (R30,R31)
    Z tego co tu autor napisał jasno wynika , że dokumentacją po prostu się "brzydzi" - regulamin p.16
  • #8 5840049
    MaaXX
    Poziom 2  
    Poprawcie mnie jeżeli się mylę ale w powyższy sposób można chyba odwołać się do adresu max FFFFh (64kb) , jak zatem czytać tablicę np od 82kb ?
    Innymi słowy czy można stworzyć wskaźnik składający się z trzech rejestrów ?

    I druga sprawa to skoro lpm nie można stosować po to aby odwołać się do tablic zaczynających się "nieparzyście" , to czego nalezy użyć aby to stało się wykonalne.
    Z tego co wyczytałem to "There is only one command for the read access to the program storage. It is defined for the pointer pair Z and it is named LPM (Load from Program Memory)."

    Zatem nie ma innej opcji jak użyć komendy LPM. To jak w takim razie dostać się do obszaru programu >64KB ?
  • #9 5840421
    kozi25
    Poziom 10  
    Wydaje mi się, że to jest tak:
    MaaXX napisał:
    Poprawcie mnie jeżeli się mylę ale w powyższy sposób można chyba odwołać się do adresu max FFFFh (64kb) , jak zatem czytać tablicę np od 82kb ?
    Innymi słowy czy można stworzyć wskaźnik składający się z trzech rejestrów ? ?

    Mikrokontrolery o pamięci powyżej 64kB mają dodatkowy rejestr RAMPZ do wyboru stron pamięci. Instrukcja lpm daje dostęp do pierwszych 64kB. Wykorzystanie adresowania RAMPZ, ZH ,ZL wymaga użycia instrukcji elpm.

    Cytat:
    I druga sprawa to skoro lpm nie można stosować po to aby odwołać się do tablic zaczynających się "nieparzyście" , to czego nalezy użyć aby to stało się wykonalne.


    Początek tablicy może być w dowolnym słowie, ale zawsze na jego początku, czyli w parzystym bajcie.
    .ORG może również wskazywać na adres nieparzysty, ponieważ jest to adres słowa (czyli pary bajtów) w pamięci programu.
    Instrukcje lpm, elpm, spm adresuje się bajtowo, jednak zapis (spm) przeprowadzany jest dla całego słowa, stąd adres w tym przypadku musi być parzysty (bo wskazuje na pierwszy bajt słowa).

    Przykład odczytu nieparzystego bajtu:
    .ORG adres_słowa
    Tablica: .DB 1,2,3,4        ; deklaracja tablicy
    
    ..........
    
    ldi ZL, low(adres_słowa*2 + 1)   ; wyliczenie adresu w bajtach
    ldi ZH, high(adres_słowa*2 + 1)
    lpm R0, Z                 ; odczyt i zapis do rejestru roboczego
    
    //albo:
    
    ldi ZL, low(Tablica*2 + 1)    ; wyliczenie adresu w bajtach
    ldi ZH, high(Tablica*2 + 1)
    lpm R0, Z


    pozdr
REKLAMA