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!!