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

[dsPIC] [dsPIC][asm30] Długi czas wykonania instrukcji nop w __reset, przyczyny?

dex 27 Mar 2008 17:30 4133 10
REKLAMA
  • #1 4956117
    dex
    Poziom 27  
    Posty: 1299
    Pomógł: 40
    Ocena: 100
    Zmontowałem taki mały "program"

    .include "p30f4013.inc";
    .global __reset;
    
    .text ;start Code section
    __reset:
    nop
    
    .org 0x0100
    Loop:
    nop
    goto Loop
    

    Instrukcja nop ( ta po __reset) debuguje/wykonuje sie jakieś 40sekund i nonstop wyskakuje:

    Cytat:
    "Stepping Target
    MPLAB ICD 2 Ready
    Stepping Target
    MPLAB ICD 2 Ready
    Stepping Target
    MPLAB ICD 2 Ready
    ...
    "

    Mplab podczas tego jakby przestawał odpowiadać.
    Czy tak ma być? czy to wina braku definicji stosu, czy to jakiś zonk??

    Pózniej jak skończy te jakies 40 sekund wałkować tego pierwszego nopa, zapętlenie Loop<>goto Loop działa już normalnie, jedno kliknięcie"step into" i wykonuje rozkazy prawidłowo-szybko.
  • REKLAMA
  • #2 4956181
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    a co jest PO tej instrukcji nop? bo skoro petle recznie postawiles pod adreem 0x100, to cholera wie co jest pomiedzy nimi... tak w ogole to ASM30 jest object assemblerem i nie powinno sie uzywac recznego ustawiania czesci kodu. jak juz trzeba, to lepiej zrobic to przez definicje sekcji i nastepnie zadeklarowanie czesci kodu jako nalezacej do danej sekcji.

    ponizej przykladowy najprostszy kod dla 16b PICow (przyklad akurat dla PIC24, ale na dsPICu dziala tak samo).

    
    .equ        __24HJ256GP210,     1
            
            .include    "p24HJ256GP210.inc"     ; basic definitions
            
    ;———————————————————————————————————————————————————————————————————————————————;
    ; globals:                                                                      ;
    ;_______________________________________________________________________________;
    
            .global __reset
    
    ;———————————————————————————————————————————————————————————————————————————————;
    ; CODE                                                                          ;
    ;_______________________________________________________________________________;
    
    .text                               ;Start of Code section
    
    __reset:
            MOV #__SP_init, W15         ;Initalize the Stack Pointer
            MOV #__SPLIM_init, W0       ;Initialize the Stack Pointer Limit Register
            MOV W0, SPLIM
            NOP                         ;Add NOP to follow SPLIM initialization
            
            RCALL _wreg_init             ;Call _wreg_init subroutine
    
    ; user code starts here ->
                                        
            clr     TRISE               ; port E - output
            clr     LATE                ; clear the latch
    
    led:    btg     LATE,#RE7           ; toggle pin 7 of port E
            call    delay
            bra     led
    
            
    done:
            PWRSAV  #0                  ; go into sleep mode (CPU OFF)
            BRA     done                ;Place holder for last line of executed code
    
    
    
    ;———————————————————————————————————————————————————————————————————————————————;
    ;Subroutine: Initialization of W registers to 0x0000
    ;_______________________________________________________________________________;
    
    _wreg_init:
            CLR     W0
            MOV     W0,W14
            REPEAT  #12
            MOV     W0,[++W14]
            CLR     W14
            RETURN
            
    ;———————————————————————————————————————————————————————————————————————————————;
    ; delay                                                                         ;
    ;_______________________________________________________________________________;
    
    delay:
            setm    w0              ; w0 = 0xFFFF
    1:      repeat  #100            ; repeat 'nop' 100 times
            nop
            dec     w0,w0           ; decrement w0
            bra     NZ,1b           ; keep decrementing until 0
            
            return
            
    ;———————————————————————————————————————————————————————————————————————————————;
    ; configuration bits                                                            ;
    ;_______________________________________________________________________________;
    
            config FBS, RBS_NO_RAM & BSS_NO_FLASH & BWRP_WRPROTECT_OFF
                    ; no boot segment
            config FSS, RSS_NO_RAM & SSS_NO_FLASH & SWRP_WRPROTECT_OFF
                    ; no secure segment
            config FGS, GSS_OFF & GCP_OFF & GWRP_OFF
                    ; no code protection
            config FOSCSEL, FNOSC_FRC & IESO_OFF
                    ; internal FRC oscillator
            config FOSC, FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_HS
                    ; clock switching disabled, clock monitor disabled, OSCO pin has
                    ; clock out function, primary oscillator - high speed mode
            config FWDT, FWDTEN_OFF & WINDIS_OFF &  WDTPRE_PR128 &  WDTPOST_PS32768
                    ; watchdog timer disabled
            config FPOR, FPWRT_PWR128
                    ; power up timer - 128ms
    
    ;================================= end of code =================================;
    
    .end                               ; end of code in this file
    
    


    w kodzie asm wymagane jest kilka fajnych rzeczy: na poczatku inicjalizacja SP i SPLIM jest mocno wskazana [; nastepnie wskazane jest zainicjalizowanie wszystkich rejestrow WREG, poniewaz wg dokumentacji, jesli przypadkowo zostanie ktorys z nich uzyty w formie zrodla danych bez wczesniejszej inicjalizacji (czyli jakiegokolwiek zapisu), to moga sie dziac dziwne rzeczy... tak wiec stos, wreg_init i mozna pisac kod. wskazane jest na koncu wstawienie nieskonczonej petli (tu akurat z dodatkowym wejsciem w tryb SLEEP). na koncu kodu mozna wrzucic bity konfiguracyjne (opis w pliku naglowkowym), a na samym samym koncu pliku nalezy wrzucic '.end' i za nim entera.

    taki totalnie pusty plik bazowy dla asm powinien wygladac wiec mniej wiecej tak:

    
    .equ        __24HJ256GP210,     1
            
            .include    "p24HJ256GP210.inc"     ; basic definitions
            
    ;———————————————————————————————————————————————————————————————————————————————;
    ; globals:                                                                      ;
    ;_______________________________________________________________________________;
    
            .global __reset
    
    ;———————————————————————————————————————————————————————————————————————————————;
    ; CODE                                                                          ;
    ;_______________________________________________________________________________;
    
    .text                               ;Start of Code section
    
    __reset:
            MOV #__SP_init, W15         ;Initalize the Stack Pointer
            MOV #__SPLIM_init, W0       ;Initialize the Stack Pointer Limit Register
            MOV W0, SPLIM
            NOP                         ;Add NOP to follow SPLIM initialization
            
            RCALL _wreg_init             ;Call _wreg_init subroutine
    
    ; user code starts here ->
    
    ; <- user code ends here
            
            BRA     $                ;Place holder for last line of executed code
    ; if there are no interrupts, the line above can be fully replaced by: PWRSAV #0, which stops the CPU and peripherals.
    
    ;———————————————————————————————————————————————————————————————————————————————;
    ;Subroutine: Initialization of W registers to 0x0000
    ;_______________________________________________________________________________;
    
    _wreg_init:
            CLR     W0
            MOV     W0,W14
            REPEAT  #12
            MOV     W0,[++W14]
            CLR     W14
            RETURN
    
    ;================================= end of code =================================;
    
    .end                               ; end of code in this file
    
    



    co do twojego pytanka - czasem problem ten pojawia sie na prockach, ktore maja wiecej niz jedna pare pinow do programowania. zaprogramujesz go kazda para, ale para uzywana do debuggowania musi byc w sposob jasny zdefiniowana w bitach konfiguracyjnych. nie wiem czemu, ale w naglowkach assemblerowych nie ma definicji do ustawienia akurat tej rzeczy, w naglowkach C jest zdefiniowane makro:

    
    // bckgr debug off, reset into operational mode, jtag disabled, debugger on ch2
    _FICD(BKBUG_OFF & COE_ON & JTAGEN_OFF & ICS_PGD2)
    


    dlatego tez w assemblerze akurat debugowanie nalezy definiowac przez menu w MPLABie niestety (dotyczy to oczywiscie tylko prockow, ktore maja wiecej niz jedna pare pinow do debuggowania (EMUD/EMUC).

    wglebiajac sie jeszcze bardziej - problem twoj wynikal z tego, ze PICe sa debugowane w sposob programowy - kompilacja i linkowanie programu w trybie Debug powoduje, ze do kodu dodawany jest gdzies bonusowy fragment zajmujacy sie obsluga debuggowania i rezerwowane jest 80b RAMu (na dsPICach, bo na slabszych prockach oczywiscie mniej [; ). z tego powodu, bez uprzedniego zaprogramowania procesora kodem w trybie debug, ICD2 nie jest w stanie sie z czymkolwiek polaczyc.

    uwaga techniczna - goto jest w stanie skoczyc wszedzie, bra tylko do +/- 32k w pamieci. niemniej jednak rzadko pisze sie tak wielki kod, aby goto bylo potrzebne, wiec mozna stosowac bra, ktore zajmuje 1slowo kodu, natomiast goto zajmuje dwa. taka sama roznica jest miedzy call a rcall (rcall jest mniejsze i potrafi skoczyc tylko 'blisko')

    0x41 0x56 0x45!!
  • REKLAMA
  • #3 4956218
    dex
    Poziom 27  
    Posty: 1299
    Pomógł: 40
    Ocena: 100
    Tak to była wina tego org-a. Czy mam rozumieć że .text =.org 0x100 ?
    W moim picu obszar dla programu zaczyna się od adresu 0x100 własnie, aa podobno .text zaczyna sekcję kodu.
  • #4 4956247
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    zmodyfikowalem swojego posta z 10x wiec jakby co, to przeczytaj raz jeszcze.

    definicji sekcji .text (gdyz jest to najzwyklejsza sekcja) szukaj w pliku linkera twoj_model_procka.gld, ktory dolaczasz do projektu.

    dla mojego procka, na samym poczatku pliku jest:

    
    /*
    ** Memory Regions
    */
    MEMORY
    {
      data  (a!xr) : ORIGIN = 0x800,         LENGTH = 0x4000
      reset        : ORIGIN = 0x0,           LENGTH = 0x4
      ivt          : ORIGIN = 0x4,           LENGTH = 0xFC
      aivt         : ORIGIN = 0x104,         LENGTH = 0xFC
      program (xr) : ORIGIN = 0x200,         LENGTH = 0x2AA00
      FBS          : ORIGIN = 0xF80000,      LENGTH = 0x2
      FSS          : ORIGIN = 0xF80002,      LENGTH = 0x2
      FGS          : ORIGIN = 0xF80004,      LENGTH = 0x2
      FOSCSEL      : ORIGIN = 0xF80006,      LENGTH = 0x2
      FOSC         : ORIGIN = 0xF80008,      LENGTH = 0x2
      FWDT         : ORIGIN = 0xF8000A,      LENGTH = 0x2
      FPOR         : ORIGIN = 0xF8000C,      LENGTH = 0x2
      FICD         : ORIGIN = 0xF8000E,      LENGTH = 0x2
      FUID0        : ORIGIN = 0xF80010,      LENGTH = 0x2
      FUID1        : ORIGIN = 0xF80012,      LENGTH = 0x2
      FUID2        : ORIGIN = 0xF80014,      LENGTH = 0x2
      FUID3        : ORIGIN = 0xF80016,      LENGTH = 0x2
    }
    


    interesuje cie sekcja program, w ktorej zlokalizowana jest sekcja .text.

    jesli nie potrzebujesz udziwnien, typu lokalizacja niektorych czesci kodu w konkretnym miejscu, to w ogole adresami sie nie przejmujesz i caly swoj kod piszesz w sekcji .text

    0x41 0x56 0x45!!
  • REKLAMA
  • #5 4956617
    dex
    Poziom 27  
    Posty: 1299
    Pomógł: 40
    Ocena: 100
    Myśle nad inicjalizacją wskażnika stosu mianowicie:


    
    __reset: 
    1:        MOV #__SP_init, W15         ;Initalize the Stack Pointer 
    2:       MOV #__SPLIM_init, W0       ;Initialize theStackPointerLimitRegister
    3:        MOV W0, SPLIM 
    4:       NOP   
    


    Dlaczego składnia jest odwrócona? GRRRR!! W AVR mov r0,r16 kopiuje r16 do r0.
    Dlaczego nie robią od razu zamiast 2i3 tak:
    MOV #__SPLIM_init, SPLIM ?

    I po co ten nop na końcu, załadowanie SPLIM trwa więcej cykli?

    --------------------------
    Jeszcze dwa pytania w kwestii formalnej obsługi ICD2:
    1.MPLAB odpalony, ICD2 skonektowany jako programmer. Na gorąco wyciągam ICD2 z USB, podczas włączonego mplaba. Żeby sie zakonektował ponownie musze zamknąć mplab wyciągnać jeszcze raz z USB i z powrotem wsadzić do USB, po czym uruchomić ponownie mplaba i konektować jako programmer, tak ma być ?

    2. Pracuję jako z ICD2 jako debugger. Czy by procesor działał samodzielnie, bez debagowania musze przestawić ICD2 jako programmer zrobić ponownie kompilację, zaprogramować procesor oraz dodatkowo muszę rozłączyć złącze ICSP? Doszedłęm do tego doświadczalnie, ale pytam czy dobrze postępuje.

    Czy widziałeś gdzies tabelę rozkazów ale posegregowaną wg typów operacji, np operacje matematyczne, operacje na portach, operacje bitowe, skoki warunkowe itd. Spis alfabetyczny mi nie pasuje..
  • #6 4957191
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    dla ciebie jest odwrocona, dla mnie jest normala [;

    move skad,dokad [;

    co do zrobienia na raz. poczytalbys datasheeta to bys wiedzial (a jeszcze lepiej programmers reference manual). otoz jedynym wariantem instrukcji mov, ktory przyjmuje wartosc stala (intermediate addressing) jest mov #lit16,Wnd - wniosek - nalezy najpierw zaladowac jakas liczbe do jakiegos WREGa, a dopiero potem pod jakis adres.

    nop jest... bo tak jest w przykladach [; wszystkich ktore widzialem... ciekawostka - inicjalizacja stosu i wskaznika jego konca dla MSP430 jest identyczna, wlacznie z NOPem na koncu. pewnie wiec tak musi byc i juz.

    jak wyciagniesz icd2, to w sumie mozna go wsadzic ponownie, poczekac chwilke i probowac zrobic reconnect... niemniej jednak - nie polecam takich operacji jak wyciaganie go na zywca [;

    zeby procesor dzialal zupelnie samodzielnie (czyli ze odpala sie program po podlaczeniu zasilania), trzeba tak jak napisales - przestawic z Debug -> Release, przelaczyc na programator, skompilowac jeszcze raz i ponownie zaprogramowac.

    posegregowane rozkazy sa wlasnie w programmers reference manual. strona 25,sekcja 3: instruction set overview. w sekcji 6 jest wytlumaczony dokladnie kazdy z rozkazow.

    0x41 0x56 0x45!!
  • #7 4957291
    dex
    Poziom 27  
    Posty: 1299
    Pomógł: 40
    Ocena: 100
    Cytat:
    zeby procesor dzialal zupelnie samodzielnie (czyli ze odpala sie program po podlaczeniu zasilania), trzeba tak jak napisales - przestawic z Debug -> Release, przelaczyc na programator, skompilowac jeszcze raz i ponownie zaprogramowac.


    A złacze ICSP musisz wyciągnąć?
  • #8 4959107
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Zlacze ICSP zasadniczo ma w sobie linie reset, ktora domyslnie utrzymuje procka w stanie resetu. jesli jednak przelaczysz to w MPLABie a potem wylaczysz ICD2 z USB, to stan ten sie (chyba!) nie zmieni. jesli w procku - przez config - wylaczysz reset, to rowniez nie trzeba odlaczac zlacza, bo i po co [;

    nie do konca kumam twoje pytanie w sumie [; nie prosciej sprawdzic ? <:

    0x41 0x56 0x45!!
  • REKLAMA
  • #9 4959326
    dex
    Poziom 27  
    Posty: 1299
    Pomógł: 40
    Ocena: 100
    Tak już widzę 'Hold' i 'relase' from reset ikonki. O to mi chodziło dzięki.

Podsumowanie tematu

✨ Problem dotyczył długiego czasu wykonania instrukcji NOP umieszczonej bezpośrednio po etykiecie __reset w asemblerze dla dsPIC30F4013. Użytkownik zauważył, że podczas debugowania w MPLAB IDE program zatrzymuje się na tej instrukcji nawet około 40 sekund, po czym dalsze instrukcje w pętli działają normalnie. Przyczyną okazało się ręczne ustawianie adresu kodu za pomocą dyrektywy .org 0x0100, co powodowało nieprawidłowe rozmieszczenie kodu i problemy z inicjalizacją. Zalecano korzystanie z definicji sekcji kodu (.text) zgodnie z plikiem linkera dla danego modelu procesora, zamiast ręcznego ustawiania adresów. Dodatkowo poruszono temat inicjalizacji wskaźnika stosu (SP i SPLIM) w asemblerze dsPIC, gdzie instrukcje MOV wymagają najpierw załadowania wartości do rejestru W, a następnie przeniesienia do rejestru docelowego, co tłumaczyło odwróconą składnię. NOP na końcu inicjalizacji stosu jest standardowym elementem przykładowych kodów i prawdopodobnie koniecznym ze względu na czas wykonania instrukcji. W dyskusji pojawiły się także kwestie dotyczące obsługi debuggera/programatora ICD2, w tym konieczność restartu MPLAB po odłączeniu ICD2 oraz zachowanie linii reset w złączu ICSP podczas debugowania.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA