HC908GT8(16) writing non-volatile data to FLASH

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

HC908GT8(16) writing non-volatile data to FLASH

5,302 次查看
Technoman64
Contributor III
I am working on small project using the HC908GT8 mcu and need to record a small amount of data to FLASH and also store the trim value. I have written the following code after reading a few threads on here and the user manual for the derivative I am using.
Unfortunatly I do not have a board here to test with. I will be able to do a hardware test in the morning though. Just thought I would present my idea and see if anyone had any further input and or could use it for other HC(S)08 family members.
 
First here is the prm file in which I have defined two small segments. One section is in FLASH and the other in RAM. The FLASH segment is used to compile and store the ProgramFlash function. The RAM segment will hold a copy of the ProgramFlash function.
 
Code:
/* This is a linker parameter file for the GT8 */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    0xE051 TO 0xFDFF;    ROM2                     =  READ_ONLY    0xE000 TO 0xE050 FILL 0x00;    Z_RAM                    =  READ_WRITE   0x0040 TO 0x00FF;    RAM                      =  READ_WRITE   0x0151 TO 0x023F;    RAM2                     =  READ_WRITE   0x0100 TO 0x0150;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;        /* Code section for Flash programing function */    FLASH_CODE                          INTO  ROM2;    /* Copy section for Flash programming function */    /* Code must be ran from RAM whill programming Flash */    FLASH_RAM                           INTO  RAM2;    END/* Define the system STACK size */STACKSIZE 0x50/* Reset vector: this is the default entry point for an application. */VECTOR 0 _Startup/* Items in this section will be included during linking */ENTRIESProgramFlashEND

 
Now for the code.
Code:
#include <hidef.h> /* for EnableInterrupts macro */#include "derivative.h" /* include peripheral declarations *//* Define block protect register location */volatile const unsigned char BLOCK_PROTECT_REGISTER @ 0xFF7E;/* ProgramFlashByte function type define */typedef void (*PFB)(char*, char); /* Declare and initialize ProgramFlashByte */const PFB ProgramFlashByte = (PFB)0x0100;/* This segment is declared in the prm linker placement file *//* Segment address is 0x0100 to 0x0150 */#pragma DATA_SEG FLASH_RAM/* Declare array to copy ProgramFlash function into */unsigned char FlashRoutine[0x50];#pragma DATA_SEG DEFAULT/* This segment is declared in the prm linker placement file *//* Segment address is 0xE000 to 0xE050 */#pragma CODE_SEG FLASH_CODE/* This function will be copied to RAM at startup *//* Bus frequency MUST be at minimum 1 Mhz! for HC08GT8(16) *//* Delay timing is for bus speed of 2.457600Mhz maximum */void ProgramFlash(char* Address, char c){  /* Variables on the STACK */  char Buffer;    /* We must disable interrupts so no FLASH is accessed */  /* Remember to turn back on in main code */  DisableInterrupts;    /* Programming step 1 */  FLCR = 1;  /* Programming step 2 */  Buffer = BLOCK_PROTECT_REGISTER;           /* Programming step 3 */  Address[0] = c;  /* Wait for minimum 10us */  asm{    ldx #10;  Loop1:    dbnzx Loop1;  }  /* Programming step 5 */  FLCR = 9;  /* Wait for minimum 5us */  asm{    ldx #5;  Loop2:    dbnzx Loop2;  }  /* Programming step 7 */  Address[0] = c;  /* Wait for minimum 30us */  asm{    ldx #30;  Loop3:    dbnzx Loop3;  }  /* Programming step 10 */  FLCR = 8;  /* Wait for minimum 5us */  asm{    ldx #5;  Loop4:    dbnzx Loop4;  }  /* Programming step 12 */  FLCR = 0;  /* Programming step 13 */  asm{    nop;    nop;  }}#pragma CODE_SEG DEFAULT/* Function prototype(s) */void Cpu_Initialize(void);/* main() function */void main(void) {  /* Pointer to ProgramFlash function in FLASH */  volatile const char *Ptr = (volatile const char *)0xE000;  /* Used as index during code move from FLASH to RAM */  int Index;    /* Initialize cpu */  Cpu_Initialize();    /* Copy ProgramFlash function to RAM */  for(Index=0; Index<0x50; Index++){    FlashRoutine[Index] = Ptr[Index];  }  /* Program byte in FLASH using function in RAM */  ProgramFlashByte((char*)0xFF80, 20);    /* Loop forever */  for(;;) {  }}/* Initialize cpu registers and internal clock */void Cpu_Initialize(void) {  /* CONFIG1: COPRS=0,LVISTOP=0,LVIRSTD=1,LVIPWRD=0,LVI5OR3=1,SSREC=0,STOP=0,COPD=1 */  CONFIG1 = 41;  /* CONFIG2: Unused=0,Unused=0,EXTXTALEN=0,EXTSLOW=0,EXTCLKEN=0,Unused=0,OSCENINSTOP=0,Unused=0 */  CONFIG2 = 0;   /* ICG multiplier factor, 9.830400Mhz internal clock, 2.457600Mhz bus */  /* 307.2Khz * 32 */  ICGMR = 32;  /* Has the osc trim been set— */  if(*(byte*)0xFF80 != 0xFF)    ICGTR = *(byte*)0xFF80;  /* Wait for internal oscillator stabilization */  while(!ICGCR_ICGS);                  }

 
I believe this should work as inteneded(let me stress the should part). If it works I was thinking of trying to save the interrupt enable state and restore interrupts after programming the byte if they were enabled on entry to the ProgramFlashByte function. I read in the sticky post of the problems encountered when an interrupt occured while programming to the Flash array.
 
标签 (1)
0 项奖励
回复
3 回复数

959 次查看
Technoman64
Contributor III

Please see attached zip file for demo project. First time trying file attachment so if does not exist I messed up.

Must use Codewarrior HC08 Version 5.0

See ReadMe.txt in the project window for more information on using the code.

Hope it helps out some of you that have been trying to store non-volatile data to FLASH.

Found an error in main() and fixed.

Message Edited by Technoman64 on 05-25-200609:43 AM

Message Edited by Technoman64 on 05-25-200609:51 AM

0 项奖励
回复

959 次查看
Technoman64
Contributor III

I have updated the prm file and code some. This was done using Codewarrior for HC08 5.0 Eval version.

a - There is no need for a special ROM section for the programming code.

b - I have made a DATA_ROM section that is 256 bytes in size or Four 64-byte rows.

c - I have updated the programming functions as I suggested in the previous post.

d - There is no a function to ERASE 64-byte rows in FLASH.

e - The code for Programming and Erasing FLASH is loaded into RAM only as needed.

f - Only one Array is Required in RAM for both the Program and Erase functions.

Functions that I feel need to be included.

a - ProgramFlashWord(char * Address, unsigned int Number), this would be used for storing integers.

b - ProgramFlashLong(char *Address, unsigned long Number), should be obvious.

c - A function that can use two 64 byte sections to store data to be programmed and verify the operation was succesful on Reset.

New prm file

Code:

/* This is a linker parameter file for the GT8 */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    0xE000 TO 0xFCFF;    ROMDATA                  =  READ_ONLY    0xFD00 TO 0xFDFF;    Z_RAM                    =  READ_WRITE   0x0040 TO 0x00FF;    RAM                      =  READ_WRITE   0x0151 TO 0x023F;    RAM2                     =  READ_WRITE   0x0100 TO 0x0150;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;     _DATA_ZEROPAGE, MY_ZEROPAGE         INTO  Z_RAM;        /* Copy section for Flash programming function */    /* Code must be ran from RAM whill programming Flash */    FLASH_RAM                           INTO  RAM2;        /* 256 bytes of Non-volatile data section in FLASH */    /* There are four 64 byte rows in this section */    DATA_ROM                            INTO  ROMDATA;        END/* Define the system STACK size */STACKSIZE 0x50/* Reset vector: this is the default entry point for an application. */VECTOR 0 _Startup/* Items in this section will be included during linking */ENTRIESTestArrayEND


 
Now for the new code. Please excuse the fact that I have not broken this up into multiple files.

Code:

#include <hidef.h> /* for EnableInterrupts macro */#include "derivative.h" /* include peripheral declarations *//* Define FLASH programming error codes */#define ERROR_FLASH_ERASE   1#define ERROR_FLASH_ADDRESS 2#define ERROR_FLASH_WRITE   3/* Define ProgramFlashByte ID */#define PFB_ID              0x01#define PFB_ID_ADDRESS      0x0100#define PFB_SIZE            0x3C#define PFB_SIZE_ADDRESS    0x0101/* Define EraseFlashRow ID */#define EFR_ID              0x02#define EFR_ID_ADDRESS      0x0100#define EFR_SIZE            0x32#define EFR_SIZE_ADDRESS    0x0101/* Define block protect register location */#define BLOCK_PROTECT_REGISTER 0xFF7E;/* ProgramFlashByte function type define */typedef void (*PFB)(char*, char); /* Declare and initialize ProgramFlashByte */const PFB ProgramFlashByte = (PFB)0x0102;/* EraseFlashRow function type define */typedef void (*EFR)(char*); /* Declare and initialize ProgramFlashByte */const EFR EraseFlashBytes = (EFR)0x0102;/* This segment is declared in the prm linker placement file *//* Segment address is 0x0100 to 0x0150 */#pragma DATA_SEG FLASH_RAM/* Declare array to copy ProgramFlash function into */unsigned char FlashRoutine[0x50];#pragma DATA_SEG DEFAULT/* Non-Volatile data array in FLASH */#pragma CONST_SEG DATA_ROMconst int TestArray[5] = {0,1,2,3,4};#pragma CONST_SEG DEFAULT/* This function will be copied to RAM as needed *//* Bus frequency MUST be at minimum 1 Mhz! for HC08GT8(16) *//* Delay timing is for bus speed of 2.457600Mhz maximum */void ProgramFlash(char *Address, char c){  /* Programming step 1, set PGM bit */  FLCR = 1;  /* Programming step 2, Read block protect register */  asm{    lda BLOCK_PROTECT_REGISTER;  };  /* Programming step 3, Write any data to address */  *(char*)Address = c;  /* Programming step 4, Wait for minimum 10us */  asm{    ldx #10;  Loop1:    dbnzx Loop1;  }  /* Programming step 5, Set HVEN bit */  FLCR = 9;  /* Programming step 6, Wait for minimum 5us */  asm{    ldx #5;  Loop2:    dbnzx Loop2;  }  /* Programming step 7, Write data to address */  *(char*)Address = c;  /* Programming step 8, Wait for minimum 30us */  asm{    ldx #30;  Loop3:    dbnzx Loop3;  }  /* Programming step 9, Clear PGM bit */  FLCR = 8;  /* Programming step 10, Wait for minimum 5us */  asm{    ldx #5;  Loop4:    dbnzx Loop4;  }  /* Programming step 12, Clear HVEN bit */  FLCR = 0;  /* Programming step 13, Wait for 1us */  asm{    nop;    nop;  };}/* This function will be copied to RAM as needed *//* Bus frequency MUST be at minimum 1 Mhz! for HC08GT8(16) *//* Delay timing is for bus speed of 2.457600Mhz maximum */void EraseFlash(char *Address){  /* Row Erase step 1, Set ERASE bit */  FLCR = 2;  /* Row Erase step 2, Read Flash Block protect register */  asm{    lda BLOCK_PROTECT_REGISTER;  };  /* Row Erase step 3, Write to ROW address for ERASE */  *(char*)Address = 0;  /* Row Erase step 4, Wait for minimum 10us */  asm{    ldx #10;  Loop1:    dbnzx Loop1;  }  /* Row Erase step 5, Set HVEN bit */  FLCR = 10;  /* Row Erase step 6, Wait for minimum 1ms */  asm{    ldx #100;  Loop2:    dbnzx Loop2;  }  /* Programming step 7, Clear ERASE bit */  FLCR = 8;  /* Programming step 8,Wait for minimum 5us */  asm{    ldx #5;  Loop4:    dbnzx Loop4;  }  /* Programming step 9, Clear HVEN bit */  FLCR = 0;  /* Programming step 10, Wait for 1us */  asm{    nop;    nop;  };}/* Function prototype(s) *//* WriteFlashByte */char WriteFlashByte(char *Address, char c);/* EraseFlashRow */char EraseFlashRow(char *Address);/* Cpu_Initialize */void Cpu_Initialize(void);/* main() function */void main(void) {  /* Local variables */  char Error;  /* Initialize cpu */  Cpu_Initialize();    /* Write "Test" data to FLASH */  Error = WriteFlashByte((char*)0xFDF0, 'T');  Error = WriteFlashByte((char*)0xFDF1, 'e');  Error = WriteFlashByte((char*)0xFDF2, 's');  Error = WriteFlashByte((char*)0xFDF3, 't');  /* Erase FLASH row, 64 bytes */  Error = EraseFlashRow((char*)0xFDF3);      /* Write "Test2" data to FLASH */  Error = WriteFlashByte((char*)0xFDF0, 'T');  Error = WriteFlashByte((char*)0xFDF1, 'e');  Error = WriteFlashByte((char*)0xFDF2, 's');  Error = WriteFlashByte((char*)0xFDF3, 't');  Error = WriteFlashByte((char*)0xFDF4, '2');    /* Loop forever */  for(;;) {  }}/* WriteFlashByte */char WriteFlashByte(char *Address, char c) {  /* Turn OFF non-standard pointer conversion warning */  #pragma MESSAGE DISABLE C1805  /* Pointer to ProgramFlash function in FLASH */  char *Ptr = (char *)ProgramFlash;  /* Used as index during code move from FLASH to RAM */  int Index;  /* Storage for CCR */  unsigned char CCR_Byte;    /* Verify byte at Address is erased */  if(*(char*)Address != 0xFF) {    /* Return error not erased */    return ERROR_FLASH_ERASE;  }  /* Get a copy of the CCR */  asm{    tpa;    sta CCR_Byte;  };  /* Diasable interrupts now */  DisableInterrupts;  /* Mask off the interrupt bit */  CCR_Byte &= 0x08;  /* Check to see if ProgramFlash is present in RAM */  if(*(char*)PFB_ID_ADDRESS != PFB_ID || *(char*)PFB_SIZE_ADDRESS != PFB_SIZE) {    /* Set PFB ID and SIZE */    FlashRoutine[0] = PFB_ID;    FlashRoutine[1] = PFB_SIZE;    /* Copy ProgramFlashFunction to RAM */    for(Index=2; Index<0x50; Index++){      FlashRoutine[Index] = Ptr[Index-2];    }  }  /* Write the char(byte) to FLASH */  ProgramFlashByte(Address, c);  /* Restore interrupts— */  if(!CCR_Byte)    EnableInterrupts;  /* Verify write to FLASH */  if(*(char*)Address != c)    /* Return write error */    return ERROR_FLASH_WRITE;  /* Return success */  return FALSE;}  /* EraseFlashRow */char EraseFlashRow(char *Address) {  /* Pointer to ProgramFlash function in FLASH */  char *Ptr = (char *)EraseFlash;  /* Used as index during code move from FLASH to RAM */  int Index;  /* Storage for CCR */  unsigned char CCR_Byte;    /* Is row already erased– */  /* TODO */    /* Get a copy of the CCR */  asm{    tpa;    sta CCR_Byte;  };  /* Diasable interrupts now */  DisableInterrupts;  /* Mask off the interrupt bit */  CCR_Byte &= 0x08;  /* Check to see if EraseFlash is present in RAM */  if(*(char*)EFR_ID_ADDRESS != EFR_ID || *(char*)EFR_SIZE_ADDRESS != EFR_SIZE) {    /* Set PFB ID and SIZE */    FlashRoutine[0] = EFR_ID;    FlashRoutine[1] = EFR_SIZE;    /* Copy ProgramFlashFunction to RAM */    for(Index=2; Index<0x50; Index++){      FlashRoutine[Index] = Ptr[Index-2];    }  }  /* Write the char(byte) to FLASH */  EraseFlashBytes(Address);  /* Restore interrupts˜ */  if(!CCR_Byte)    EnableInterrupts;  /* Verify erase was successful */  /* TODO */  /* Return success */  return FALSE;}  /* Initialize cpu registers and internal clock */void Cpu_Initialize(void) {  /* CONFIG1: COPRS=0,LVISTOP=0,LVIRSTD=1,LVIPWRD=0,LVI5OR3=1,SSREC=0,STOP=0,COPD=1 */  CONFIG1 = 41;  /* CONFIG2: Unused=0,Unused=0,EXTXTALEN=0,EXTSLOW=0,EXTCLKEN=0,Unused=0,OSCENINSTOP=0,Unused=0 */  CONFIG2 = 0;   /* ICG multiplier factor, 9.830400Mhz internal clock, 2.457600Mhz bus */  /* 307.2Khz * 32 */  ICGMR = 32;  /* Has the osc trim been set™ */  if(*(byte*)0xFF80 != 0xFF)    ICGTR = *(byte*)0xFF80;  /* Wait for internal oscillator stabilization */  while(!ICGCR_ICGS);                  }


 

0 项奖励
回复

959 次查看
Technoman64
Contributor III

Tested the code listed above on an actaul device this morning and it worked.

I think the next thing to do is make a function that is in FLASH that,

a - Checks the memory location to insure it is erased.

b - Checks and stores the state of the interrupt enable.

c - Copy the byte programming function to RAM if it is NOT present.

d - If address is erased call the Function in RAM.

e - Restore the interrupt state.

f - Verify that the byte was programmed correctly.

g - Return FALSE on Success and Error Code relating to error.

 

Then write a Row erase function.

a - If Row is erased exit with success code.

b - Checks and stores the state of the interrupt enable.

c - Copy the RowErase function to RAM if it is NOT present.

d - Erase the desired Row using function in RAM.

e - Restore the interrupt state.

f - Verify that the byte was programmed correctly.

f -Return FALSE on Success and Error Code relating to error.

0 项奖励
回复