Search code examples
debuggingassemblymicrocontrollerpicmicrochip

How do I clear the RAM correctly when using indirect addressing with PIC16F1829


How do you clear the RAM and initialize the FSR0 register correctly when using indirect addressing with PIC16F1829?

The code works. My problem is that when debugging, the variables (i.e., Delay1 & Delay2 in this case) whose values should be stored at address 0x70 and 0x71 are being stored at 0x120 and 0x121 respectively, despite the FSR0 register holding the 0x70 address.

enter image description here

I do not know what I have missed, as there are not many examples of using a 16-bit FSR register around. Therefore, any assistance that anyone can provide will be very much appreciated.

LIST        p=16f1829   ;list directive to define processor
#INCLUDE    <p16f1829.inc>  ;processor specific variable definitions

 __CONFIG _CONFIG1, (_FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF);
 __CONFIG _CONFIG2, (_WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _LVP_OFF);

;-------------------------------------------------------------------------

; UDATA declares a section of uninitialised data
VARIABLES   UDATA       ; VARIABLES is the name of the section of memory
Delay1      RES 1       ; uninitialised data, placed by linker in GPR's.
Delay2      RES 1       ; uninitialised data, placed by linker in GPR's.


;-------------------------------------------------------------------------
; RESET VECTOR
;-------------------------------------------------------------------------

RESET_VECTOR    CODE    0x0000
    GOTO    START   

;-------------------------------------------------------------------------
; INTERRUPT SERVICE ROUTINE
;-------------------------------------------------------------------------

INT_VECTOR  CODE    0x0004  ; Interrupt vector location
    GOTO    START

;-------------------------------------------------------------------------
; MAIN PROGRAM
;-------------------------------------------------------------------------

MAIN_PROG   CODE

START

;-------------------------------------------------------------------------
; SET OSCILLATOR TO FACTORY FREQUENCY AND CLEAR GPR's
;-------------------------------------------------------------------------

    ERRORLEVEL -302     ; Disable warning accessing register not in bank 0
    BANKSEL OSCTUNE     ; Configure OPTION_REG and TMR0
    MOVLW   0x00        ; Set oscillator to factory calibrated frequency
    MOVWF   OSCTUNE     ;
    BANKSEL STATUS
    ERRORLEVEL +302     ; Enable warning accessing register not in bank 0

CLEAR_RAM               ; code sequence initialises all GPR's to 0x00                           
    MOVLW   0x70        ; initialise pointer to RAM
    MOVWF   FSR0L
    CLRF    FSR0H

NEXT
    CLRF    INDF0       ; clear INDF0 register
    INCF    FSR0L, F    ; inc pointer
    BTFSS   FSR0L, 7    ; all done?
    GOTO    NEXT        ; no clear NEXT

CONTINUE            ; yes CONTINUE
    NOP

;-------------------------------------------------------------------------
; REMAINDER OF PROGRAM 
;-------------------------------------------------------------------------
; Setup main init
    BANKSEL OSCCON          ; Selects memory bank containing OSCCON register 
    MOVLW   b'00111000'     ; Set CPU clock speed of 500KHz -> correlates to (1/(500K/4)) for each instruction
    MOVWF   OSCCON          ; OSCCON <- 0x38

; Configure the LEDs        
    BCF     TRISC,0             ; Make I/O Pin C0 an output for DS1
    
    BANKSEL LATC            ; Selects memory bank containing LATC
    CLRF    LATC            ; Start by turning off all of the LEDs

MAINLOOP:
    BSF LATC, 0         ; Turn LED on
 
ONDELAYLOOP:
    DECFSZ  Delay1,f        ; Waste time.
    BRA     ONDELAYLOOP     ; The Inner loop takes 3 instructions per loop * 256 loops = 768 instructions
    DECFSZ  Delay2,f        ; The outer loop takes an additional 3 instructions per lap * 256 loops
    BRA     ONDELAYLOOP     ; (768+3) * 256 = 197376 instructions / 125K instructions per second = 1.579 sec.
    BCF     LATC,0          ; Turn off LED C0 - NOTE: do not need to switch banks with 'banksel' since bank2 is still selected

OFFDELAYLOOP:
    DECFSZ  Delay1,f        ; same delay as above
    BRA     OFFDELAYLOOP
    DECFSZ  Delay2,f
    BRA     OFFDELAYLOOP
    BRA     MAINLOOP        ; Do it again...

;-------------------------------------------------------------------------
; END OF PROGRAM
;-------------------------------------------------------------------------

    END         ; End of program

Solution

  • The answer is that your code:

    ; UDATA declares a section of uninitialised data
    VARIABLES   UDATA       ; VARIABLES is the name of the section of memory
    Delay1      RES 1       ; uninitialised data, placed by linker in GPR's.
    Delay2      RES 1       ; uninitialised data, placed by linker in GPR's.
    

    Tells the assembler to place these in banked memory.

    To place data in common (non-banked) memory use this syntax with MPASM:

    ; UDATA_SHR declares a section of uninitialised data common to all banks
    VARIABLES   UDATA_SHR   ; VARIABLES is the name of the section of memory
    Delay1      RES 1       ; uninitialised data, placed by linker in GPR's.
    Delay2      RES 1       ; uninitialised data, placed by linker in GPR's.