Programming QG4 flash problem

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Programming QG4 flash problem

Jump to solution
4,926 Views
paul51
Contributor I
Hi All,

We are using a QG4 with a 4MHz bus frequency. FDIV has been set to provide a 200KHz flash clock. No other registers have been modified.

When we run this code it appears to have erased the entire flash as our code stops working and requires reprogramming. The locations at where the two bytes should be stored are both $00. We have looked at all of the comments on the site regarding the programming of flash but have not found any version that seems to work. Only get one assembly error with this code and that is with the Icont aix instruction.
It looks like we have missed something.

Any help would be appreciated. We have protos to ship in less than a week and this is the only remain piece of code that has a problem.

Thanks in advance.

Paul

; this KBISR loads the current timer modulo value into both registers

FREQ_SAVE   ldhx    $FB00                       ;get beginning address of page to be erased
            jsr     FlashErase1                 ;call erase routine
            ldhx    $FB00                       ;get address to program timer modulo low byte
            lda     TPMMODL                     ;get low byte of timer modulo register     
            jsr     FlashProg1                  ;call routine to program byte to flash memory
            ldhx    $FB01                       ;get next address to program timer modulo high byte
            lda     TPMMODH                     ;get high byte of timer modulo register
            jsr     FlashProg1                  ;call routine to program byte ti flash memory
            bset    FREQ_SAVED,FLAG_1           ;indicate a frequency value is saved in flash
            bra     KBISR_EXIT


;  Flash memory program routines                              


; SUBROUTINE:   FlashProg1
; ON ENTRY:     H:X - points at the flash byte to be programmed
;               A holds the data for the location to be programmed
; ON RETURN:    H:X unchanged and A = FSTAT shifted left by 2 bits
;               Z=1 if OK, Z=0 if protect violation or access error
;               Uses 32 bytes of stack space + 2 bytes for BSR/JSR used to call it
; USES:         DoOnStack which uses SpSub


FlashProg1  psha                    ;temporarily save entry data
            lda     #(mFSTAT_FPVIOL+mFSTAT_FACCERR)    ;mask
            sta     FSTAT           ;abort any command and clear errors
            lda     #mByteProg      ;mask pattern for byte prog command
            bsr     DoOnStack       ;execute prog code from stack RAM
            ais     #1              ;deallocate data location from stack
            rts                     ;Z = 1 means there was an error


; SUBROUTINE:   FlashErase1 
; ON ENTRY:     H:X - points at a location in a page to be erased 
; ON RETURN:    H:X unchanged a A = FSTAT shifted left by 2 bits   
;               Z=1 if OK, Z=0 if protect violation or access error   
;               Uses 32 bytes of stack space + 2 bytes for BSR/JSR used to call it 
; USES:         DoOnStack which uses SpSub

FlashErase1 psha                    ;adjust sp for DoOnStack entry
            lda     #(mFSTAT_FPVIOL+mFSTAT_FACCERR)    ;mask
            sta     FSTAT           ;abort any command and clear any errors
            lda     #mPageErase     ;mask pattern for page erase command
            bsr     DoOnStack       ;finish command from stack based subroutine
            ais     #1              ;de-allocate data location from stack
            rts                     ;Z = 0 means there was an error

; SUBROUTINE:   DoOnStack
; ON ENTRY:     H:X - points at the flash byte to be programmed
;               A holds the data for the location to be programmed
; ON RETURN:    H:X unchanged a A = FSTAT shifted left by 2 bits 
;               Z=1 if OK, Z=0 if protect violation or access error 
;               Uses 32 bytes of stack space + 2 bytes for BSR/JSR used to call it
; USES:         DoOnStack which uses SpSub 

DoOnStack:  pshx       
            pshh                    ;save pointer to flash
            psha                    ;save command to stack
            ldhx    #SpSubEnd       ;point at last byte to move to stack
SpMoveLoop: lda     ,x              ;read from flash
            psha                    ;move onto stack
            aix     #-1             ;next byte to move
            cphx    #SpSub-1        ;past end?
            bne     SpMoveLoop      ;loop until the whole subroutine is on stack
            tsx                     ;point to subroutine on stack
            tpa                     ;move CCR to A for testing
            and     #$08            ;check the I mask
            bne     I_set           ;skip if I already set
            sei                     ;block interupts while flash busy
            lda     SpSubSize+6,sp  ;preload data for command
            jsr     ,x              ;execute the subroutine on the stack
            cli                     ;OK to cleat the I mask now
            bra     I_cont          ;continue to stack de-allocation
I_set:      lda     SpSubSize+6,sp  ;preload data for command
            jsr     ,x              ;execute the subroutine on the stack
I_cont:     ais     #SpSubSize+3    ;de-allocate subroutine body _ H:X + command   !!only error this line!!
                                    ;H:X flash pointer OK from SpSub
            lsla                    ;A=00 & Z=1 unless PVIOL or ACCERR
            rts                     ;to flash where DoOnStack was called


SpSub:      ldhx    <SpSubSize+4,sp ;get flash address from stack  !!The "<" fixed the assemly error!!
            sta     0,x             ;write to flash: latch address and data
            lda     SpSubSize+3,sp  ;get flash command
            sta     FCMD            ;write the flash command
            lda     #mFSTAT_FCBEF   ;mask to initiate command
            sta     FSTAT           ;[pwpp] register command
            nop                     ;[p] want min 4~ from write cycle to read
ChkDone:    lda     FSTAT           ;[prpp] so FCCF is valid
            lsla                    ;FCCF is now in MSB
            bpl     ChkDone         ;loop if FCCF = 0
SpSubEnd:   rts                     ;back into DoOnStack in flash
SpSubSize:  equ     (*-SpSub)          

Labels (1)
0 Kudos
1 Solution
1,387 Views
peg
Senior Contributor IV
Hi all,
 
OK, I tidied it up a bit and made it test the written string to see if it actually worked.
It is assembled with P&E's assembler so I have included the s19 and the LST files as well.
 

View solution in original post

0 Kudos
18 Replies
1,387 Views
thisobj
Contributor III
Hello Paul,

You stated that your code stops when erasing flash memory, indicating that the code is running in flash.  I'm assuming that this was simply a test and that you are not running your real flash programming code in flash memory.  The programming code must reside in RAM memory.

Frank
0 Kudos
1,387 Views
paul51
Contributor I
Hi, thisobj

We are having some problems getting into background debug with the P&E USB emulator so now I am not sure if the flash has all been written with $00. I do know the main loop of our program stops working and the part has to be reprogrammed. If the code we showed here is not loading into the stack I presume this is why the flash is getting wiped.

Thanks,

Paul
0 Kudos
1,387 Views
peg
Senior Contributor IV
Hi Paul,
 
I have not checked your code, but presumably it is basically OK as you have compared it with others.
One thing that came to my attention was...
Are you being careful that no interrupts are being triggered while you are progamming?
They will most likely cause execution to go back to the flash area.
You probably should always globally disable interrupts when you go to ram to do this.
It looks like you may be already doing this though as you are maybe calling this from within an ISR and unless you have deliberately re-enabled them you would be safe.
 
0 Kudos
1,387 Views
paul51
Contributor I
Hi PEG,

Thanks for the response. Interupts are disable during these operations. Still having the same problem.
Is there a particular memory address which the 2 bytes are stored at that may help?

Paul
0 Kudos
1,387 Views
peg
Senior Contributor IV
Hi Paul,
 
Not sure what you meant in your first post "both bytes stored at $00" ???
Not sure on your second post question about this either.
 
The error your getting is possibly resolved by placing the SpSubSize+3 in curly braces.
This exact line error has been discussed here before. Search forums for the variable may find it.
 
[edit]
This may be the one I was thinking of:
 


Message Edited by peg on 2007-11-15 10:32 AM
0 Kudos
1,387 Views
paul51
Contributor I
Hi peg,

I am confused on one thing shown in the code on the link you provided. In the SpSub (see below) the label I_cont is used. The same label is also used in DoOnStack so I get an error on this. Why is label being used in both subroutines?

Thanks,

Paul


                         7 *SpSub:      ldhx LOW(SpSubSize+4),sp ;get flash add
                           ress from stack
 E800  [05] 9EFE1C       8 SpSub:      ldhx SpSubSize+4,sp ;get flash address f
                           rom stack
 E803  [02] F7           9             sta 0,x ;write to flash; latch addr and
                           data
 E804  [05] 9ED6001B    10             lda SpSubSize+3,sp ;get flash command
 E808  [04] C7FEEE      11             sta FCMD ;write the flash command
 E80B  [02] A680        12             lda #FACCERR ;mask to initiate command
 E80D  [04] C7FEEF      13             sta FSTAT ;[pwpp] register command
 E810  [01] 9D          14             nop ;[p] want min 4~ from w cycle to r
 E811  [04] C6FEEF      15 ChkDone:    lda FSTAT ;[prpp] so FCCF is valid
 E814  [01] 48          16             lsla ;FCCF now in MSB
 E815  [03] 2AFA        17             bpl ChkDone ;loop if FCCF = 0
 E817  [06] 81          18 SpSubEnd:   rts ;back into DoOnStack in flash
            00000018    19 SpSubSize:  equ (*-SpSub)
     00
                        20
 E818  [02] A618        21 I_cont: lda #SpSubSize
 E81A  [02] AB03        22         add #3
 E81C  [02] 87          23         psha
                        24
            0000001A    25 test1        equ     $1A
     00
            00000002    26 test2        equ     $2
     00
            00000018    27 test3        equ     (test1-test2)


0 Kudos
1,387 Views
peg
Senior Contributor IV
Hi Paul,
 
The code I presented there is not actually meant to do anything but check the behaviour of the P&E assembler against the CW one. It is, I believe, various fragments of the doonstack routine and other flash programming bits along with another test by me.
 
0 Kudos
1,387 Views
paul51
Contributor I
Hi peg,

The code below now assembles without any errors. However when used with the program and erase code listed in my first post I still cannot write anything to flash. It does appear to write the entire flash memory to $00 at each location from $F000 to $FFFF. Do not know why this is occuring. There must be some other registers that need to be programmed or I have missed something else.

We are running out of time so it looks like we will have to deadbug an 8 pin SOIC 1K EEPROM to our board just to save 2 bytes since we cannot get the on chip flash to work.

Thanks to everyone for their help.

Regards,

Paul



;************************************************************************************************
; SUBROUTINE:       SpSub                                                                         ;
;************************************************************************************************

SpSub       ldhx    <SpSubSize+4,sp           
            sta     0,x
            lda     SpSubSize+3,sp
            sta     FCMD
            lda     #mFSTAT_FCBEF
            sta     FSTAT
            nop
ChkDone:    lda     FSTAT
            lsla
            bpl     ChkDone                                     
SpSubEnd:   rts                     ;back into DoOnStack in flash
SpSubSize:  equ     (*-SpSub)           

;************************************************************************************************
; SUBROUTINE:   DoOnStack                                                                         ;
; ON ENTRY:     H:X - points at the flash byte to be programmed                                 ;
;               A holds the data for the location to be programmed                              ;
; ON RETURN:    H:X unchanged a A = FSTAT shifted left by 2 bits                                ;
;               Z=1 if OK, Z=0 if protect violation or access error                             ;
;               Uses 32 bytes of stack space + 2 bytes for BSR/JSR used to call it              ;
; USES:         DoOnStack which uses SpSub                                                      ;
;************************************************************************************************

DoOnStack:  pshx        
            pshh                    ;save pointer to flash
            psha                    ;save command to stack
            ldhx    #SpSubEnd       ;point at last byte to move to stack
SpMoveLoop: lda     ,x              ;read from flash
            psha                    ;move onto stack
            aix     #-1             ;next byte to move
            cphx    #SpSub-1        ;past end?
            bne     SpMoveLoop      ;loop until the whole subroutine is on stack
            tsx                     ;point to subroutine on stack
            tpa                     ;move CCR to A for testing
            and     #$08            ;check the I mask
            bne     I_set           ;skip if I already set
            sei                     ;block interupts while flash busy
            lda     SpSubSize+6,sp  ;preload data for command
            jsr     ,x              ;execute the subroutine on the stack
            cli                     ;OK to cleat the I mask now
            bra     I_cont          ;continue to stack de-allocation
I_set:      lda     SpSubSize+6,sp  ;preload data for command
            jsr     ,x              ;execute the subroutine on the stack
I_cont:     ais     #SpSubSize+3    ;de-allocate subroutine body _ H:X + command
                                    ;H:X flash pointer OK from SpSub
            lsla                    ;A=00 & Z=1 unless PVIOL or ACCERR
            rts                     ;to flash where DoOnStack was called

0 Kudos
1,387 Views
peg
Senior Contributor IV
Hi Paul,
 
The code you have shown in the last post is EXACTLY as AN2140/D. This works!
Show me (us) your flash clock initialisation and busclock init and some code fragment from where you call the flash write and I will try this out for you on a QG8.
Also ext clock/xtal details if this is what you have got.
 
0 Kudos
1,387 Views
peg
Senior Contributor IV
Hi Paul,
I hope you haven't started to glue those poor bugs down on their backs yet as I have discovered your problem!
 
You for got those pesky little #'s in front of the address you load in to HX before going to flasherase/flashprog then doonstack.
You were loading $FFFF into HX all the time, the erase then trashes the vectors and sets security.
 
I have built a working programme mostly from your posts in this thread. It writes "Peg" to $FB00 after erasing the page there.
 
I might clean it up a bit later, but am posting now to save your glue.
 
[edit]
woops forgot the attachment!


Message Edited by peg on 2007-11-17 09:59 AM
0 Kudos
1,388 Views
peg
Senior Contributor IV
Hi all,
 
OK, I tidied it up a bit and made it test the written string to see if it actually worked.
It is assembled with P&E's assembler so I have included the s19 and the LST files as well.
 
0 Kudos
1,387 Views
lu4eg
Contributor I

Using Code Warrior 6.1, I tried but stops when LDA $FB00 saying: "Attempt to use invalid or uninitialized memory" (is "uu" in the Memory map!), what am I doing wrong?

Project fok.zip is attached.

Thanks a lot.

Dany.

0 Kudos
1,387 Views
bigmac
Specialist III

Hello Dany, and welcome to the forum.

 

I assume that you are attempting to use full chip simulation for your tests.  The programming of flash memory is not simulated, so you will need to use the actual hardware to test this.

 

Regards,

Mac

 

0 Kudos
1,387 Views
lu4eg
Contributor I

OK Mac, I used hardware and it worked perfectly. I did not know Code Warrior Simulator can't show flash programming ...

 

I used to work with Win IDE (for HC08 family) and it does it!

 

Thanks a lot for your valuable help.

 

Dany

0 Kudos
1,387 Views
paul51
Contributor I
Hi peg,

Those poor bugs may be spared now. I knew it was probably something like this I overlooked. Staring at the same code for too long. Will try this over the weekend and let you know how the code works out. Cannot thank you enough for your help.

Regards,

Paul
0 Kudos
1,387 Views
paul51
Contributor I
Hi PEG,

I meant to say the two bytes stored at $FB00 and $FB01. Must have missed the link you referenced. Will try this tonight and let you know the results.

Paul
0 Kudos
1,387 Views
bigmac
Specialist III
Hello Paul,
 
You should be able to eliminate the assembly warning by re-positioning the SpSub sub-routine prior to the DoOnStack sub-routine.  This would mean that the value of the equate SpSubSize is already defined by the time it is used to calculate the immediate value at the label Icont.
 
Peg suggested to surround an expression with curly braces.  If you are using CW assembler, use parenthesis instead.  The curly braces pertain to the P&E assembler.
 
Since the value read from an unprogrammed flash location should be $FF, if you are reading values of $00, this would indicate that the word at location $FB00 has been previously programmed at some point.  You could try running just the erase routine, and see if you then get the values $FF.
 
Incidently, if you are re-programming soon after reset, the default TPMMOD value will be $0000.  Perhaps this accounts for the values you appear to be getting.
 
Regards,
Mac
 


Message Edited by bigmac on 2007-11-15 11:38 AM
0 Kudos
1,387 Views
paul51
Contributor I
Hi bigmac,

Will try the re-positioning of the SpSub subroutine and the addition of paranthesis as we are using CW.

The values that are programmed at $FB00 and $FB01 have been initialized in our main loop. So both bytes of TPMMOD have non zero values in them prior to the use of the flash programming routine.  Will try running just the erase routine and see what happens.

Thanks,

Paul
0 Kudos