HCS08单片机的在应用编程IAP
0赞HCS08单片机支持在应用编程IAP,可以把需要断电保存的内容存到Flash里,有人称之为Flash模拟EEPROM。实现该功能要求2点:
1、Flash时钟要在150~200kHz。
2、被挖除的Flash与操作Flash的程序不能放在同一扇区。
一种办法是把操作代码放到栈里面运行,官方为该方法提供了3个文件,把它们包含进工程中就可以实现应用编程IAP了,程序中只需初始化Flash时钟到150kHz~200kHz,之后调用“FlashErase”、“FlashProg”、“FlashProgBurst”函数即可。
下面给出官方的doonstack.asm的代码:
;******************************************************************************
;
; Freescale Semiconductor Inc.
; (c) Copyright 2004-2006 Freescale Semiconductor, Inc.
; (c) Copyright 2001-2004 Motorola, Inc.
; ALL RIGHTS RESERVED.
;
;**************************************************************************//*!
;
; $File Name: doonstack.asm$
;
; $Author: r30323$
;
; $Version: 1.0.3.0$
;
; $Date: May-27-2009$
;
; Add instructions to clear watchdog in DoOnStack and SpSub
; $Date: May-8-2011$
;
; $Version: new
; Put the code in EE_CODE section
; $Date: Sep-13-2011$
;
; @brief DoOnStack.asm (see HCS08RM.pdf for details)
;
;******************************************************************************
; export symbols
XDEF FlashErase
XDEF FlashProg
XDEF FlashProgBurst
Include 'doonstack.inc'
; ORG $D000
; code section
EE_CODE: SECTION
;**************************************************************
; this assembly routine is called the C/C++ application
DoOnStack:
pshx
pshh ;save pointer to flash
psha ;save command on stack
ldhx #SpSubEnd ;point at last byte to move to stack;
SpMoveLoop:
sta SRS ;clear watchdog
lda ,x ;read from flash
psha ;move onto stack
aix #-1 ;next byte to move
cphx #SpSub-1 ;past end?
bne SpMoveLoop ;loop till whole sub on stack
tsx ;point to sub 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 interrupts while FLASH busy
lda SpSubSize+6,sp ;preload data for command
jsr ,x ;execute the sub on the stack
cli ;ok to clear 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 sub on the stack
I_cont:
ais #SpSubSize+3 ;deallocate sub 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
;**************************************************************
SpSub:
ldhx LOW(SpSubSize+4),sp ;get flash address from stack
sta 0,x ;write to flash; latch addr and data
lda SpSubSize+3,sp ;get flash command
sta FCMD ;write the flash command
lda #mFCBEF ;mask to initiate command
sta FSTAT ;[pwpp] register command
nop ;[p] want min 4~ from w cycle to r
ChkDone:
sta SRS ;clear watchdog
lda FSTAT ;[prpp] so FCCF is valid
lsla ;FCCF now in MSB
bpl ChkDone ;loop if FCCF = 0
SpSubEnd:
rts ;back into DoOnStack in flash
SpSubSize: equ (*-SpSub)
;**************************************************************
FlashErase:
; see Errata: SE133-FLASH : Unexpected Flash Block Protection Errors
STA ,X ;latch the unprotected address from H:X
NOP ;brief delay to allow the command state machine to start
STA ,X ;intentionally cause an access error to abort this command
psha ;adjust sp for DoOnStack entry
lda #(mFPVIOL+mFACCERR) ;mask
sta FSTAT ;abort any command and clear errors
lda #mPageErase ;mask pattern for page erase command
bsr DoOnStack ;finish command from stack-based sub
ais #1 ;deallocate data location from stack
rts
;**************************************************************
FlashProg:
; see Errata: SE133-FLASH : Unexpected Flash Block Protection Errors
STA ,X ;latch the unprotected address from H:X
NOP ;brief delay to allow the command state machine to start
STA ,X ;intentionally cause an access error to abort this command
psha ;temporarily save entry data
lda #(mFPVIOL+mFACCERR) ;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
;**************************************************************
SpSubBurst:
lda FSTAT ;check FCBEF
and #mFCBEF ;mask it
beq SpSubBurst ;loop if not empty
ldhx LOW(SpSubSizeBurst+4),sp ;get source address from stack
lda 0,x ;load source data byte
aix #1 ;increment source address
sthx (SpSubSizeBurst+4),sp ;save new source address to stack
ldhx LOW(SpSubSizeBurst+8),sp ;get destionation address from stack
sta 0,x ;write to flash Latch
aix #1 ;increment destination address
sthx (SpSubSizeBurst+8),sp ;save new destionation address to stack
lda #mBurstProg ;load Burst program command
sta FCMD ;write the flash command
lda #mFCBEF ;mask to initiate command
sta FSTAT ;[pwpp] register command
nop ;[p] want min 4~ from w cycle to r .
lda FSTAT ;load FSTAT to check ERRORs
and #$30 ;check only FPVIOL and FACCERR
beq FlashWriteOk
lda #255 ;set up error flag
rts ;back into FlashProgBurst in flash
FlashWriteOk:
dbnz SpSubSizeBurst+3,sp,SpSubBurst
ChkDoneBurst:
lda FSTAT ;[prpp] so FCCF is valid
lsla ;FCCF now in MSB
bpl ChkDoneBurst ;loop if FCCF = 0
clra
SpSubEndBurst:
rts ;back into DoOnStack in flash
SpSubSizeBurst: equ (*-SpSubBurst)
;**************************************************************
FlashProgBurst:
pshx ;save source address - low byte
pshh ;save source address - high byte
psha ;save length of data
lda #(mFPVIOL+mFACCERR) ;mask
sta FSTAT ;abort any command and clear errors
ldhx #SpSubEndBurst ;point at last byte to move to stack;
SpMoveLoopBurst:
lda ,x ;read from flash
psha ;move onto stack
aix #-1 ;next byte to move
cphx #SpSubBurst-1 ;past end?
bne SpMoveLoopBurst ;loop till whole sub on stack
tsx ;point to sub on stack
tpa ;move CCR to A for testing
and #$08 ;check the I mask
bne I_setBurst ;skip if I already set
sei ;block interrupts while FLASH busy
jsr ,x ;execute the sub on the stack
cli ;ok to clear I mask now
bra I_contBurst ;continue to stack de-allocation
I_setBurst:
jsr ,x ;execute the sub on the stack
I_contBurst:
ais #SpSubSizeBurst+3 ;deallocate sub body + H:X + command ;H:X flash pointer OK from SpSub
rts ;to flash where DoOnStack was called
;**************************************************************
上述代码是汇编写的,其提供了C语言调用接口,详见doonstack.h:
/******************************************************************************
*
* Freescale Semiconductor Inc.
* (c) Copyright 2004-2006 Freescale Semiconductor, Inc.
* (c) Copyright 2001-2004 Motorola, Inc.
* ALL RIGHTS RESERVED.
*
***************************************************************************//*!
*
* @file doonstack.h
*
* @author B01119
*
* @version 1.0.3.0
*
* @date May-27-2009
*
* @brief C header file for DoOnStack.asm
*
*******************************************************************************/
#ifndef _DOONSTACK_H
#define _DOONSTACK_H
#ifdef __cplusplus
extern "C" { /* our assembly functions have C calling convention */
#endif
// DoOnStack API
void FlashErase(const unsigned char * flash_destination);
void FlashProg(const unsigned char * flash_destination, unsigned char data);
unsigned char FlashProgBurst(const unsigned char * flash_destination, unsigned char * ram_source, unsigned char length);
// this definitions has been on this place only for backward compatibility
#define CopyRam2Flash (void)FlashProgBurst
#define CopyRam2FlashBurst CopyRam2Flash
#ifdef __cplusplus
}
#endif
#endif /* _DOONSTACK_H */