AnsweredAssumed Answered

Programming QG4 flash problem

Question asked by Paul Savage on Nov 14, 2007
Latest reply on Dec 9, 2010 by Dany Piergiacomi
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)          

Outcomes