Flash page write in GP32, Codewarrior 5.7

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

Flash page write in GP32, Codewarrior 5.7

2,540 Views
CarlFST60L_2nd
Contributor I
Hi all,

Just after some ideas i have spent a couple of hours without making and progress with my flash erase / write routines for GP32 (68HC908GP32)...

I cannot work out why the processor is resetting when i call the WriteFlashRow(); function. Erase works. COP is disabled, routines are running from RAM, i believe i have all the right timing (i think), based on the data sheet... Seems to work in the simulator, and the erase routines appear to work as the bytes are erased when i upload the module (FB01, FB02)..

This code was chopped down, so some basic things may have been deleted, im also open to comments on better ways to do things as i am new to C, comming from assembly background

**************************************
FLASH.C
**************************************

#include "derivative.h"
#include "FlashRoutines.h"


#pragma CONST_SEG UserFlashData
const far byte FB01 = 0xC1;
const far byte FB02 = 0xC3;
#pragma CONST_SEG DEFAULT

//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 header file for addressing far bytes
byte xFLCR @ 0xFE08;          // NOTHING IS PROTECTED!
#define PGM   1               // Mask bits for FLCR
#define ERASE 2
#define MASS  4
#define HVEN  8

/*************************************************************************/
/****           Erase a Block of FLASH Memory Subroutine           *****/
/*************************************************************************/
// 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;
// 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 of the size specified in the      */
/* FLASH Control Registers and at the location specified by FLASH_addr.  */
/* FLASH_addr is any address within the block to be erased.  The routine */
/* follows the basic 9 step sequence of the FLASH erase operation.       */
/*                                                    */
/* Initializations required:                                 */
/*    Set charge pump clock and block erase size in xFLCR and xFLCR2;     */
/*    FLASH_addr set                                       */
/* Values returned:                                     */
/*    none                                               */
/*************************************************************************/
void EraseRoutine (byte *FlashRow)  //WARNING: This name is part of CopyInRAM, do not add code above this
{
  //This may need to be done in one line
 
  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
}
/*************************************************************************/
/****                        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){

    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
    while(pFlashData != (pFlashFirstByte+63)){
        *pFlashData++ = *pRAMData++;
        Delay(t10uS);         //Tprog MAX is 40uS, allowing for the delay in the loop, this works out to ~36uS
    }

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

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

    xFLCR &= (~HVEN);                  //Step 12 - Clear HVEN
}
/*************************************************************************/
/****                        Delay Routine                           *****/
/*************************************************************************/
/* This routine delays for a variable amount of time depending on the      */
/* value passed into the routine as variable A.                     */
/* Delay time = (12 + (5 + (11+72+11)*A + 11) + 8) / Bus Freq         */
/* This equation includes the bus cycles from calling the delay routine  */
/* until hitting the next line of code. This allows the user to           */
/* accurately predict the delay between two steps in the code.           */
/*                                                 */
/* 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 no add code to be ran from RAM below here       


Message Edited by CarlFST60L_2nd on 2007-08-09 09:11 AM
Labels (1)
0 Kudos
Reply
6 Replies

980 Views
CarlFST60L_2nd
Contributor I
Problem solved!

while(pFlashData != (pFlashFirstByte+63)

This compiled to code that runs from FLASH!

Thanks for putting up with my posts!

Whats the best way to do this without causing code to run from Flash?


Message Edited by CarlFST60L_2nd on 2007-08-09 01:11 PM
0 Kudos
Reply

980 Views
CarlFST60L_2nd
Contributor I
I have a file zipped that i am happy to post with full working GP32 flash erase/write routines if someone wants to host it
0 Kudos
Reply

980 Views
edgarandres8
Contributor I
Flash page write code

Hello.

would you please send me the file zipped with the flash page write code?

My email is edgarandres8@yahoo.com

Thanks

0 Kudos
Reply

980 Views
CarlFST60L_2nd
Contributor I
      
**************************************
MAIN.C
**************************************

#include <hidef.h>                /* for EnableInterrupts macro */
#include "derivative.h"           /* include peripheral declarations */
#include "EDS_MCinit.h"
#include "FlashRoutines.h"

void main(void) {

    MCUSetup();                     //Setup MCU (PLL, Config, IO and all other processor environment settings
    EnableInterrupts;               // enable interrupts
//    DebounceInit();                 //Initialise the debounce routines

// MAIN LOOP
for(;:smileywink:{
 
//------------------------------------------------------------------------------------------------
//Main loop   

byte  RAMData[64] = {0};
byte  FlashData[64] = {0};
byte  *pRAMData = &RAMData;
byte  temp = 0x00;
char  *pFlashData;
pFlashData = (char *)Start_User_Flash_Data;

while(pRAMData != (RAMData+65)) *pRAMData++ = ++temp ;         //Fill up RAM table with 0x01 to 0x3F

pRAMData = &RAMData;                 
DisableInterrupts;
CopyInRAM();
EraseRoutine(pFlashData);
//TEST pFlashData = &FlashData;              /*Write data to a ram array for testing purposes, where FlashData is byte; FlashData[64] = {0}; */
WriteFlashRow(pRAMData, pFlashData);  //Processor resets in this function
EnableInterrupts;

for(;:smileywink: PTC ^= 1;      //Stop here and toggle PTC bit 0

    __RESET_WATCHDOG();           // feeds the dog 
    }
// END Main loop

}

******************************
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 0x016F; //CDN 02/07/07 7pm
END

PLACEMENT /* 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
END


STACKSIZE 0x50

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

ENTRIES
   FB01
   FB02
END
***********************************
Flash.h
***********************************

#pragma CONST_SEG UserFlashData
extern const far byte FB01;
extern const far byte FB02;
#pragma CONST_SEG DEFAULT

/*************************************************************************/
/*****                   Program-Specific Defines                           *****/
/*************************************************************************/
extern char __SEG_START_ToCopyToRAM[];    //Used for copying code to RAM
extern char __SEG_SIZE_ToCopyToRAM[];     //Used for copying code to RAM

extern byte __SEG_START_UserFlashData[];    //Used for copying code to RAM
extern byte __SEG_SIZE_UserFlashData[];     //Used for copying code to RAM

void 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 thebeginining 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
/*************************************************************************/
/*****                     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
// Please note these results are wrong, the times are all substaintially over! (approx 25%),
// to many beers = bad code!
/*************************************************************************/
#define t5uS    0x00    // ~5uS (6.31uS)

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

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

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

*************************************
copied out of "EDS_MCinit.h"
*************************************
void SetupConfigReg(void){
     CONFIG1 = (
     CONFIG1_STOP_MASK |
     CONFIG1_LVIRSTD_MASK |
     CONFIG1_LVIPWRD_MASK |
     CONFIG1_LVISTOP_MASK |
     CONFIG1_COPD_MASK);
    
     CONFIG2 = (
     CONFIG2_OSCSTOPENB_MASK |
     CONFIG2_SCIBDSRC_MASK);
}
//------------------------------------------------------------------------------------------------
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
}


Message Edited by CarlFST60L_2nd on 2007-08-09 09:10 AM

Message Edited by CarlFST60L_2nd on 2007-08-09 09:12 AM

Message Edited by CarlFST60L_2nd on 2007-08-09 09:12 AM

Message Edited by CarlFST60L_2nd on 2007-08-09 09:15 AM
0 Kudos
Reply

980 Views
CarlFST60L_2nd
Contributor I
I have also updated
    (in flash write routines)
    while(pFlashData != (pFlashFirstByte+65)){
   
    while(pFlashData != (pFlashFirstByte+64)){
    and/or
    while(pFlashData != (pFlashFirstByte+32)){


**************************************
MAIN.C
**************************************

#include <hidef.h>                /* for EnableInterrupts macro */
#include "derivative.h"           /* include peripheral declarations */
#include "EDS_MCinit.h"
#include "FlashRoutines.h"

void main(void) {

    MCUSetup();                     //Setup MCU (PLL, Config, IO and all other processor environment settings
    EnableInterrupts;               // enable interrupts
//    DebounceInit();                 //Initialise the debounce routines

// MAIN LOOP
for(;{
 
//------------------------------------------------------------------------------------------------
//Main loop   

byte  RAMData[64] = {0};
byte  FlashData[64] = {0};
byte  *pRAMData = &RAMData[0];
byte  *pFlashData;
pFlashData = (byte *)Start_User_Flash_Data;

while(pRAMData != (RAMData+64)) *pRAMData++ = ++temp ;         //Fill up RAM table with 0x01 to 0x3F

pRAMData = &RAMData[0];                 
DisableInterrupts;
CopyInRAM();
EraseRoutine(pFlashData);
//TEST pFlashData = &FlashData[0];              /*Write data to a ram array for testing purposes, where FlashData is byte; FlashData[64] = {0}; */
WriteFlashRow(pRAMData, pFlashData);  //Processor resets in this function
EnableInterrupts;

for(; PTC ^= 1;      //Stop here and toggle PTC bit 0

    }
// END Main loop

}


Nothing major, just fixed up some basic stuff...

I am still stumped as to why the processor is reseting. I have tried two processors and get the same result, i can call eraseflash and it works, but calling writeflash causes a reset.

LVI is disable, COP is disabled, the Simulator lets it run no problem, but the processor resets... Take out that routine, and it sits there toggling PTC0


Message Edited by CarlFST60L_2nd on 2007-08-09 12:06 PM
0 Kudos
Reply

980 Views
CarlFST60L_2nd
Contributor I
The cause of the reset is ILAD (Illegal address reset) i.e. "last reset called by an opcode fetch from an illegal address", the POR reset flag is also set.

Would the simulator not reset with the same problem?? I have stepped through the assembly code an not noticed the PC going anywhere out of bounds...

Anyone go any ideas as to what could cause this in the processor and not in the simulator?
0 Kudos
Reply