S08 Flash question programming, strange results

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

S08 Flash question programming, strange results

7,405 Views
CarlFST60L_3rd
Contributor I
Hi,

I have had a read of programming flash for the S08 family (previously posted full working C code for 908 on this forum) which is in production and working fine.

The S08 data sheet seems to be all over the place with information scattered through out (unlike 908 which was in order very clear).

This code is run out of ram, the code below works exactly as the code reads ( have tripple checked stepping through it), so I guess the concept of what I am doing must be the problem?

This code is to show the core concept.
Code:
//--- Somewhere in main//20Mhz BusICGC1 = 0x78;ICGC2 = 0x30;while(!ICGS1_LOCK);   //Wait for lock before allowing software to startupwhile(FSTAT_FACCERR) FSTAT_FACCERR = 1;             //Make sure error is cleared before setting up the divider    if(!FCDIV_DIVLD) FCDIV = 0b01001100;                //set fFCLK = about 200kHz unless already setupFPROT_FPOPEN = 1;                                   //No flash protectionFPROT_FPS = 1;                                      //No flash protection//Another Function moves this code to ram, and runs from there   
if(FSTAT_FACCERR) FSTAT_FACCERR = 1;  //Step 1 - If there is an access error, clear it
while(!FSTAT_FCBEF);                  //Step 2 - Wait until ready to accept the command
ADDRESS_0xF300 = 0xFF;        // Step 3 - Write to page for erase
FCMD = mPageErase;                    // Step 4 - Setup the erase command
FSTAT_FCBEF = 1;                      // Step 5 - Carry out command
if(FSTAT_FPVIOL || FSTAT_FACCERR) FSTAT_FACCERR = 1;  //Step 6 - If there is an access error, clear it, work out error handling later
while(FSTAT_FCCF);                    // Step 7 - Wait for the command complete flag

 
Now, what is REALLY strange is, this code actually works IF and only IF i do exactly this
Fresh burn the chip
run to cursor at step1
then run to cursor at the line after step 8

If i move the memory window to watch address F300, it dosnt work, if i leave the memory window alone, it works.

If i just hit run, it hangs at step 7 and causes Watchdog reset

This software has also been causig me to have to unplug the USB on my Cyclone pro and refresh for the first time ever (not sure if its related, but its only since i have been playing with this code).

Once i get this working i will post up this most basic C code to run either 908 or S08 processors

Thanks,
Labels (1)
0 Kudos
15 Replies

1,877 Views
CarlFST60L_3rd
Contributor I

As promised here is some basic code to get flash running on either 908 and S08 family processors. The code is basic, not setup for final production version, just enough to give people a starting point! Hope this helps someone. Feel free to email updated etc to carl@edsengineering.com.au

WARNING: When using S08 with BDM connectect, you MUST close all three data windows or it will simply not work!

Dont forget its time critical, you need to have your clock / bus speed work out, for this S08 its:

Code:

//-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -//

4Mhz external xtal, internal bus F = 20Mhz

//FLL is used (in FEE mode) to multiply the external 4 MHz oscillator up to 40-MHz to achieve 20 MHz bus frequency.

void ConfigureClock(void)

{

     /*ICGC1 =Bit 7 HGO 0 Configures oscillator for low-power operationBit 6 RANGE 1 Configures oscillator for high-frequency range; FLL presc     ale factor is 1Bit 5 REFS 1 Requests an oscillatorBits 4:3 CLKS 11 FLL engaged, external reference clock modeBit 2 OSCSTEN 0 Disables      the oscillator in stop modesBit 1 LOCD 0 Loss-of-clock detection enabledBit 0 0 Unimplemented or reserved, always reads zero*/

     ICGC1 = 0x78;

     /*ICGC2 =Bit 7 LOLRE 0 Generates an interrupt request on loss of lockBit 6:4 MFD 011 Sets the MFD multiplication factor to 10Bit 3 LOCR     E 0 Generates an interrupt request on loss of clockBit 2:0 RFD 000 Sets the RFD division factor to ÷1*/

     ICGC2 = 0x30;

     while(!ICGS1_LOCK);  //Wait for lock before allowing software to startup

}

//-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -


For GP32 it is running off a 32Khz XTAL with PLL setup as

Code:

//------------------------------------------------------------------------------------------------

void SetupPLL(void)

     PCTL_PLLON = 0;   //Turn off PLL//PLL to run the internal clock at 4.9152MHz

     PCTL_VPR1 = 1;

     PMSH = 0x02; 

     PMSL = 0x58; 

     PMRS = 0x80;  

     PCTL_PLLON = 1;     //Turn on PLL 

     PCTL_BCS = 1;       //Base clock select

}

//------------------------------------------------------------------------------------------------

Code:

// flash.c

/* ###################################################################**    

Filename  : FlashRoutines.c**    

Processor : MC9S08**    

FileFormat: V1.0**    

DataSheet :**    

Compiler  : CodeWarrior compiler 5.7.0**    

Date/Time : January 30, 2008 : 8am**    

Abstract  : **         .****    

(c) Copyright EDS Engineering Pty Ltd 2007**    

http      : www.edsengineering.com.au**    

mail      : carl@edsengineering.com.au****     

Notes for implmenting this code:**      //This needs to be setup once on boot up

#ifdef _MC9S08  //If using S08, setup bus   

while(FSTAT_FACCERR)

     FSTAT_FACCERR = 1;             //Make sure error is cleared before setting up the divider

if(!FCDIV_DIVLD) FCDIV = initFCDIV; //set fFCLK = about 200kHz (if not already setup i.e. on warm boot)   

FPROT_FPOPEN = 1;  //No flash protection   

FPROT_FPS = 1;  //No flash protection 

#endif

**** ###################################################################*/

#include "derivative.h"

#include "FlashRoutines.h"  //Flash data table as required

//Need to add anything here to the entries section in the PRM file or you will not be able to use it

#pragma CONST_SEG

UserFlashDataconst far byte FB01 = 0xC1;

const far byte FB02 = 0xC4;

#pragma CONST_SEG DEFAULT

#ifdef _MC9S08  //Flash block protect register set 

const byte xFLBPR @ 0xFF7E = 0xFF;  // NOTHING IS PROTECTED! 

//xFLCR (Flash Control Register) This is not setup properly in the the GP32 header file for addressing far bytes 

byte xFLCR @ 0xFE08; //  

#define PGM   1 // Mask bits for FLCR 

#define ERASE 2 

#define MASS  4 

#define HVEN  8

#endif

/*************************************************************************//****

Example / Test code *****//*************************************************************************/

//TEST CODE FOR MAIN LOOP

//This main loop simply writes 0x01 to 0x40 into the address of UserFlashData (see PRM file)

//PLease note, you must have the PRM setup correctly for this code

/*

byte  RAMData[64] = {0}; //RAM Data that will be written to Flash

//TEST CODE

byte  FlashData[64] = {0}; //Area to write to (for testing only)

byte  *pRAMData = &RAMData[0];

byte  temp = 0x00;

char  *pFlashData = (byte *)Start_User_Flash_Data;  //Point to the segment

(ref to PRM)while(pRAMData != (RAMData+64)) *pRAMData++ = ++temp ;  //Fill RAMData with 0x01 to 0x40p

RAMData = &RAMData[0];

//Reset pointerDisableInterrupts;

//Must disable interupts while writing to flash

CopyInRAM();

//Move required routines to RAM for running (cannot write to flash while PC is in flash!)

EraseRoutine(pFlashData);

//Erase data before writing

WriteFlashRow(pRAMData, pFlashData); 

//write data to flash

EnableInterrupts;      

for(;;) PTC ^= 1;       //Stop here, just toggle the output

}

*//*************************************************************************

//**** Copy routines to RAM (must execute from RAM!)        *****

//*************************************************************************/

// This routine copies all the flash routines to ram as defined in// the PRM  file

// Add this to the last SEGMENTS entry in the .PRM file

// ROM_IMAGE = READ_ONLY 0xF000 TO 0xF2FF RELOCATE_TO 0x0200;

//Where 0x0200 is the area in RAM free

// Add this line to the last entry under PLACMENT

// ToCopyToRAM

INTO  ROM_IMAGE;

// For more information see TN228 from freescale, or search on "SEGMENTS"

// or "RELOCATE_TO" in the code warrior help files.

/*************************************************************************/

void CopyInRAM(void)

       char *srcPtr, *dstPtr;  int count;   

       srcPtr = (byte *)Start_Copy_In_RAM;   

       dstPtr = (byte *)&EraseRoutine; //Must be address of first routines

       for (count = 0; count < (int) Size_Copy_In_RAM; count++, dstPtr++, srcPtr++)

       {

                       *dstPtr = *srcPtr;     

       }

}

//WARNING: These function MUST be loaded into RAM before calling using

// CopyInRAM(); 

//Call prior to calling function in 'ToCopyToRAM'#pragma CODE_SEG ToCopyToRAM

/*************************************************************************/

/**** Erase a Block of FLASH Memory Subroutine        *****/

/*************************************************************************/

// This routine erases a block of FLASH // Make sure interupts are off, code is loaded into ram, simply point to any

// addres in the block you want to erase

// Initializations required:

// Pass Value:

// FlashRow = Any address in the block of flash to erase

// Values returned:

// none

//Note: S08 family is a 512 block!

/*************************************************************************/

void EraseRoutine (byte *FlashRow) 

//WARNING: This name is part of CopyInRAM, do not add code above this{

//-   -   - -   -   -   -   - -   -   -   -   - -   -   -   -   - -   -   -   -   - -   -   -   -

//Runs this code when running MC9S08 processors#ifdef _MC9S08  byte  tmpa; //Just used for chewing cycles 

if(FSTAT_FACCERR)

       FSTAT_FACCERR = 1;             //Step 1 - If there is an access error, clear it while(!FSTAT_FCBEF) //Step 2 - Wait until ready to accept the command

        __RESET_WATCHDOG();      //feed the dog     

*FlashRow = 0xFF; // Step 3 - Write to any FLASH

FCMD = mPageErase; // Step 4 - Setup the erase command     

FSTAT_FCBEF = 1; // Step 5 - Carry out command

__asm ror tmpa;        // Step 6 - Chew some cycles as required by the data  sheet (atleast four cycles, this will do 5)   

if(FSTAT_FPVIOL || FSTAT_FACCERR)

       FSTAT_FACCERR = 1;            //Step 7 - If there is an access error, clear it, work out error handling later     

while(!FSTAT_FCCF) // Step 8 - Wait for the command complete flag    __RESET_WATCHDOG(); //feed the dog         

#endif 

//-   -   - -   -   -   -   - -   -   -   -   - -   -   -   -   -   - -   -   -   -   - -   -   -

//Runs this code when running HC908 processors

#ifdef _HC908  xFLCR |= ERASE; // Step 1 - Set erase and clear MASS erase 

       xFLCR &= (~MASS);              // MASS and xFLCR is actually xFLCR GP32 header is WRONG

    __asm lda xFLBPR;                    // Step 2 - read from Flash block protect register *FlashRow = 0xFF; // Step 3 - Write to any FLASH  

       Delay(t10uS);  // Step 4 - Delay 10uS 

       xFLCR |= HVEN; // Step 5 - Set the HVEN bit 

       Delay(t1mS);  // Step 6 - Wait 1mS 

       xFLCR &= (~ERASE); // Step 7 - Clear the ERASE bit 

       Delay(t5uS);  // Step 8 - Wait min 5uS 

       xFLCR &= (~HVEN); // Step 9 - Clear the HVEN bit

#endif

//-   -   - -   -   -   -   - -   -   -   -   - -   -   -   -   -   - -   -   -   -   - -   -   -}

/*************************************************************************

//**** Flash Write Row *****

//*************************************************************************/

//Pass a pointer to the data in RAM to write, called pRAMData

//Pass a pointer to the Flash row to write to

//Warning, this WILL write the hole row i.e. 64 bytes, you must point to the START of a row!

void WriteFlashRow(byte* pRAMData, byte* pFlashData)

{

       //- -   -   -   -   - -   -   -   -   - -   -   -   -   - -   -   -   -   - -   -   -   -   -   -

       //Runs this code when running MC9S08 processors

       #ifdef _MC9S08  byte  tmpa;    //Just used for chewing cycles 

       byte StillData = 0x40;              //How many bytes to write (complete 64 bytes)

       if(FSTAT_FACCERR)

                       FSTAT_FACCERR = 1;            //Step 1 - If there is an access error, clear it

//-   -   - -   -   -   -   - -   -   -   -   - -   -   -   -   -   - -   -   -   -   - -   -   -   -   - -   -  

//Loop to program all bytes

       while(StillData--)

       {

                       __RESET_WATCHDOG(); //feed the dog

                        while(!FSTAT_FCBEF) //Step 2 - Wait until ready to accept the command                           __RESET_WATCHDOG(); //feed the dog         

                       *pFlashData++ = *pRAMData++;          // Step 3 - Write RAM data to FLASH                               FCMD = mBurstProg;             // Step 4 - Setup the burst program command FSTAT_FCBEF = 1; // Step 5 - Carry out command   

                       __asm ror tmpa;      // Step 6 - Chew some cycles as required by the data sheet (atleast four cycles, this will do 5)   

                       if(FSTAT_FPVIOL || FSTAT_FACCERR)

                       //Step 7 - If there is an access error, clear it, and exit (work out error handling  later)     

                       {

                                      FSTAT_FACCERR = 1;         

                                      return;

                       }

       }

       while(!FSTAT_FCCF) // Step 8 - Wait for the command complete flag                  __RESET_WATCHDOG();    //feed the dog

//-   -   - -   -   -   -   - -   -   -   -   - -   -   -   -   -   - -   -   -   -   - -   -   -   -   - -   -  

#endif 

//-   -   - -   -   -   -   - -   -   -   -   - -   -   -   -   -   - -   -   -   -   - -   -   -

//Runs this code when running HC908 processors#ifdef _HC908 

byte  StillData = 0x40;    //How many bytes to write (complete 64 bytes)

byte* pFlashFirstByte = pFlashData;  //Need to save this so we know when the row is

programmed  xFLCR |= PGM; //Step 1 - Set PGM bit 

__asm lda xFLBPR; // Step 2 - read from Flash block protect register

*pFlashFirstByte = 0xFF; //Step 3 - Write to any address in the flash range we are about to write data to

Delay(t10uS); //Step 4 - Wait for time tNVS xFLCR |= HVEN;     //Step 5 - Set the HVEN enable Delay(t5uS);     //Step 6 - Wait for time

//Step 7-8-9 - Write data to flash, delay 30uS, for entire row 0x40 bytes

(routine takes 30.1uS while(StillData--)

       {

       *pFlashData++ = *pRAMData++; 

       Delay(tPrg); //Tprog MAX is 40uS, allowing for the delay in the loop, this works out to ~30.1uS

       }

xFLCR &= (~PGM); //Step 10 - Clear PGM bit

Delay(t5uS); //Step 11 - Delay for tNVH

xFLCR &= (~HVEN); //Step 12 - Clear HVEN

#endif

//-   -   - -   -   -   -   - -   -   -   -   - -   -   -   -   - -   -   -   -   - -   }

/*************************************************************************

//**** Delay Routine *****

//*************************************************************************/

//Routine for delays above, not efficient at all, takes up time, and code space

//Please feel free to re write this and email to carl@edsengineering.com.au to be re posted

//Initializations required:

//Pass in variable A = Delay Value

//Values returned:    

//None

/*************************************************************************/

void Delay (byte A)

{

       unsigned char count;

       while (A!=0)

       {

                       for (count=0x03;count!=0;count--);

                        A--;

       }

       return;

}

#pragma CODE_SEG DEFAULT;

//WARNING: Do not add code to be ran from RAM below here   

// S08 PRM

/* This is a linker parameter file for the mc9s08gb32a */

NAMES END

/* CodeWarrior will pass all the needed files to the linker by command line. But here you may add your own files too. */

SEGMENTS

/* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */   

Z_RAM  = READ_WRITE   0x0080 TO 0x00FF;   

RAM =  READ_WRITE   0x0100 TO 0x087F;   

ROMDATA  =  READ_ONLY 0x8000 TO 0x87FF;   

//2K reserved for flash constants

ROM  =  READ_ONLY 0x8800 TO 0xEFFF;   

//Did end at 0xFFAF, moved back to make room for flash ram CDN 30/01/08   

F_RAM  =  READ_ONLY 0xF300 TO 0xFFAF;   

//Added read write block for flash data storage CDN 30/01/08   

ROM1  =  READ_ONLY 0xFFC0 TO 0xFFCB;   

ROM_IMAGE  =  READ_ONLY 0xF000 TO 0xF2FF RELOCATE_TO 0x0600;

//CDN 30/01/08 9pm (0x0600 needs to be adjusted, beware of stack and normal ram)

/* INTVECTS  =  READ_ONLY 0xFFCC TO 0xFFFF;

Reserved for Interrupt Vectors */

ENDPLACEMENT

/* Here all predefined and user segments are placed into the SEGMENTS defined above. */    DEFAULT_RAM /* non-zero page variables */ 

INTO  RAM;       

FlashData  INTO  ROMDATA;

_PRESTART,  /* startup code */  STARTUP,  /* startup data structures */  ROM_VAR,             /* constant variables */  STRINGS,  /* string literals */  VIRTUAL_TABLE_SEGMENT, /* C++ virtual table segment */   DEFAULT_ROM,  COPY  /* copy down information: how to initialize variables */   INTO  ROM;

/* ,ROM1: To use "ROM1" as well, pass the option -OnB=b to the compiler */    _DATA_ZEROPAGE,  /* zero page variables */   MY_ZEROPAGE INTO  Z_RAM; UserFlashData INTO  F_RAM; //CDN 30/01/08 9pm   

ToCopyToRAM INTO  ROM_IMAGE;  //CDN 30/01/08 9pm

ENDSTACKSIZE 0x50VECTOR 0 _Startup /* Reset vector: this is the default entry point for an application. */

//Required for flash routines

ENTRIES   FB01   FB02

END

//Just setup this define below to chose which processor you are using, include flash.h in your main.c

// flash.h

#define _MC9S08  //Use this to run for this family

// #define _HC908  //Use this to run for this family#include "derivative.h"

#pragma CONST_SEG UserFlashData  extern const far byte FB01; 

extern const far byte FB02;

#pragma CONST_SEG DEFAULT

/*************************************************************************

//***** Program-Specific Defines *****

//*************************************************************************/

#ifdef _MC9S08       //This must be setup based on the clock settings 

#define initFCDIV 0b01001100 //FLASH clock divider (setup for 20Mhz Bus) 

// |||||||| 

// |||||||+-DIV0 \ 

// ||||||+--DIV1 | 

// |||||+---DIV2 >-- divide by (12+1) 

// ||||+----DIV3 | BUSCLK/(8*12)~=(192.3Khz) 

// |||+-----DIV4 | 

// ||+------DIV5 / 

// |+-------PRDIV8 -- divide (prescale) by 8 

// +--------DIVLD --- read-only status

#endif

extern char __SEG_START_ToCopyToRAM[];   //Used for copying code to RAMextern char

__SEG_SIZE_ToCopyToRAM[]; //Used for copying code to RAMextern byte __SEG_START_UserFlashData[];    //Used for copying code to RAMextern byte __SEG_SIZE_UserFlashData[]; //Used for copying code to RAMvoid EraseRoutine (byte*);void Delay (byte);

void CopyInRAM(void);

void WriteFlashRow(byte*, byte*); //Start_Copy_In_RAM refers to the begining of the segment

//ToCopyToRAM. This segment contains the functions after

//they have been copied to RAM.#define Start_Copy_In_RAM __SEG_START_ToCopyToRAM

#define Size_Copy_In_RAM __SEG_SIZE_ToCopyToRAM

//Start_In_ROM refers to the begining of the segment

//ToCopyToRAM. This segment contains the functions in ROM.

//refers to the beginining of the segment

#define Start_User_Flash_Data __SEG_START_UserFlashData

//UserFlashData start

#define User_Flash_Data __SEG_START_UserFlashData

//Size of UserFlashData as defined in PRM file

#define Size_User_Flash_Data __SEG_SIZE_UserFlashData

#ifdef _HC908 

/*************************************************************************/

/***** FLASH Delay Equates *****/ /*************************************************************************/

// To setup these values use 

// 30X + 31 cycles where X is the value u pass 

// NOTE, when passing 0x00, it only takes 30 cycles, not 31. 

// to take into account bus frequency 

// (30X + 31) / Bus Frequency = Time 

// GP32 Set at 4.9152uS   // 

// .XLS formula =((30*A2)+31) / $C$2 

// Where A2 is a colum from 0 > 255, and Cell C2 = bus frequency in Hertz 

// These results arnt correct, but they are close enough for the flash erase/write /*************************************************************************/ 

#define t5uS    0x00    // ~5uS (6.31uS) 

#define t10uS   0x01   // ~10uS (12.4uS) 

#define tPrg    0x02    // Used for delay in programming bytes

#define t30uS   0x03  // ~30uS (30.7uS) 

#define t1mS    0xA3    // 1ms (1.00mS)

#endif              

//908 prm file    /* This is a linker parameter file for the GP32 */  NAMES END  /* CodeWarrior will pass all the needed files to the linker by command line. But here you may add your own files too. */  SEGMENTS   /* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */    ROM  =  READ_ONLY    0xA000 TO 0xFDFF; //Moved from 0x8000 to 0x9000 to make room for flash data storage   

F_RAM  =  READ_ONLY 0x9000 TO 0x9FFF;      //Added read write block for flash data  storage   

Z_RAM =  READ_WRITE 0x0040 TO 0x00FF;   

RAM  =  READ_WRITE 0x0100 TO 0x023F;

ROM_IMAGE =  READ_ONLY 0xF000 TO 0xF2FF RELOCATE_TO 0x017A;  

//CDN 02/07/07 7pm

ENDPLACEMENT

/* Here all predefined and user segments are placed into the SEGMENTS defined above. */    DEFAULT_RAM   INTO  RAM;   

DEFAULT_ROM, ROM_VAR, STRINGS  INTO ROM;

/*  In case you want to use  as well, be sure the option -OnB=b is passed to the compiler. */    _DATA_ZEROPAGE, MY_ZEROPAGE  INTO  Z_RAM;   

UserFlashData  INTO  F_RAM; //CDN 02/07/07 10pm   

ToCopyToRAM INTO  ROM_IMAGE; //CDN 02/07/07 7pm

ENDSTACKSIZE 0x50VECTOR 0 _Startup

/* Reset vector: this is the default entry point for an application. */

ENTRIES   FB01   FB02

END


Message Edited by CarlFST60L_3rd on 2008-01-31 11:31 AM

Message Edited by CarlFST60L_3rd on 2008-01-31 11:32 AM

Message Edited by CarlFST60L_3rd on 2008-01-31 11:33 AM

0 Kudos

1,877 Views
russellsher
Contributor III

HI -

Forgive my ignorance but how do I expand the view of that posted code from the one line with a scroll bar?

I copied using shift/end and pasted , but it is not formatted.

thanks

Russell

0 Kudos

1,877 Views
alexod
Contributor I
Carl,

Thanks for the example.  I was porting my MCF5213 code to an S08, and it was driving me crazy.

The CF has a different address range to write to flash, so I was writing to flash outside the RAM routine, that was legal and worked.  The S08 was different enough, I salvaged about 75% of my code, and yo filled in the blanks the data sheets leave.

Alex
0 Kudos

1,877 Views
HelloIvan
Contributor I

Hello all,

Sorry for digging out this thread as I need to seek some advice fromt he expert here.

Currently, I am using the HCS08DZ60 for my project and I have developed a codes based on the example below.  However, I found that the programming time used by Byte program and Burst program is exactly the same after testing.   Hence I hope the experts here can clear my doubts.

=================================================================================
void WriteFlashRow(byte* pRAMData, byte* pFlashData){
//-   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -
//Runs this code when running MC9S08 processors
#ifdef _MC9S08
  byte  tmpa;                          //Just used for chewing cycles
  byte  StillData = 0x40;              //How many bytes to write (complete 64 bytes)
 
  if(FSTAT_FACCERR) FSTAT_FACCERR = 1;  //Step 1 - If there is an access error, clear it
//-   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -  
//Loop to program all bytes
while(StillData--){
   
    __RESET_WATCHDOG();                   //feed the dog  
   
    while(!FSTAT_FCBEF)                   //Step 2 - Wait until ready to accept the command
      __RESET_WATCHDOG();                 //feed the dog 
   
    *pFlashData++ = *pRAMData++;          // Step 3 - Write RAM data to FLASH
    
    FCMD = mBurstProg;                    // Step 4 - Setup the burst program command
     
    FSTAT_FCBEF = 1;                      // Step 5 - Carry out command

    __asm ror tmpa;                       // Step 6 - Chew some cycles as required by the data sheet (atleast four cycles, this will do 5)

    if(FSTAT_FPVIOL || FSTAT_FACCERR)     //Step 7 - If there is an access error, clear it, and exit (work out error handling later)
      {
        FSTAT_FACCERR = 1; 
        return;
      }

  }

=================================================================================

I noticed that the example above is going to program 64 bytes to flash memory.
From the codes, I found that the mBurstProg command is lanuched every times.  What I do not understand is that the Burst Program will program 32 bytes at a time, the why do we need to launch the Burst command every time?
If I need to program 128 bytes, does it mean I need to launch the command for 128 times?  Then it will be similar to the Byte program.

I read the below statement from the user manual Section 4.5.5 Burst Program Executive.
"The next sequential address selects a byte on the same burst block as the current byte being programmed. A burst block in this Flash memory consists of 32 bytes. A new burst block begins at each 32-byte address boundary."

The statement mentioned about the boundary address, but from the above example code, I can only see the address is increasing sequentially.  Do we need to increment the address by 32 so as to program a new burst block?  For example, I have 128 bytes to be programmed (let say the starting address is 0x2B00), do I need to provide the address in this way: 0x2B00 (first burst block), 0x2B00+0x20 (second burst block), etc.?

Hope the expert here can give me some pointers.

Thank you ver much.

Regards,
ivan



Message Edited by Hello Ivan on 2009-01-21 06:55 AM
0 Kudos

1,877 Views
bigmac
Specialist III
Hello Ivan, and welcome to the forum.

The difference between burst programming and the programming of a single byte is the particular status flag used.  For burst programming, the FCBEF flag is tested, and when set a new burst command can be initiated.  However, when programming a single byte there should be a wait until the FCCF flag is set, which requires the additional cycles.

You have actually omitted from your code the test of the FCCF flag for the final byte - not a good idea if you intend to immediately program another flash row or single byte.

Since the maximum number of bytes that may be programmed during burst mode is 32, your function should limit to this amount, rather than the 64 bytes you currently have.  Presumably, as each flash row is completed, the internally generated high voltage is turned off, and then reapplied to the next row.  The additional wait for the FCCF flag should ensure this occurs.  To program 128 bytes, you would need to call the burst programming function four times.  The pointer parameter pFlashData will always require to be initialised to a 32 byte boundary.

You have not specifically mentioned what you have done, but for the 'DZ60 device, if the data is to reside in flash memory, the burst programming function code will need to reside within the EEPROM block, or vice versa.  Alternatively, the function code could be transferred to RAM prior to its use.

The following modified function code has been slightly streamlined, and includes the final FCCF flag test.

byte WriteFlashRow( byte* pRAMData, byte* pFlashData)
{
#ifdef _MC9S08
   byte  err_status;
   byte  StillData = 32;             // Number of bytes to write
 
   FSTAT = 0x30;                     // Clear FPVIOL & FACCERR flags
   while (StillData--) {             // Loop to program all bytes
      while (!FSTAT_FCBEF);          // Wait until ready to accept command
      *pFlashData++ = *pRAMData++;   // Write RAM data to FLASH address
      FCMD = mBurstProg;             // Setup burst program command
      FSTAT_FCBEF = 1;               // Initiate command
      __RESET_WATCHDOG();            // Delay 3+ cycles
      err_status = FSTAT & 0x30;
      if (err_status)
         return (err_status);        // If error, return error status
   }
   while (!FSTAT_FCCF);              // Wait for command complete
   return (err_status);
#endif
}



Regards,
Mac
0 Kudos

1,877 Views
Ricardo_RauppV
Contributor I

Hi Guys

I lost many hours trying make my code works, and now finally I found the reason to not work.

Maybe it is usefull for others...and for me if some advice appears..:smileyhappy::smileyhappy:

My flash routines writes data either from RAM as FLASH:

 

void Internal_flash::write(uint32 flash_address_write,uint8 *p_in,uint16 size)

 

I´m running this routine in RAM memory....

 

It was working fine until I decide to make use of burst mode.

For this mode, inside the main loop, we monitor the EMPTY buffer flag (FSTAT_FCBEF)  and not the COMPLETE process flag (FSTAT_FCCF).

After mani attempts I realize that only data from RAM area was successfully transfered to thye flash, while data from FLASH were not copied....

So I concluded the reason is I´m reading the flash while burning it.

I thought I could make it, because:

0x2400 = destiny

0x2E00 = source

 

that is, different pages....

ColdFires allows this kind of operation...

 

Well, the solution I adopted is to continue to monitor COMPLETE process flasg.....

Have someone a experience like this? 

 

Thanks

Ricardo Raupp

 

 

 

 

 

 

 

0 Kudos

1,877 Views
bigmac
Specialist III

Hello Ricardo,

 

You do not say which HCS08 device you are using, however most devices provide only a single flash array (the 'DZ60 device is an exception).  With a single array, access to all flash is disabled during the erase and programming process.  Therefore, the portion of the code that executes whilst high voltage is internally applied to the flash array must be RAM resident.  Once the FCCF flag is set, high voltage is no longer applied, and flash access is available.

 

When using the burst programming command, when the FCBEF flag becomes set, ready for the next data byte, the previous flash command has not completed, and flash access is still unavailable.  Therefore more of the code needs to be RAM resident in this case, plus the data block to be programmed.

 

For very small HCS08 devices, the additional RAM requirement for burst programming may not be readily available.  The small reduction in total programming time for burst programming, compared with byte-by-byte programming, will not be justified in many cases, especially if the flash sector needs to be first erased (20 milliseconds typical).

 

Regards,

Mac

 

0 Kudos

1,877 Views
Ricardo_RauppV
Contributor I

Hi Bigmac

Sorry..the mcu is a QE128....

Very thanks for your help !!!!

 

Ricardo Raupp

0 Kudos

1,877 Views
CarlFST60L_3rd
Contributor I
Yes, but it only works with the memory windows open if i follow specific steps, if just hit run, the code runs, but does not actually erase... I am confused.

Will post the working code in a couple of days, hopefully someone will find a use for it.
0 Kudos

1,877 Views
JimDon
Senior Contributor III
Well, in theory anyway, if you have no periodical updates, and only a hardware break point set, the debugger should leave the chip alone.

Are you using a BDM?




Message Edited by JimDon on 2008-01-30 10:29 PM
0 Kudos

1,877 Views
bigmac
Specialist III
Hello,
 
My understanding is that the COP timer is enabled after a reset, but does not increment during background debug mode, to prevent COP reset.
During normal operation, it is possible for COP reset to occur within the flash erase period (20ms), unless precautions are taken.
 
Regards,
Mac
 


Message Edited by bigmac on 2008-01-31 09:16 PM
0 Kudos

1,877 Views
CarlFST60L_3rd
Contributor I
Thanks for that input.

The fix was simply to feed the watch dog during both while loops, close all three memory windows and add the ! to the last while loop.

To me, this cop reset dosnt make sense as with the orginal code I can step the program to the erase function, run to the next line after erase function and it works every time! Obviously if this didnt work, I would have been thinking differently.

I tried adding long delays just before and after flash erase routines (to see if i could simulate stopping before and after the function), but that didnt work so it appears to me that the cyclone pro has somthing to do with helping the orginal code to work... confusing. And it works with the memory windows open...

I didnt want to have the two watchdog reset lines in the while loop to allow us to use the watchdog as some crude saftey i.e. if the while loops get stuck due to Flash problems, the processor resets and and will not attempt to write to flash until some user input.

Now to do the flash rowwrite routines. Then I will post combined routines for page erase / burst write routines.


0 Kudos

1,877 Views
JimDon
Senior Contributor III
And it works with the memory windows open...
Well, if you did not have periodical on, it shouldn't try to read while running.
Also, when TT thinks it is flash, he won't refresh the display at all (at least the version I was using)
I once thought my HCS12 EERPOM write code was broke, because not matter what I did I could not get TT to re-read the memory, until I lied and said it was ram.


0 Kudos

1,877 Views
peg
Senior Contributor IV
Hi Carl,

Running a live memory window on flash while programming will cause flash memory accesses which will disrupt programming!

0 Kudos

1,877 Views
kef
Specialist I
step 7 should be
 
    while( ! FSTAT_FCCF);                   
 
 
0 Kudos