• AVR Freaks

Helpful ReplyHot![SOLVED] PIC16 FSR question

Author
Richard Rasker
Starting Member
  • Total Posts : 66
  • Reward points : 0
  • Joined: 2013/02/14 09:03:07
  • Location: 0
  • Status: offline
2019/09/05 01:35:06 (permalink)
0

[SOLVED] PIC16 FSR question

Hello,
I have a (hopefully) simple question about initializing FSR registers.
I'm using a PIC16F15376 in a motor control application, where I declared the following variables:
; Variables
GPR_VAR UDATA
ENCSETL res 1 ; Encoder pulse time set value low byte
ENCSETH res 1 ; Encoder pulse time set value high byte
XENCL res 1 ; Current X encoder count low byte, from start position
XENCH res 1 ; Current X encoder count high byte, from start position
XMAXL res 1 ; Maximum calibrated X encoder count low byte
XMAXH res 1 ; Maximum calibrated X encoder count high byte
 
CUR_POS res 1 ; Current position
 
XFLAGS res 1; Several flags

 
I want to save these consecutive register values in the Storage Area Flash memory via FSR0H:FSR0L, but how do I initialize FSR0? The code examples with FSR0 and indirect addressing that I can find are all based on known values for FSR0L and FSR0H.
I can of course define the location of the first variable with GPR_VAR UDATA 0x20 and set FSR0L to 0x20 too (with FSR0H=0), but I think that this creates an unnecessary constraint, and that there must be a generic way to enter an arbitrary register address in an FSR register pair.
 
Could someone enlighten me on this? Thanks in advance.
post edited by Richard Rasker - 2019/09/05 02:24:44
#1
ric
Super Member
  • Total Posts : 25215
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: offline
Re: PIC16 FSR question 2019/09/05 02:17:25 (permalink) ☄ Helpfulby Richard Rasker 2019/09/05 03:25:40
+1 (1)
You're over-thinking this.
Just do
        movlw   low ENCSETL
        movwf   FSR0L
        movlw   high ENCSETL
        movwf   FSR0H



 
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#2
Richard Rasker
Starting Member
  • Total Posts : 66
  • Reward points : 0
  • Joined: 2013/02/14 09:03:07
  • Location: 0
  • Status: offline
Re: PIC16 FSR question 2019/09/05 02:23:06 (permalink)
0
Ah yes, of course - this is what I was looking for, I knew it should be simple!
 
Thanks!
#3
mpgmike
Super Member
  • Total Posts : 342
  • Reward points : 0
  • Joined: 2014/01/23 17:27:06
  • Location: NJ
  • Status: online
Re: [SOLVED] PIC16 FSR question 2019/09/05 02:35:20 (permalink) ☄ Helpfulby Richard Rasker 2019/09/05 03:25:31
0
For starters, SAFEN = OFF in your CONFIGs.
 
Take a good look at Section 13.0 (page 179) of the Data Sheet regarding Reading & Writing NVM.  Section 13.2 specifically covers using INDF access.
 
TB3163 should fill in the rest of the blanks

I don't need the world to know my name, but I want to live a life so all my great-grandchildren proudly remember me.
#4
Richard Rasker
Starting Member
  • Total Posts : 66
  • Reward points : 0
  • Joined: 2013/02/14 09:03:07
  • Location: 0
  • Status: offline
Re: PIC16 FSR question 2019/09/05 03:33:58 (permalink)
0
For starters, SAFEN = OFF in your CONFIGs.

Yes, I already found that one - although now that you mention it, I have another question: am I correct to assume that code protection (_CP_ON) also extends to SAF?

A planned feature is reserving a dozen or so SAF locations for error and warning information, to be read out later - and because my hardware doesn't feature a display, it would be nice if this reading could simply be done with my programmer (PICKit 4).

If this is not possible with code protection enabled, I must come up with another way to access any stored information, e.g. an LED blinking code (although this is of course only practical for a handful of possible error values).

Thanks,
Richard
#5
Richard Rasker
Starting Member
  • Total Posts : 66
  • Reward points : 0
  • Joined: 2013/02/14 09:03:07
  • Location: 0
  • Status: offline
Re: [SOLVED] PIC16 FSR question 2019/09/05 03:35:08 (permalink)
0
For starters, SAFEN = OFF in your CONFIGs.

Yes, I already found that one - although now that you mention it, I have another question: am I correct to assume that code protection (_CP_ON) also extends to SAF?
 
A planned feature is reserving a dozen or so SAF locations for error and warning information, to be read out later - and because my hardware doesn't feature a display, it would be nice if this reading could simply be done with my programmer (PICKit 4).
If this is not possible with code protection enabled, I must come up with another way to access any stored information, e.g. an LED blinking code (although this is of course only practical for a handful of possible error values).
 
Thanks,
 
Richard
#6
mpgmike
Super Member
  • Total Posts : 342
  • Reward points : 0
  • Joined: 2014/01/23 17:27:06
  • Location: NJ
  • Status: online
Re: [SOLVED] PIC16 FSR question 2019/09/05 14:21:59 (permalink)
+1 (1)
Register 5-4, CONFIGURATION WORD 4: MEMORY, page 106 of the Data Sheet has more answers.

I don't need the world to know my name, but I want to live a life so all my great-grandchildren proudly remember me.
#7
Richard Rasker
Starting Member
  • Total Posts : 66
  • Reward points : 0
  • Joined: 2013/02/14 09:03:07
  • Location: 0
  • Status: offline
Re: [SOLVED] PIC16 FSR question 2019/09/07 04:39:49 (permalink)
0
Yes, I found that information, but it doesn't say if code protection extends to SAF or not.
 
Anyway, I specified _CP_ON, and it turns out that code protection indeed extends to the contents of the SAF area. There appears to be no way to protect the program code, yet still read some persistent data -- something that is possible in many other PIC devices. So I can't log errors in flash, at least not in a way that I can read back using a programmer device.
 
Also, I still have some questions with regard to FSR0 and the location of my variables, in particular the assembler's choice for my data with GPR_VAR UDATA.
 
Here's the relevant code:
 
Constant and variable definitions:

SAFADD_L  equ 0x80            ; High-endurance flash memory (SAF) starts at 0x3F80
SAFADD_H  equ 0x3F
 
; The following ten bytes must be saved at power-down
GPR_VAR UDATA
CUR_STG res 1 ; Current position; closed = 0, open = 1 (1 motor) or 3 (2 motors)
XENCL res 1 ; Current X encoder count low byte, from open position
XENCH res 1 ; Current X encoder count high byte, from open position
XMAXL res 1 ; Maximum calibrated X encoder count low byte
XMAXH res 1 ; Maximum calibrated X encoder count high byte
XDIV8 res 1 ; Single-byte X encoder count
XMAX8 res 1 ; Single-byte maximum calibrated X encoder count
XREM8 res 1 ; Single-byte remaining X encoder counts
COMMAND res 1 ; Broadcast command byte
    #define CMD_OPEN COMMAND,0 ; Open command
    #define CMD_CLS COMMAND,1 ; Close command
FLAGS res 1
    #define FL_RCREC FLAGS,0 ; Signals RC receive in progress
    #define FL_RCVAL FLAGS,1 ; Signals valid RC command
    #define FL_ENCFB FLAGS,2 ; Signals encoder feedback speed control
    #define FL_STEND FLAGS,3 ; Signals end position reached
    #define FL_CALD FLAGS,4 ; Signals calibrated stage
    #define FL_XONLY FLAGS,5 ; Signals system without Z direction

 
Erase + write procedure:
; Power-down sequence
powerdn
 bcf LED_GN ; Switch off all current consumers
 bcf PWM_EN
 bsf LED_RED
 movlw 0x0A
 movwf COUNTER
 
; Erase flash user data
erasef
 bcf INTCON, GIE ; Stop all interrupts
 movlw low CUR_STG ; Load first data address in FSR0 (CUR_STG) <- THIS DOESN'T WORK?
 movwf FSR0L
 movlw high CUR_STG
 movwf FSR0H
 banksel NVMADRL
 movlw SAFADD_L ; Load first SAF address (=0x3F80)
 movwf NVMADRL
 movlw SAFADD_H
 movwf NVMADRH
 bcf NVMCON1,NVMREGS
 bsf NVMCON1,FREE
 bsf NVMCON1,WREN
 call unlockf
 bcf NVMCON1,WREN
; Flash write routine
fwrite
 movlw SAFADD_L ; Load first SAF address (=0x3F80)
 movwf NVMADRL
 movlw SAFADD_H
 movwf NVMADRH
 bcf NVMCON1,NVMREGS ; Set Program Flash Memory as write location
 bsf NVMCON1,WREN ; Enable writes
 bsf NVMCON1,LWLO ; Load only write latches
writelp
 moviw FSR0++
 movwf NVMDATL ; Load data byte into NVM
 decf COUNTER
 btfsc STATUS,Z ; 10 bytes saved in latch?
 goto writedo ; Yes: write latches into memory
 call unlockf ; No: continue loading latch
 incf NVMADRL,F ; Increment address
 goto writelp
writedo
 bcf NVMCON1,LWLO ; Latch writes complete, now write memory
 call unlockf ; Perform required unlock sequence
 bcf NVMCON1,WREN ; Disable writes
 sleep ; No further action until POR
; NVM Unlock sequence
unlockf
 movlw 0x55
 movwf NVMCON2
 movlw 0xAA
 movwf NVMCON2
 bsf NVMCON1,WR ; Set WR bit to begin write/erase
 return

 
And a simple check of the first variable address at the end:
 ORG 0x3F80
 retlw low CUR_STG
 retlw high CUR_STG
 
    END

 
I noticed the following:
  • Immediately after programming, the first SAF addresses (0x3F80/1) shows that my first variable is apparently located at address 0x06A0, so in Bank 13, not in Bank 0 as I would expect. Is this normal?
  • The erase and write procedures work OK, but my registers aren't saved. Instead, only 0x00 values are written to SAF - so it appears that FSR0 doesn't point to the start of my data, but to some unused part of RAM - which would be consistent with the previous point.
  • However, if I force 0x0020 as the start of user data (GPR_VAR UDATA 0x0020), things work as expected: at 0x3F80 I see 0x0020 as the address for CUR_STG, and after running the code, I see the ten register values I expect.
So do I need to explicitly specify the start address of my user data if I want to refer to it via FSR0, or have I made some other mistake? I think that it is important that I fully understand what is going on.
 
Thanks once again for any explanation.
#8
Jump to:
© 2020 APG vNext Commercial Version 4.5