Hi, I am currently porting my bootloader to the MC9S08D60.
I've been using this bootloader on 9S08AW60, 9S08AC60, 9S08AC96.
So I wasn't expecting what happend....
I have changed the page size from 512 to 768 bytes (datasheet), I also have noticed that the erased page is not a multiple of 768 (experiment), and that burst programming works only for 32 consecutive bytes, starting at a multiple of 32.
Here is a list of related topics I found :
S08 Flash question programming, strange results
https://community.freescale.com/message/33624#33624
Here is what happends :
After blanking my page, I start programming is, say 32 bytes per 32.
During the first 256 bytes, all bytes are written.
From 256 to 511, I can flash the first byte, and get an access error when attempting to write the next byte.
From 512 to 767, all bytes are written again
Thats the same is I proceed 256 per 256 bytes, or 8 per 8 bytes.
You will find attached two S19, before and after flashing. The files should be the same (I suggest the use kdiff3 or winmerge to ease comparison).
The area to be programmed is 0x3100..0x33FF, here is a snapshot of the borders :
S123 31E0 EB37EAFCEABFEA81EA41E9FFE9BCE977E931E8E8E89DE84FE7FEE7ABE754E6FA5F
S123 3200 E6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE3
S123 32E0 04FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5
S123 3300 049B049A0499049904980498049704970496049504950494049404930493049204
Here is the assembly routine that I use. I think I found it some where around this forum :
ProgSub: lda #(mFSTAT_FPVIOL|mFSTAT_FACCERR) ;clear FSTAT[PVIOL,ACCERR] ldhx #FCNFG ;load address of FCNFG sta 2,x ;double-write FSTAT ensures FSTAT[PVIOL,ACCERR] are cleared sta 2,x clr ,x ;write $00 to FCNFG to clear FCNFG[KEYACC] clra ;clear return code psha ;save to stack, used as return code and operation resultcheckSize: lda #1 ;set the stop function flag ldhx LEN ;check if size is zero beq waitFCCF ;if zero, wait FCCF set and terminate function aix #-1 ;sub size by 1 sthx LEN pula ;remove previous operation result and ignore AwaitFCBEF: lda FSTAT ;check if FSTAT[FCBEF] is high bpl waitFCBEF ;new command can only be start if FSTAT[FCBEF] is high ldhx ADRR lda 0,x aix #1 sthx ADRR ldhx ADRS ;get flash address sta 0,x ;write to flash; latch addr and data aix #1 sthx ADRS lda #mBurstProg ;load A with burst program command sta FCMD ;store burst program command to FCMD lda #mFSTAT_FCBEF ;launch command sta FSTAT ;4 bus cycle nop nop nop nop lda ,x ;check error flags in FSTAT and #(mFSTAT_FPVIOL|mFSTAT_FACCERR) ;reserve FSTAT[PVIOL,ACCERR] psha ;return code and operation result in A; save to stack beq checkPAGEEND ;do the next program sequence if success sta ,x ;clear FSTAT[PVIOL,ACCERR] bra waitFCCF ;non zero in A will stop function after FSTAT[FCCF] setcheckPAGEEND: ;need to wait FSTAT[FCCF] set at page boundary tsx lda 9,x ;high byte of dest asra ;lowest bit saved in carry bit bcs checkSize ;not a page start if carry bit is set lda 10,x ;low byte of dest bne checkSize ;not a page start if low byte is non zero, ;Zero in A. function continue after FSTAT[FCCF] setwaitFCCF: psha ;save stop flag ldx FSTAT ;check if FSTAT[FCCF] is high aslx ;commands are finished if FSTAT[FCCF] is high pula ;retrieve stop flag bpl waitFCCF ;wait until FSTAT[FCCF] is high tsta ;check if stop function beq checkSize pula ;retrieve return code from stack ldhx STACK txs rtsProgSubEnd:ProgSubSize: equ (*-ProgSub)
I tried to add some more nop after starting programming, without succes.
Can Anyone help me to fix the problem ?
Regards,
Pierre
已解决! 转到解答。
I didn't notice on p65 that if the base block address is not a multiple of 768, the protected area size is always.
You were right : the line you pointed on my code
lda ,x
is incorrect, since HX points to ADRS ...
I fixed my code by replacing this line by
lda FSTAT
The funny, and also worrying, fact is that this bug is on a bootloader that I use on all my freescale projects. So far, it has gone through all tests !
Thanks for your help.
Pierre
Kef,
The 'DZ60, and related devices are different from most other HCS08 devices in that the flash sector size has been increased to 768 bytes.
Pierre,
I assume that you are actually using the "doonstack' method, with the data pre-loaded to the stack, followed by the ProgSub code. But the stack usage for the data is not immediately evident from your code snippet. Have you checked that the data being read is correct, and there is not a data indexing problem?
Keep in mind that, with the 'DZ60 there is an alternative approach, that would provide simpler code. This is to place the ProgSub code permanently into EEPROM, and run the code from there. EEPROM is a separate array from flash for this device, so is accessible during flash programming.
Also consider that, if you are erasing the non-volatile data sector immediately prior to the programming process, there is usually little justification to use burst programming mode, as the sector erase period will exceed the programming period for the data. Byte-by-byte programming will occupy a marginally longer period, but should give somewhat simpler and much more straightforward code. Burst programming is really only of value for time critical applications, where the sector has already been erased.
Some general comments about your code:
I would see little point in writing to FCNFG register, as you are not dealing with the backdoor key. Indexing to this register has apparently caused some indexing errors later in the code. I assume that the original code on which you based your code actually indexed to FSTAT. I do not know why you would need to double write to FSTAT.
Regards,
Mac
bigmac :
You are right : I use the "doonstack" method. But as far as I can remember, I didn't change a byte from the code I got, except the code section and a macro name. I join the full source file to this post.
I have checked that the pointers are correct, their values are ok, and so the pointed data.
I am about to place the code in the eeprom to ease debuging, but think in the end I will still have to use the flash code from ram since I want to keep the eeprom dedicated to the application.
What you say about burst/non burst programming is intersting, I didn't consider that point : I just wanted the fastest possible code !
kef also pointed some issues about fstat, I'll check that, and compare my code to the one provided in the bootloader application sample.
The double write to fstat was already there.
Also, is it realy necessary to program 32 bytes per 32 bytes ? I tested with 256 bytes, and it was ok, for the 256 first and last bytes only.
Thanks for your help so far
Pierre
Page size is not 768 bytes? You must be wrong.
I see at least one problem in your code:
ldhx ADRS ;get flash address sta 0,x ;write to flash; latch addr and data aix #1 sthx ADRS lda #mBurstProg ;load A with burst program command sta FCMD ;store burst program command to FCMD lda #mFSTAT_FCBEF ;launch command sta FSTAT ;4 bus cycle nop nop nop nop===> HX doesn't point to FSTAT! lda ,x ;check error flags in FSTAT and #(mFSTAT_FPVIOL|mFSTAT_FACCERR) ;reserve FSTAT[PVIOL,ACCERR]
Yes, I use a 768 byte page, but I made a mistake in my sentence.
What I wanted to say is :
"The starting adress of the erased page is not at a multiple of 768 bytes"
Considering these points, it comes to something logic :
- The flash starting adress is 0x1900, which is not a multiple of 768 bytes.
- In my example, when I set the erase adress to 0x3300 (which is a multiple of 768), the bytes effectively erased are from 0x3100 (which is a not multiple of 768) to 0x33FF.
I think this is due to the flash protection mechanism which still work on multiples of 512 bytes, if you look at the first protected bytes in the datasheet (cf datasheet table 4.14 page 65 ).
Thanks for your suggestion about HX not pointing to fstat, I must have a look !
Pierre
Pierre,
Yes, 64k address space is not divisible by 0x300 (768). Since vectors are in top most addresses and flash has to be there, 0x300 bytes sectors are aligned not to the bottom of address space (address 0), but to the top of address space. The top most sector(page) is 0xFD00-FFFF, then 0xFA00-0xFCFF etc. In other words each sector starts at address
(0x10000 % 0x300) + (N * 0x300) = 0x100, 0x400, 0x700 etc
Flash protection scheme works not on multiple of 512 bytes, but on multiple of two 768 sectors. See datasheet page 65. Flash Block Protection table. You can protect 0 kB, 1.5kB( 2x768), 3kB (4*768), 4.5kB etc.
(You may wonder why such odd sector size. Look at S08DE datasheet. With flash error correction (ECC) enabled, you have 512 bytes sectors, with ECC off you have 768 bytes sectors. Extra 256 bytes in the sector are used for errors correction. I guess DZ60 uses same flash arrays, just that the ECC feature is disabled.)
I didn't notice on p65 that if the base block address is not a multiple of 768, the protected area size is always.
You were right : the line you pointed on my code
lda ,x
is incorrect, since HX points to ADRS ...
I fixed my code by replacing this line by
lda FSTAT
The funny, and also worrying, fact is that this bug is on a bootloader that I use on all my freescale projects. So far, it has gone through all tests !
Thanks for your help.
Pierre
Hello Pierre,
For comparison purposes, I have attached some code that uses an alternative method for byte-by-byte programming. This code uses a fixed location in RAM for the RAM resident code, rather than using the stack. This code size requrement is less than 20 bytes, is common to erase and programming routines, and could alternatively be programmed to EEPROM, for the 'DZ60.
Regards,
Mac