MCF51QE128:  Problem using Flash, errors in CodeWarrior  (long post)

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

MCF51QE128:  Problem using Flash, errors in CodeWarrior  (long post)

3,676 Views
fireweaver
Contributor I
I have been working on a medical-related project that accumulates a few hundred bytes of data from a transducer and when the data are finally accumulated, it is stored in Flash and read back at next powerup.  Or, that is at least the intent.

I am using CodeWarrior 6.1 (the one that came with the DEMOQE128 kit), and programming the actual product board via BDM using the "USB HCS08/HCS12 Multilink Rev. C" programmer.

Problem 1:

When I try to compile the code (code in question attached) I get the following error messages out of CodeWarrior.

Message:
Link Error   : Overflow in segment: userram from section: .bssSegment reserved size is: 0x00002000 -- Overflow of: 0x00001fe4Link Error   : Overflow in segment: userram from section: .customSegment reserved size is: 0x00002000 -- Overflow of: 0x00001fe4Link Error   : Overflow in segment: userram from section: .rompSegment reserved size is: 0x00002000 -- Overflow of: 0x00001ffc

Problem 2:   This is weird, but it seems related, and I'm not sure I have language to describe it properly.

When I compile any of the statements below into my code, the "True-Time Simulator and Real-Time Debugger" that came with CodeWarrior jams.  It doesn't seem to completely load the code, (it "hangs" at the very end) so the target CPU cannot even be reset without a power cycle to clear the blockage. All of the statements involved either read or write to Flash.

Code:
Flash_Programme_One_Byte( i, Volume.flash_study[ i]);   // see end of codeFlash_Programme_One_Byte( i, Extra.flash_report[ i]);Volume.flash_study[ i] = flash_rom[ i];       // see end of codeExtra.flash_report[ i] = flash_rom[ i];

 These statements appear in the code presented below which contains the data definitions and the complete implementation of the Flash programming interface as needed by this project.

Code:
/* study_data.c *//****************************************************************************        Defines data structures for Microflo and provides a means of saving and    recovering a study in flash.****************************************************************************//****************************************************************************        Assorted variable and constant declarations.****************************************************************************/// time declarations#define THIRTY_SECONDS  30*8#define ONE_MINUTE      60*8#define TWO_MINUTES     120*8#define ONE_HALF_SECOND 4#define STARTUP_FLOW    24bool collector_still_busy = TRUE;short max_flow;                 // maximum flow.long autozero_total;short autozero_samples; /****************************************************************************    ADC variables and storage area.****************************************************************************/#define ADC_SAMPLES  64         // size of averagerstruct Convertor{    short offset15;             // weight of empty GUB.    short previous15;           // immediately preceding sample.    short raw15;                // a->d reading without offsetting    short volume15;             // volume enhanced to 15 bits.    short i;                    // index to adc_samples.                 long  total;                // sum of last 64 samples.    short data[ ADC_SAMPLES];   // holds last samples. } ADC;  /****************************************************************************    Flow averaging variables and storage area.****************************************************************************/#define FLOW_SAMPLES  8struct FlowAverager {    short raw;                  // calculated flow rate    short smoothed;             // after heavy averaging    short previous;             // saved flow value    short i;                    // index to flow samples    short total;                // sum of last 8 flow samples    short data[ FLOW_SAMPLES];  // holds last 8 flow samples} Flow; /****************************************************************************    Volume recording variables and storage area.    This gets stored in flash.****************************************************************************/#define RECORD_LENGTH 3*62*8    struct VolumeMemory{    short i;                            // index to recorded study    short stop;                         // index < RECORD_LENGTH where record stops.    short final_volume;                 // final value of volume    short recording[ RECORD_LENGTH];    // body of study } Study;// Determine number of long words needed to save the study in flash.#define STUDY_SIZE (sizeof( Study) + sizeof( long) / sizeof( long))// Translate between record format and linear long format for storage.union volume_union{    struct VolumeMemory Study;    long   flash_study[ STUDY_SIZE];} Volume;/****************************************************************************    Patient report fields and variables.    This contains only "finished" values.    This gets stored in flash.****************************************************************************/struct PatientReport{    short Vvol;                 // voided volume    short TtoMax;               // time to maximum flow.        short Tvoid;                // total time it took patient to piss.    short Tflow;                // total time patient actually spent pissing.        short Qmax;                 // maximum flow    short Qavg;                 // average flow        bool  flow_pattern;         // "CONTINUOUS" or "INTERMITTENT"} Report;// Determine number of long words needed to save the report in flash.#define REPORT_SIZE  ((sizeof( Report) + sizeof( long)) / sizeof( long))// Translate between record format and linear long format for storage.union report_union{    struct PatientReport  Report;    long   flash_report[ REPORT_SIZE];} Extra;/****************************************************************************    Empty out the study area after reset or starting a new study.****************************************************************************/void Clear_Study( void){    short i;        for( i = 0; i < RECORD_LENGTH; i++) Study.recording[ i] = 0;} /* Clear_Study *//****************************************************************************    Test routine to report on amount of memory allocation for the    study and report.  Not used in product.****************************************************************************/void Test_Show_Allocated_Data_Sizes( void){    Printer_Enable();    PrintH( "Study size  = ", STUDY_SIZE);    PrintH( "Report size = ", REPORT_SIZE);    Printer_Disable();} /* Test_Show_Allocated_Data_Sizes *//****************************************************************************    Test the study area and see if it is empty.    Return TRUE if this is the case and FALSE otherwise.****************************************************************************/bool Empty_Study( void){    short i;    short notzero = 0;        for( i = 0; i < RECORD_LENGTH; i++) notzero |= Study.recording[ i];        if(notzero)    {        Message( "Study area has data.");         Advance_For_Spacing();         return FALSE;    }    else    {        Message( "Study area is blank.");         Advance_For_Spacing();         return TRUE;    }} /* Empty_Study *//****************************************************************************    Starting address of code related to flash memory.    Flash is organised as longwords (32-bits).    In this application, it is unprotected.        Taken from pp81..86 of MCF51QE128 Reference Manual, Rev 3****************************************************************************/extern long volatile flash_rom[ REPORT_SIZE] @0x0001F000;   // last 4 sectors./****************************************************************************    Flash commands****************************************************************************/#define ERASE_VERIFY        0x25#define PROGRAM_ONE_LONG    0x20#define BURST_PROGRAM       0x25#define SECTOR_ERASE        0x40#define MASS_ERASE          0x41/****************************************************************    This is the global initialisation routine for the flash    memory.  It is used by all the flash commands.        [1] Writes the proper divisor into the FCDIV register.    The flash programmer requires a reference frequency in the    range of 195 KHz to 200 KHz.  Using a divisor of 21 gives a     flash reference frequency of 4194304 / 21 = 199728 Hz which    is within specification.  Bit 7 of FCDIV is written "1" to     ensure future writability to this register.        [2] No backdoor key is used, so this is set to zero.        [3] All but the uppermost 4K of flash are protected against    inadvertent writes.****************************************************************/void Flash_Common_Code( void){    FCDIV = 0x80 + 21;    FCNFG = 0;                  // interpret write commands as actual writes.    FPROT = 0x41;               // protect all but uppermost 4K.    while(!(FSTAT & FSTAT_FCBEF_MASK)) {};  // wait for command buffer empty        if( FSTAT & (FSTAT_FACCERR_MASK | FSTAT_FPVIOL_MASK)) FSTAT = 0x30;} /* Flash_Common_Code *//****************************************************************    Checks a block of flash to see it if is erased:    Returns TRUE if operation is successful, FALSE otherwise.****************************************************************/bool Flash_Erase_Verify( short index){    Cpu_DisableInt();     Flash_Common_Code();        flash_rom[ index] = 0;        // command write sequence    FCMD = ERASE_VERIFY;    FSTAT = 0x80;        while(!(FSTAT & FSTAT_FCCF_MASK)) {};   // wait for command buffer empty         if( FSTAT & FSTAT_FBLANK_MASK) return TRUE; else return FALSE;    Cpu_EnableInt();} /* Flash_Erase_Verify *//****************************************************************    Erases a single sector (1024 bytes or 256 longs)    Returns TRUE if operation is successful, FALSE otherwise.****************************************************************/void Flash_Sector_Erase( short index){    Cpu_DisableInt();     Flash_Common_Code();         flash_rom[ index] = 0;    FCMD = SECTOR_ERASE;    FSTAT = 0x80;        while(!(FSTAT & FSTAT_FCCF_MASK)) {};           // wait for command buffer empty      Cpu_EnableInt();} /* Flash_Sector_Erase *//****************************************************************    Programs a single address in flash.****************************************************************/void Flash_Programme_One_Byte( short index, long data){    Cpu_DisableInt();     Flash_Common_Code();         flash_rom[ index] = data;            FCMD = BURST_PROGRAM;    FSTAT = 0x80;                   while(!(FSTAT & FSTAT_FCCF_MASK)) {};   // wait for command completion    Cpu_EnableInt();} /* Flash_Programme_One_Byte *//****************************************************************    Erase the study area of flash and verify the erasure.    Return TRUE if the erasure of all three sectors is good,    FALSE otherwise.****************************************************************/bool Erase_And_Verify_Data_Flash( void){    Flash_Sector_Erase( 0);    if( Flash_Erase_Verify( 0))    {                Flash_Sector_Erase( 0x100);        if( Flash_Erase_Verify( 0x100))        {            Flash_Sector_Erase( 0x200);            if( Flash_Erase_Verify( 0x200))            {                error = 0;                return TRUE;            }            else error = 29;     // block 3 failed erasure        }        else error = 28;         // block 2 failed erasure    }    else error = 27;             // block 1 failed erasure    return FALSE;} /* Erase_And_Verify_Data_Flash *//****************************************************************    Saves a study in flash.    ****************************************************************/void Save_Study_In_Flash( void){    short i;        if( Erase_And_Verify_Data_Flash())    {        for( i = 0; i < STUDY_SIZE; i++)         { //             Flash_Programme_One_Byte( i, Volume.flash_study[ i]);   // one of the problems        }        for( i = STUDY_SIZE; i < STUDY_SIZE + REPORT_SIZE; i++)        {             Flash_Programme_One_Byte( i, Extra.flash_report[ i]);        }    }     else    // something wrong so print an error message.    {        Printer_Enable();        Print_Error( error);        Printer_Disable();    }} /* Save_Study_In_Flash *//****************************************************************    Retrieves the last study from flash****************************************************************/void Restore_Study_From_Flash( void){    short i;        for( i = 0; i < STUDY_SIZE; i++)    { //       Volume.flash_study[ i] = flash_rom[ i];       // one of the problems    }        for( i = STUDY_SIZE; i < STUDY_SIZE + REPORT_SIZE; i++)    {        Extra.flash_report[ i] = flash_rom[ i];    }} /* Restore_Study_From_Flash *//*    These two statements result in the errors listed below.     //       Flash_Programme_One_Byte( i, Volume.flash_study[ i]); //       Volume.flash_study[ i] = flash_rom[ i]; Link Error   : Overflow in segment: userram from section: .bssSegment reserved size is: 0x00002000 -- Overflow of: 0x00001f5cLink Error   : Overflow in segment: userram from section: .customSegment reserved size is: 0x00002000 -- Overflow of: 0x00001f5cLink Error   : Overflow in segment: userram from section: .rompSegment reserved size is: 0x00002000 -- Overflow of: 0x00001f74Link failed.*/

 





Message Edited by fireweaver on 2008-07-30 07:14 PM
Labels (1)
0 Kudos
Reply
9 Replies

1,092 Views
JimDon
Senior Contributor III
The link error appear to indicate you have tried to use more RAM that is available.

You must be running from ram to program flash.  The QE128 has two 16 bit wide block that are interleaved, so it is not possible to program flash from flash. I don't see that stated in the QERM, so shame on the writers for omitting that "minor" point.
You must write the command and wait for it to finish from ram.

I do know where you could fin sample code. If you go to canyourbadgedothis.com, register, log in then click the link for "contest tools".
download FTF_Badge_2008_Bootloader.zip. There is code in that project to flash a V1.






0 Kudos
Reply

1,092 Views
fireweaver
Contributor I
So what you are saying is that even though the flash is divided into sectors (that's what the book says, anyway), those sectors are not really independent?  That it you are executing from one sector, programming an entirely different sector is forbidden?

Anyway, thanks for the link, I'm going to check it out.

0 Kudos
Reply

1,092 Views
JimDon
Senior Contributor III
Yes, the sectors are in a block, so there are gates to control programming, but the block as a whole goes "offline" when programming. I can't believe they fail to mention that - you are not the first one to miss it.


From the RM:

"The MCF51QE128/64/32 flash memory is organized as two 16-bit wide blocks interleaved to yield a 32-bit data path"

Since it needs 32 bits, it need both blocks.

If you get the code from that sample, post it here if you would.

0 Kudos
Reply

1,092 Views
fireweaver
Contributor I
Here is the code you asked for.  It is copied straight from the website:

Code:
/*********************************************************************************                                                                     *       Copyright (C) 2007 Freescale Semiconductor, Inc.              *       All Rights Reserved                      *                            * Filename:     flash.h                *                            * Revision:                              *                            * Functions:    flash driver header file*         * Description:  ** Notes:        **********************************************************************************//*********************************** Includes ***********************************//*********************************** Macros ************************************//*********************************** Defines ***********************************//* error code */#define Flash_OK          0x00#define Flash_FACCERR     0x01#define Flash_FPVIOL      0x02#define Flash_NOT_ERASED   0x04#define Flash_CONTENTERR   0x08#define Flash_NOT_INIT     0xFF/* flash commands */#define FlashCmd_EraseVerify    0x05#define FlashCmd_Program        0x20#define FlashCmd_BurstProgram   0x25#define FlashCmd_SectorErase    0x40#define FlashCmd_MassErase      0x41/********************************** Constant ***********************************//*********************************** Variables *********************************//*********************************** Prototype *********************************/extern void Flash_Init(unsigned char FlashClockDiv);extern unsigned char Flash_SectorErase(unsigned long *FlashPtr); extern unsigned char Flash_ByteProgram(unsigned long *FlashStartAdd,unsigned long *DataSrcPtr,unsigned long NumberOfBytes); void SpSub(void);void SpSubEnd(void);

 and

Code:
/*********************************************************************************                                                                     *       Copyright (C) 2007 Freescale Semiconductor, Inc.              *       All Rights Reserved                      *                            * Filename:     flash.c                *                            * Revision:                              *                            * Functions:    Includes flash routines*         * Description:  ** Notes:        **********************************************************************************//*********************************** Includes ***********************************/#include <hidef.h> /* for EnableInterrupts macro */#include "derivative.h" /* include peripheral declarations */#include "flash.h" /* include flash driver header file *//*********************************** Macros ************************************//*********************************** Defines ***********************************//********************************** Constant ***********************************//*********************************** Variables *********************************//*********************************** Prototype *********************************//*********************************** Function **********************************/ /******************************************************************************* * Function:        Flash_Init * * Description:     Set the flash clock * * Returns:         never return * * Notes: * *******************************************************************************/void Flash_Init(unsigned char FlashClockDiv) {  /* Flash clock between 150-200kHz - > 8MHz/(39+1)=200kHz*/  FCDIV = FlashClockDiv;}/******************************************************************************* * Function:        Flash_SectorErase * * Description:     erase a sector of the flash * * Returns:         Error Code * * Notes: * *******************************************************************************/unsigned char Flash_SectorErase(unsigned long *FlashPtr) {  unsigned char Return = Flash_OK;    /* Allocate space on stack to run flash command out of SRAM */ char localbuf[100]; int (*RunOnStack)(void) = (int(*)(void))localbuf; memcpy(localbuf, (void*)SpSub, (char*)SpSubEnd - (char*)SpSub);    if(FCDIV_FDIVLD == 1)    {    /* flash is init */        /* wait until FCBEF is set in FSTAT */    while(FSTAT_FCBEF == 0){}    /* check for errors */    if(FSTAT_FACCERR == 1)      {      /* clear error flag */      FSTAT = 0x10;      }    if(FSTAT_FPVIOL == 1)      {      /* clear error flag */      FSTAT = 0x20;      }    /* dummy write to flash */    *FlashPtr = (unsigned long)0x11111111;       /* write command */    FCMD = FlashCmd_SectorErase;        RunOnStack();        /* launch command */    //FSTAT = 0x80;        /* wait for command completion */    //while(FSTAT_FCCF == 0){}        /* check for errors */    if(FSTAT_FACCERR == 1)      {      /* clear error flag */      FSTAT = 0x10;            /* update return value*/      Return |= Flash_FACCERR;      }    if(FSTAT_FPVIOL == 1)      {      /* clear error flag */      FSTAT = 0x20;            /* update return value*/      Return |= Flash_FPVIOL;      }    }  else    {    /* flash is not init */    Return = Flash_NOT_INIT;    }  /* function return */  return  Return;}/******************************************************************************* * Function:        Flash_ByteProgram * * Description:     byte program the flash * * Returns:         Error Code * * Notes: * *******************************************************************************/unsigned char Flash_ByteProgram(unsigned long *FlashStartAdd,unsigned long *DataSrcPtr,unsigned long NumberOfBytes) {  unsigned char Return = Flash_OK;          /* Allocate space on stack to run flash command out of SRAM */ char localbuf[100]; int (*RunOnStack)(void) = (int(*)(void))localbuf; memcpy(localbuf, (void*)SpSub, (char*)SpSubEnd - (char*)SpSub);    if(FCDIV_FDIVLD == 1)    {    /* flash is init */        /* wait until FCBEF is set in FSTAT */    while(FSTAT_FCBEF == 0){}    /* check for errors */    if(FSTAT_FACCERR == 1)      {      /* clear error flag */      FSTAT = 0x10;      }    if(FSTAT_FPVIOL == 1)      {      /* clear error flag */      FSTAT = 0x20;      }    while((NumberOfBytes) && (Return == Flash_OK))      {            /* write data to flash and increase pointers by 1 */      *FlashStartAdd++ = *DataSrcPtr++;           /* write command */      FCMD = FlashCmd_Program;            RunOnStack();      /* launch command */      //FSTAT = 0x80;            /* wait for command completion */      //while(FSTAT_FCCF == 0){}            /* check for errors */      if(FSTAT_FACCERR == 1)        {        /* clear error flag */        FSTAT = 0x10;                /* update return value*/        Return |= Flash_FACCERR;        }      if(FSTAT_FPVIOL == 1)        {        /* clear error flag */        FSTAT = 0x20;                /* update return value*/        Return |= Flash_FPVIOL;        }            /* decrement byte count */      NumberOfBytes--;      }    }  else    {    /* flash is not init */    Return = Flash_NOT_INIT;    }  /* function return */  return  Return;}/******************************************************************************* * Function:        SpSub * * Description:     Execute the Flash write while running out of SRAM * * Returns:          * * Notes: * *******************************************************************************/void SpSub(void) { asm(    //Save off registers d0, d1, and d2    link    a6,#-12    movem.l d0-d2,(sp)    // MCF_CFM_CFMUSTAT = CBEIF;    mvs.w    #128,d0    move.b   d0,0xffff9825      // while (!(MCF_CFM_CFMUSTAT & CCIF)){};//wait until execution complete    loop:      mvz.b    0xffff9825,d1      moveq    #25,d0      lsl.l    d0,d1      moveq    #31,d2      lsr.l    d2,d1      tst.b    d1      beq.s   loop         //Restore registers d0, d1, and d2    movem.l (sp),d0-d2    lea     12(sp),sp    unlk    a6 );}/* Leave this immediately after SpSub */void SpSubEnd(void){}

 




0 Kudos
Reply

1,092 Views
gerardodiez
Contributor II

Hi to all,

I´m developing and event log with my internal flash and i need to erase only a sector giving the starting address of it. I use this function Flash_SectorErase that you add but in my case it erases 2Kbytes instead of 1KB. Do you know why? How would I need to change??

Thanks

0 Kudos
Reply

1,092 Views
JimDon
Senior Contributor III
Cool, thanks.

So it uses like 100 bytes on the stack. Shortly, some asm birds of prey should come by and cut that down, but at least you have a known working example.

Did you track down the source of the link error?


0 Kudos
Reply

1,092 Views
fireweaver
Contributor I
I didn't track down the link error.  When I spliced in the new code and doctored it a little, that went away.

If all this works, there are going to be a lot of happy people here at work.  :smileyvery-happy:
0 Kudos
Reply

1,092 Views
bkatt
Contributor IV


JimDon wrote:

Shortly, some asm birds of prey should come by and cut that down...


/*
 * This is copied to the stack and executed there by the flash driver
 */

flash_wait:
_flash_wait:
    /*  MCF_CFM_CFMUSTAT = CBEIF; */
    move.l   #__IPSBAR+0x1D0020,a0
    move.b   #0x80,(a0)   

    /* while (!(MCF_CFM_CFMUSTAT & CCIF)){}; */
.loopf:
    move.b   (a0),d0
    andi.l   #0x40,d0    
    beq.s    .loopf
       
    rts

flash_wait_x:
_flash_wait_x:

0 Kudos
Reply

1,092 Views
JimDon
Senior Contributor III
Wow, that was quick.
I assume a0 and d0 are disposable and do not need to be saved and restored?
0 Kudos
Reply