volatile unsigned char PGM[10] = { 0xc7,0x18,0x25, // sta FSTAT 0x44, // lsra - delay and convert to FCCF bit0xc5,0x18,0x25, // Bit fstat0x27,0xfb, // BEQ *-30x81 // RTS}; byte FlashErasePage(word page) { asm { TPA ; Get status to A PSHA ; Save current status SEI ; Disable interrupts LDA #0x30 STA FSTAT ; Clear FACCERR & FPVIOL flags LDX page STA ,X ; Save the data LDA #$40 ; Erase command STA FCMD LDA #FSTAT_FCBEF_MASK JSR PGM PULA ; Restore previous status TAP } if (FSTAT&0x30){ //check to see if FACCERR or FVIOL are set return 0xFF; //if so, error. } return 0; }byte FlashProgramByte(word address, byte data) { asm{ TPA PSHA ; Save current status SEI ; Disable interrupts LDA #0x30 STA FSTAT ; Clear FACCERR & FPVIOL flags LDX address LDA data STA ,X ; Save the data LDA #$20 ; Burn command STA FCMD LDA #FSTAT_FCBEF_MASK JSR PGM PULA ; Restore previous status TAP } if (FSTAT&0x30){ //check to see if FACCERR or FVIOL are set return 0xFF; //if so, error. } return 0; }
volatile unsigned char PGM[6] = { 0xf7, // sta ,X FSTAT 0x44, // lsra - delay and convert to FCCF bit 0xf5, // Bit ,X FSTAT 0x27,0xfd, // BEQ *-1 0x81 // RTS }; byte FlashErasePage(word page) { asm { TPA ; Get status to A PSHA ; Save current status SEI ; Disable interrupts LDA #0x30 STA FSTAT ; Clear FACCERR & FPVIOL flags LDHX page STA ,X ; Save the data LDA #$40 ; Erase command STA FCMD LDA #FSTAT_FCBEF_MASK LDHX @FSTAT JSR PGM PULA ; Restore previous status TAP } return (FSTAT & 0x30); } byte FlashProgramByte(word address, byte data) { asm{ TPA PSHA ; Save current status SEI ; Disable interrupts LDA #0x30 STA FSTAT ; Clear FACCERR & FPVIOL flags LDHX address LDA data STA ,X ; Save the data LDA #$20 ; Burn command STA FCMD LDA #FSTAT_FCBEF_MASK LDHX @FSTAT JSR PGM PULA ; Restore previous status TAP } return (FSTAT & 0x30); }
I was just looking for a version with COP reset and was unable to find. Here is the updated RAM function that will work on all processors, and, now with COP reset. My GB32 was resetting cop even on slowest setting so it was required.
//------------------------------------------------------------------------------------------------------------------------
//ASM code to write to flash from RAM
#pragma DATA_SEG MY_ZEROPAGE //003
#define Use_COP //Use COP reset, you may need to modify the address of SRS for the selected processor
#ifdef Use_COP
volatile unsigned char PGM[10] = {
#else
volatile unsigned char PGM[7] = {
#endif
0xf7, // sta ,X FSTAT
0x44, // lsra - delay and convert to FCCF bit
0xf5, // Bit ,X FSTAT
#ifdef Use_COP
0xC7,0x18,0x00, // sta SRS (Clear cop), SRS is at 1800 in this processor
#endif
0xf5, // Bit ,X FSTAT //Added dummy read to allow all masked version to function correctly
#ifndef Use_COP
0x27,0xfd, // BEQ *-1
#else
0x27,0xfa, // BEQ *-4
#endif
0x81 // RTS
};
#pragma DATA_SEG DEFAULT //003
//------------------------------------------------------------------------------------------------------------------------
Congratulations - everyone had missed this up until now, but it makes sense that access to flash would remain up until the FCBEF flag is written, and the command commences. Probably a case of "not seeing the wood for the trees".
JimDon wrote:
It turns out that in non-burst mode, the only code that must be in ram is writing the start command bit and the wait loop, which cut another 8 bytes out of ram.
If you notice in the asm code, that does not go in ram, I seeming loaded X with 'page' when I did not need to. This is not an oversight, as it is bad design to "know" where the compiler puts things, as other compilers may or may not pass things in this way, or this compiler may change.
bigmac wrote:
Congratulations - everyone had missed this up until now, but it makes sense that access to flash would remain up until the FCBEF flag is written, and the command commences. Probably a case of "not seeing the wood for the trees".
;*******************************************************************************
; Purpose: RAM routine to do the job we can't do from Flash
; Input : A = value to program
; Output : None
; Note(s): This routine is modified in RAM by its loader at @2,3 and @5
; : Stack needed: 20 bytes + 2 for JSR/BSR
?RAM_Execute sta EEPROM ;Step 1 - Latch data/address
;EEPROM (@2,@3) replaced
lda #mByteProg ;mByteProg (@5) replaced
sta FCMD ;Step 2 - Write command to FCMD
lda #FCBEF_
sta FSTAT ;Step 3 - Write FCBEF_ in FSTAT
lsra ;min delay before checking FSTAT
;(FCBEF -> FCCF for later BIT)
?RAM_Execute.Loop bit FSTAT ;Step 4 - Wait for completion
beq ?RAM_Execute.Loop ;check FCCF_ for completion
rts
;after exit, check FSTAT for FPVIOL and FACCERR
?RAM_Needed equ *-?RAM_Execute
;*******************************************************************************
; Purpose: RAM routine to do the job we can't do from Flash
; Input : A = FCBEF bit mask
; Output : None
; Note(s): This routine is modified in RAM by its loader at @2,3 and @5
; : Stack needed: 10 bytes + 2 for JSR/BSR
?RAM_Execute sta FSTAT ;Step 3 - Write FCBEF_ in FSTAT
lsra ;min delay before checking FSTAT
;(FCBEF -> FCCF for later BIT)
?RAM_Execute.Loop bit FSTAT ;Step 4 - Wait for completion
beq ?RAM_Execute.Loop ;check FCCF_ for completion
rts
;after exit, check FSTAT for FPVIOL and FACCERR
?RAM_Needed equ *-?RAM_Execute
In all cases, when there was success, I got the correct data programmed. When there was failure, no change in the flash contents.
JimDon wrote:
Let me ask you this, was the flash correctly programmed?
JimDon wrote:
I wonder what mask set tony was using?