PIC16F NVM problem
MPLABX 5.5
PIC16f15313
mpasmx 5.81
PICKit 3
As part of a larger project I need to use non volatile memory. The attached file, I think, is the bare basics to test the NVM operation. It does not appear to be working. I have written a couple of code lines at org 300h to see if they are replaced. Using debug, I halt on the nop after the 'call nvm_write' but there is no change to prog memory 300. I am not saving the row first because I will always be modifying only the first 2 locations. Thanks in advance for any assistance.
list p=16f15313 ; list directive to define processor
#include <F:\PICs\PICLock\PICLock.X\p16f15313.inc> ; processor specific variable definitions
errorlevel -302 ; suppress message 302s fromlist file
errorlevel -306 ; suppress message 306s fromlist file
; program configuration register
; CONFIG1
; __config 0xD7DC
__CONFIG _CONFIG1, _FEXTOSC_OFF & _RSTOSC_HFINT1 & _CLKOUTEN_OFF & _CSWEN_OFF & _FCMEN_OFF
; CONFIG2
; __config 0xE73F
__CONFIG _CONFIG2, _MCLRE_ON & _PWRTE_OFF & _LPBOREN_OFF & _BOREN_OFF & _BORV_LO & _ZCD_OFF & _PPS1WAY_OFF & _STVREN_OFF
; CONFIG3
; __config 0xC080
__CONFIG _CONFIG3, _WDTCPS_WDTCPS_0 & _WDTE_OFF & _WDTCWS_WDTCWS_0 & _WDTCCS_LFINTOSC
; CONFIG4
; __config 0xFFFF
__CONFIG _CONFIG4, _BBSIZE_BB512 & _BBEN_OFF & _SAFEN_OFF & _WRTAPP_OFF & _WRTB_OFF & _WRTC_OFF & _WRTSAF_OFF & _LVP_ON
; CONFIG5
; __config 0xFFFF
__CONFIG _CONFIG5, _CP_OFF
;;/============================================================================
;/ Data storage for nvm row data - 64 bytes
data2: udata 0x0a0
nvm_code res 1
nvm_length res 0x3f
;/============================================================================
; all banks ram (71 to 7e)
data3: udata_shr ; starts at 070
loopcount res 1
addrh res 1
addrl res 1
;/============================================================================
;/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;/============================================================================
org 0x000 ; processor reset vector
goto initialise ; go to beginning of program
;/============================================================================
;/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;/============================================================================
org 0x020
;/============================================================================
initialise:
;/============================================================================
;/ Disable Modules
banksel pmd0
movlw b'01000011'
movwf pmd0
movlw b'10000010'
movwf pmd1
movlw b'01100111'
movwf pmd2
movlw b'00111111'
movwf pmd3
movlw b'00011110'
movwf pmd4
movlw b'01010001'
movwf pmd5
;/============================================================================
;/ PortA
banksel ansela
clrf ansela ; All digital I/O
banksel trisa
clrf trisa
bsf trisa,2
banksel wpua
clrf wpua
bsf wpua,2 ; Weak Pullup on RA2
banksel porta
clrf porta
banksel lata
clrf lata
;/============================================================================
;/ Clear RAM 0x0a0 64 bytes
bankisel nvm_code
movlw nvm_code
movwf fsr1
movlw 0x40
movwf loopcount
loop2:
clrf indf1
incf fsr1,f
decfsz loopcount,f
goto loop2
;/============================================================================
;/ Clear All banks RAM
clrf addrh
clrf addrl
clrf nvmadr
clrf nvmcon1
clrf nvmcon2
clrf nvmdat
;/============================================================================
;/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;/============================================================================
mainloop:
banksel porta
btfsc porta,2
goto mainloop
call gjc
nop
goto mainloop
gjc:
;/ Erase and write to NVM
movlw b'00000000'
movwf addrl
movlw b'00000011'
movwf addrh
call nvm_erase
banksel nvm_code
movlw d'255'
movwf nvm_code
movlw d'8'
movwf nvm_length
call nvm_write
nop
return
;/============================================================================
nvm_erase:
;/============================================================================
banksel nvmadrl
movfw addrl
movwf nvmadrl ; Load lower 8 bits of erase address boundary
movfw addrh
movwf nvmadrh ; Load upper 6 bits of erase address boundary
bcf nvmcon1,nvmregs ; Choose PFM memory area
bsf nvmcon1,free ; Specify an erase operation
bsf nvmcon1,wren ; Enable writes
; -------------------------------REQUIRED UNLOCK SEQUENCE:------------------------------
bcf intcon,gie ; Disable interrupts during unlock sequence
banksel nvmcon2
movlw 0x55 ; Load 55h to get ready for unlock sequence
movwf nvmcon2 ; First step is to load 55h into nvmCON2
movlw 0xaa ; Second step is to load AAh into W
movwf nvmcon2 ; Third step is to load AAh into nvmCON2
bsf nvmcon1,wr ; Final step is to set WR bit
bsf intcon,gie ; Re-enable interrupts, erase is complete
; --------------------------------------------------------------------------------------
bcf nvmcon1,wren ; Disable writes
return
;/============================================================================
nvm_write:
;/============================================================================
; This write routine assumes the following:
; 1. 64 bytes of data are loaded, starting at the address in nvm_code
; 2. Each word of data to be written is made up of two adjacent bytes in nvm_code,
; stored in little endian format
; 3. A valid starting address (the least significant bits = 00000) is loaded in ADDRH:ADDRL
; 4. ADDRH and ADDRL are located in common RAM (locations 0x70 - 0x7F)
; 5. nvm interrupts are not taken into account
;/ Write nvm - char_str at 0x0300
banksel nvmadrh
movfw addrh
movwf nvmadrh ; Load initial address
movfw addrl
movwf nvmadrl
banksel nvm_code
movlw low nvm_code ; Load initial data address
movwf fsr0l
movlw high nvm_code
movwf fsr0h
banksel nvmcon1
bcf nvmcon1,nvmregs ; Set Program Flash Memory as write location
bsf nvmcon1,wren ; Enable writes
bsf nvmcon1,lwlo ; Load only write latches
loop3:
moviw fsr0++
movwf nvmdatl ; Load first data byte
moviw fsr0++
movwf nvmdath ; Load second data byte
movfw nvmadrl
xorlw 0x1f ; Check if lower bits of address are 00000
andlw 0x1f ; and if on last of 32 addresses
btfsc status,z ; Last of 32 words?
goto start_write ; If so, go write latches into memory
call unlock_seq ; If not, go load latch
incf nvmadrl,f ; Increment address
goto loop3
start_write:
bcf nvmcon1,lwlo ; Latch writes complete, now write memory
call unlock_seq ; Perform required unlock sequence
bcf nvmcon1,wren ; Disable writes
unlock_seq:
; -------------------------------REQUIRED UNLOCK SEQUENCE:------------------------------
bcf intcon,gie ; Disable interrupts
movlw 0x55
movwf nvmcon2 ; Begin unlock sequence
movlw 0xaa
movwf nvmcon2
bsf nvmcon1,wr
; bsf intcon,gie ; Unlock sequence complete, re-enable interrupts
; --------------------------------------------------------------------------------------
return
;/============================================================================
;/============================================================================
;/============================================================================
;/ nvm
; org 300h
;
;;/============================================================================
; retlw d'1'
; retlw d'2'
;/============================================================================
end