Jim Donelson

Flashing Made Simple Min Ram Version - MC9S08QG4

Discussion created by Jim Donelson on Feb 25, 2008
Latest reply on Feb 25, 2008 by bigmac
This subject has pretty much been beat to death, but I think this code has some appeal to it, and has some ideas that make it nice for a lib.

Handles interrupts in the only way I see as acceptable for a lib. The user should not have to worry about this, but should be aware of the lock out. This code leaves the IM flag the way it found it.

Uses a minimum of ram - 35 bytes. I use this code on QG4 project where I only have 256 byte of RAM, so this is a big consideration.

No changes required to the PRM file and no special pragmas used, and no worries about other ram variables overlaying it.

And it is darned simple.

If you need to, you can reuse the ram space and copy it back later. Once you have committed to a stack size you are stuck with it, and I really don't like stressing the stack on little ones like this.  Plus, in a library this could be a hidden nasty surprise. The map file will reflect the usage with this method.

This was adapted from HCS08RUG.

Does not use burst mode to program. According to the QG8/4 spec sheet if you set the clock to 200Khz, it takes 45 us in single mode and 20us in burst mode. While this is a 2x difference, if you only need a few bytes of config data it is no big deal. Thats 23ms for a 512 byte sector - interestingly enough just about as long as it take the erase a sector. If this is an issue, it  would be easy enough to make a tweaked burst version, but you won't get away with using the same code for erasing and writing as easily.

I normally don't use asm language, but this is a just cause. In theory, this should work with all HCS08, and I will try other chips. I have done a fair amount of testing, and it seems fine.

Debugging Advice:
Hiwave will not read back flash unless you pretend to write in it, unless you set the region to R/W and check "refresh memory when halting" you should also check "no memory access while running". This is in the "Debugging Memory Map" dialog. I had not troubles at all stepping thru the code and watching memory change - I did not step through the actual command execution code.


#define Page_Erase   PGM[2]=0x40; temp = ((unsigned char(*)(unsigned int, unsigned char))(PGM))
#define Program_Byte PGM[2]=0x20; temp = ((unsigned char(*)(unsigned int, unsigned char))(PGM))

//Array of opcode instructions of the Erase/Program function in the HCS08 family// A = data, X = Address.

volatile unsigned char PGM[35]  = {  0xF7,              // STA ,X   Save the data byte into the address. 0xA6,0x00,         //  LDA cmd (Filled in before calling)0xC7,0x18,0x26,    //  STA   _FCMD0x45,0x18,0x25,    //  LDHX  @_FSTAT0xF6,              // LDA   ,X0xAA,0x80,         // ORA   #$800xF7,              // STA   ,X0x9D,0x9D,0x9D,0x9D, // NOP, NOP,NOP,NOP0xC6,0x18,0x25,     // LDA   _FSTAT0xA5,0x30,          // BIT   #$300x27,0x03,          // BEQ   *+5 (Label1)0xa6,0xff,          // RTS
// Label1:
0xC6,0x18,0x25,     // LDA   _FSTAT
0xa5,0x40,          // BIT #$40
0x27,0xF9,          // BEQ *-5 (Label)
0x81,               // RTS
byte FlashErasePage(word page)
   volatile unsigned char temp ;
   byte im;
   asm TPA;    // get the flags
   asm STA im  // save them
   asm SEI     // clear the im bit

   if (FSTAT&0x30){                     //Check to see if FACCERR or FPVIOL is set
        FSTAT = FSTAT | 0x30;            //write a 1 to clear

   temp = Page_Erase(page,0);
   asm LDA im   // get the flags back
   asm TAP      // restore the im bit.
   return temp;

byte FlashProgramByte(word address, byte data)
  volatile unsigned char temp;
   byte im;
   asm TPA;
   asm STA im
   asm SEI
    if (FSTAT&0x30){                     //Check to see if FACCERR or FPVIOL is set
        FSTAT = FSTAT | 0x30;            //write a 1 to  clear

   temp = Program_Byte(address, data);
   asm LDA im
   asm TAP
  return temp;


Message Edited by JimDon on 2008-02-25 01:24 AM


Added p/n to subject.

Message Edited by NLFSJ on 2008-02-25 07:29 AM