Hello.
I used S12VR.
I want to write or read from internal EEPROM of S12VR.
so,
////////////////////////////////////////////////////////////////////////////////////////////////////////////
static volatile word data[] ={0x1234,0x4567,0x6789,0x9123};
word eeprom_address = 0x400 ;
static byte start_flash_command_and_wait[]={
/*Clear FSTAT*/
/*BSET FSTAT 0x80*/
0x1C, 0x01, 0x06, 0x80,
/*Wait for command to end*/
/*BRCLR FSTAT 0x80*/
0x1F, 0x01, 0x06, 0x80, -5,
/*Return*/
0x3D
};
void main()
{
CPMUOSC_OSCE = 0; /*Using internal OSC. FREF = 1MHz*/
CPMUSYNR_SYNDIV = 0x18; /*FVCO = 50MHz = 2*FREF/(0x18+0x01)*/
CPMUSYNR_VCOFRQ = 0x01; /*48MHz < fVCO<= 50MHz*/
while (!CPMUFLG_LOCK){} /* Wait for PLL to lock */
CPMUCLKS_PLLSEL = 1; /* select the PLLCLK/2 as the bus clock */
CPMUPOSTDIV = 0; /*FPLL = FVCO/(POSTDIV + 1) = 50MHz*/
/*FBUS = 25MHz*/
ECLKCTL_NECLK = 0; /*Mirror Bus clock to a PIN...Only use it for reference purposes not to clock another device*/
FCCOBIX = 0 ;
FCCOB = 0x1100 ;
FCCOBIX = 1 ;
FCCOB = eeprom_address ;
eeprom_address+= 8;
while (!FSTAT_CCIF);
FSTAT=0x30;
for (FCCOBIX=2; (FCCOBIX<(4+2)); FCCOBIX++){
FCCOB = data[FCCOBIX-2];
}
FCCOBIX--;
asm(PSHC);
asm(SEI);
asm BSR start_flash_command_and_wait;
asm(PULC);
for(;;)
_FEED_COP(); /* feeds the dog */
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
what is wrong?
Do you have an exam code to read or write internal eeprom?
help me plz.
thanks.
Solved! Go to Solution.
I solved the problem.
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#define EEPROM_START 0x000400
#define EEPROM_END 0x0007FF
#define EEPROM_SECTOR 0x04
#define OK 0
#define ERASED 1
#define NON_ERASED 2
#define MISALIGNED_ADDRESS 3
#define ACCESS_ERROR 4
#define VERIFICATION_FAILED 5
#define LENGTH_OUT_OF_RANGE 6
void SetPEEmodeBUSCLK(byte _synr, byte _refdv, byte _postdiv);
#pragma CODE_SEG NON_BANKED
interrupt 28 void PLL_LockIsr(void);
#pragma CODE_SEG DEFAULT
byte EEPROM_Erase_Verify_Section(word address, word number_of_words);
byte EEPROM_Program(word int address, word *ptr, byte number_of_words);
byte EEPROM_Erase_Sector(word int address);
word EEPROM_Read_Word(word int address);
void EEPROM_Init(byte fdiv);
word buf[4] = {0xACBD, 0x9812, 0x5678, 0xEF34};
byte err;
byte cnt ;
void SetPEEmodeBUSCLK(byte _synr, byte _refdv, byte _postdiv)
{
CPMUSYNR = _synr;
CPMUREFDIV = _refdv;
CPMUPOSTDIV = _postdiv;
CPMUOSC_OSCE = 1; //enable external oscillator OSCE
while(!CPMUFLG_UPOSC)
{// you can check for timeot here with error message report
};
while(!CPMUFLG_LOCK)
{// you can check for timeot here with error message report
};
//--- select clocks --------------------
CPMUCLKS = 0B10000011; // bus=fPLL/2; COP is clocked from OSCCLK
if(CPMUCLKS != 0B10000011) // After writing CPMUCLKS register, it is strongly recommended to read
{ // back CPMUCLKS register to make sure that write of PLLSEL,
asm nop; // RTIOSCSEL, COPOSCSEL0 and COPOSCSEL1 was successful.
}
//--------------------------------------
}
//******************************************************************************
//EEPROM Send_Command
//******************************************************************************
//this function is stored in RAM memory
//in C language:
// {
// FSTAT_CCIF = 1; //launch command
// while(FSTAT_CCIF == 0); //wait for done
// }
static byte Send_Command[]=
{
0x1C, 0x01, 0x06, 0x80, 0x1F, 0x01, 0x06, 0x80, 0xFB, 0x3D
};
//******************************************************************************
//EEPROM_Erase_Verify_Section
//******************************************************************************
byte EEPROM_Erase_Verify_Section(word address, word number_of_words)
{
//check if address is aligned (global address [2:0] = 000)
if((address & 0x0004) != 0)
return MISALIGNED_ADDRESS;
while(FSTAT_CCIF == 0); //wait if command in progress
FSTAT = 0x30; //clear ACCERR and PVIOL
FCCOBIX = 0x00;
FCCOB = 0x1000;
FCCOBIX = 0x01;
FCCOB = address;
FCCOBIX = 0x02;
FCCOB = number_of_words;
asm JSR Send_Command;
if((FSTAT & (FSTAT_ACCERR_MASK | FSTAT_FPVIOL_MASK)) != 0)
return ACCESS_ERROR;
//check if phrases are erased and return result
if(FSTAT_MGSTAT != 0)
return NON_ERASED;
else
return ERASED;
}
//******************************************************************************
//EEPROM_Program
//******************************************************************************
byte EEPROM_Program(word address, word *ptr, byte number_of_words)
{
word i;
if((number_of_words < 1) || (number_of_words > 4))
return LENGTH_OUT_OF_RANGE;
//check if address is aligned (global address [0] != 0)
if((address & 0x0001) != 0)
return MISALIGNED_ADDRESS;
//check if the word(s) is/are erased
if((EEPROM_Erase_Verify_Section(address, number_of_words)) == NON_ERASED)
return NON_ERASED;
while(FSTAT_CCIF == 0); //wait if command in progress
FSTAT = 0x30; //clear ACCERR and PVIOL
FCCOBIX = 0x00;
FCCOB = 0x1100;
FCCOBIX = 0x01;
FCCOB = address;
for(i=1; i<=number_of_words; i++) //fill appropriate number of words to FCCOB
{
FCCOBIX = i+1;
FCCOB = *ptr;
ptr++;
}
asm JSR Send_Command;
if((FSTAT & (FSTAT_ACCERR_MASK | FSTAT_FPVIOL_MASK)) != 0) return ACCESS_ERROR;
if(FSTAT_MGSTAT != 0) return VERIFICATION_FAILED;
return OK;
}
//******************************************************************************
//EEPROM_Erase_Sector
//******************************************************************************
byte EEPROM_Erase_Sector(word address)
{
//size of sector is 4B
//check if address is aligned (global address [0] != 0)
if((address & 0x00000001) != 0)
return MISALIGNED_ADDRESS;
while(FSTAT_CCIF == 0); //wait if command in progress
FSTAT = 0x30; //clear ACCERR and PVIOL
FCCOBIX = 0x00;
FCCOB = 0x12;
FCCOBIX = 0x01;
FCCOB = address;
asm JSR Send_Command;
if((FSTAT & (FSTAT_ACCERR_MASK | FSTAT_FPVIOL_MASK)) != 0) return ACCESS_ERROR;
if(FSTAT_MGSTAT != 0) return VERIFICATION_FAILED;
return OK;
}
//******************************************************************************
//PFLASH_Read_Word
//******************************************************************************
word EEPROM_Read_Word(word address)
{
word data16;
data16 = *(word *)address;
return data16;
}
//******************************************************************************
//PFLASH_Init
//******************************************************************************
void EEPROM_Init(byte fdiv)
{
FCLKDIV = fdiv;
}
//******************************************************************************
static byte start_flash_command_and_wait[]={
/*Clear FSTAT*/
/*BSET FSTAT 0x80*/
0x1C, 0x01, 0x06, 0x80,
/*Wait for command to end*/
/*BRCLR FSTAT 0x80*/
0x1F, 0x01, 0x06, 0x80, -5,
/*Return*/
0x3D
};
void delay(unsigned int i)
{
while(i--) ;
}
#pragma CODE_SEG NON_BANKED
__interrupt VectorNumber_Vtimovf void TIM_OVERFLOW(void)
{
TFLG2_TOF = 1 ;
PTT_PTT0 ^= 1 ;
}
__interrupt VectorNumber_Vtimch0 void TIM_CH0(void)
{
TFLG1_C0F = 1 ;
cnt++ ;
PTT_PTT0 ^= 1 ;
}
#pragma CODE_SEG DEFAULT
void main(void) {
/* put your own code here */
unsigned int addr;
CPMUOSC_OSCE = 0; /*Using internal OSC. FREF = 1MHz*/
CPMUSYNR_SYNDIV = 0x18; /*FVCO = 50MHz = 2*FREF/(0x18+0x01)*/
CPMUSYNR_VCOFRQ = 0x01; /*48MHz < fVCO<= 50MHz*/
while (!CPMUFLG_LOCK){} /* Wait for PLL to lock */
CPMUCLKS_PLLSEL = 1; /* select the PLLCLK/2 as the bus clock */
CPMUPOSTDIV = 0; /*FPLL = FVCO/(POSTDIV + 1) = 50MHz*/
/*FBUS = 25MHz*/
ECLKCTL_NECLK = 0; /*Mirror Bus clock to a PIN...Only use it for reference purposes not to clock another device*/
DDRT_DDRT0 = 1 ; // PT0 Output
PERT_PERT0 = 1 ; //PT0 Pull up
DDRT_DDRT1 = 1 ; // PT1 Output
PERT_PERT1 = 1 ; //PT1 Pull up
TSCR2_TOI = 1; /* Timer overflow interrupt enable */
TSCR1_TEN = 1; /* Timer Enable */
TSCR2_PR = 2 ; /* Timer prescaler select */
EnableInterrupts;
//--- PLL Initialization ---------------
SetPEEmodeBUSCLK(0x01, 0x80, 0x00); // 16MHz BUSCLK from 8 MHZ oscclk, PEE mode
ECLKCTL_NECLK = 0; // enable ECLK output (bus clock is visible on pin PS7)
//--------------------------------------
// INITIALIZE THE EEPROM
//------------------------------
EEPROM_Init(0x0F);// default settings:
// internal oscillator is used = 1MHz => bus clk 8MHz => divide by 0x07
// to achieve FCLK 1MHz
// Table 15-7. FDIV values for various BUSCLK Frequencies
//------------------------------
// check entire EEPROM whether required data are already written
if( (*(word*)(0x400)) != 0xAABB)
{
// the flag at 0x0400 says there are not correct data
// check the eeprom is erased
//------------------------------
if(EEPROM_Erase_Verify_Section(EEPROM_START,512) == NON_ERASED)
{
// if no then erase entire EEPROM
//------------------------------
for(addr = EEPROM_START; addr < EEPROM_END; addr+=EEPROM_SECTOR)
{
err = EEPROM_Erase_Sector(addr);
}
}
//...and write required data
//------------------------------
err = EEPROM_Program(EEPROM_START, buf, 4);
for(addr = EEPROM_START+8; addr < EEPROM_END; addr+=2)
{
err = EEPROM_Program(addr, &addr, 1);
}
}
for(;;) {
_FEED_COP(); /* feeds the dog */
PTT_PTT1 ^= 1 ;
delay(1000) ;
/*
err = EEPROM_Program(EEPROM_START, buf, 4);
for(addr = EEPROM_START+8; addr < EEPROM_END; addr+=2)
{
err = EEPROM_Program(addr, &addr, 1);
}
*/
} /* loop forever */
/* please make sure that you never leave main */
}
I solved the problem.
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#define EEPROM_START 0x000400
#define EEPROM_END 0x0007FF
#define EEPROM_SECTOR 0x04
#define OK 0
#define ERASED 1
#define NON_ERASED 2
#define MISALIGNED_ADDRESS 3
#define ACCESS_ERROR 4
#define VERIFICATION_FAILED 5
#define LENGTH_OUT_OF_RANGE 6
void SetPEEmodeBUSCLK(byte _synr, byte _refdv, byte _postdiv);
#pragma CODE_SEG NON_BANKED
interrupt 28 void PLL_LockIsr(void);
#pragma CODE_SEG DEFAULT
byte EEPROM_Erase_Verify_Section(word address, word number_of_words);
byte EEPROM_Program(word int address, word *ptr, byte number_of_words);
byte EEPROM_Erase_Sector(word int address);
word EEPROM_Read_Word(word int address);
void EEPROM_Init(byte fdiv);
word buf[4] = {0xACBD, 0x9812, 0x5678, 0xEF34};
byte err;
byte cnt ;
void SetPEEmodeBUSCLK(byte _synr, byte _refdv, byte _postdiv)
{
CPMUSYNR = _synr;
CPMUREFDIV = _refdv;
CPMUPOSTDIV = _postdiv;
CPMUOSC_OSCE = 1; //enable external oscillator OSCE
while(!CPMUFLG_UPOSC)
{// you can check for timeot here with error message report
};
while(!CPMUFLG_LOCK)
{// you can check for timeot here with error message report
};
//--- select clocks --------------------
CPMUCLKS = 0B10000011; // bus=fPLL/2; COP is clocked from OSCCLK
if(CPMUCLKS != 0B10000011) // After writing CPMUCLKS register, it is strongly recommended to read
{ // back CPMUCLKS register to make sure that write of PLLSEL,
asm nop; // RTIOSCSEL, COPOSCSEL0 and COPOSCSEL1 was successful.
}
//--------------------------------------
}
//******************************************************************************
//EEPROM Send_Command
//******************************************************************************
//this function is stored in RAM memory
//in C language:
// {
// FSTAT_CCIF = 1; //launch command
// while(FSTAT_CCIF == 0); //wait for done
// }
static byte Send_Command[]=
{
0x1C, 0x01, 0x06, 0x80, 0x1F, 0x01, 0x06, 0x80, 0xFB, 0x3D
};
//******************************************************************************
//EEPROM_Erase_Verify_Section
//******************************************************************************
byte EEPROM_Erase_Verify_Section(word address, word number_of_words)
{
//check if address is aligned (global address [2:0] = 000)
if((address & 0x0004) != 0)
return MISALIGNED_ADDRESS;
while(FSTAT_CCIF == 0); //wait if command in progress
FSTAT = 0x30; //clear ACCERR and PVIOL
FCCOBIX = 0x00;
FCCOB = 0x1000;
FCCOBIX = 0x01;
FCCOB = address;
FCCOBIX = 0x02;
FCCOB = number_of_words;
asm JSR Send_Command;
if((FSTAT & (FSTAT_ACCERR_MASK | FSTAT_FPVIOL_MASK)) != 0)
return ACCESS_ERROR;
//check if phrases are erased and return result
if(FSTAT_MGSTAT != 0)
return NON_ERASED;
else
return ERASED;
}
//******************************************************************************
//EEPROM_Program
//******************************************************************************
byte EEPROM_Program(word address, word *ptr, byte number_of_words)
{
word i;
if((number_of_words < 1) || (number_of_words > 4))
return LENGTH_OUT_OF_RANGE;
//check if address is aligned (global address [0] != 0)
if((address & 0x0001) != 0)
return MISALIGNED_ADDRESS;
//check if the word(s) is/are erased
if((EEPROM_Erase_Verify_Section(address, number_of_words)) == NON_ERASED)
return NON_ERASED;
while(FSTAT_CCIF == 0); //wait if command in progress
FSTAT = 0x30; //clear ACCERR and PVIOL
FCCOBIX = 0x00;
FCCOB = 0x1100;
FCCOBIX = 0x01;
FCCOB = address;
for(i=1; i<=number_of_words; i++) //fill appropriate number of words to FCCOB
{
FCCOBIX = i+1;
FCCOB = *ptr;
ptr++;
}
asm JSR Send_Command;
if((FSTAT & (FSTAT_ACCERR_MASK | FSTAT_FPVIOL_MASK)) != 0) return ACCESS_ERROR;
if(FSTAT_MGSTAT != 0) return VERIFICATION_FAILED;
return OK;
}
//******************************************************************************
//EEPROM_Erase_Sector
//******************************************************************************
byte EEPROM_Erase_Sector(word address)
{
//size of sector is 4B
//check if address is aligned (global address [0] != 0)
if((address & 0x00000001) != 0)
return MISALIGNED_ADDRESS;
while(FSTAT_CCIF == 0); //wait if command in progress
FSTAT = 0x30; //clear ACCERR and PVIOL
FCCOBIX = 0x00;
FCCOB = 0x12;
FCCOBIX = 0x01;
FCCOB = address;
asm JSR Send_Command;
if((FSTAT & (FSTAT_ACCERR_MASK | FSTAT_FPVIOL_MASK)) != 0) return ACCESS_ERROR;
if(FSTAT_MGSTAT != 0) return VERIFICATION_FAILED;
return OK;
}
//******************************************************************************
//PFLASH_Read_Word
//******************************************************************************
word EEPROM_Read_Word(word address)
{
word data16;
data16 = *(word *)address;
return data16;
}
//******************************************************************************
//PFLASH_Init
//******************************************************************************
void EEPROM_Init(byte fdiv)
{
FCLKDIV = fdiv;
}
//******************************************************************************
static byte start_flash_command_and_wait[]={
/*Clear FSTAT*/
/*BSET FSTAT 0x80*/
0x1C, 0x01, 0x06, 0x80,
/*Wait for command to end*/
/*BRCLR FSTAT 0x80*/
0x1F, 0x01, 0x06, 0x80, -5,
/*Return*/
0x3D
};
void delay(unsigned int i)
{
while(i--) ;
}
#pragma CODE_SEG NON_BANKED
__interrupt VectorNumber_Vtimovf void TIM_OVERFLOW(void)
{
TFLG2_TOF = 1 ;
PTT_PTT0 ^= 1 ;
}
__interrupt VectorNumber_Vtimch0 void TIM_CH0(void)
{
TFLG1_C0F = 1 ;
cnt++ ;
PTT_PTT0 ^= 1 ;
}
#pragma CODE_SEG DEFAULT
void main(void) {
/* put your own code here */
unsigned int addr;
CPMUOSC_OSCE = 0; /*Using internal OSC. FREF = 1MHz*/
CPMUSYNR_SYNDIV = 0x18; /*FVCO = 50MHz = 2*FREF/(0x18+0x01)*/
CPMUSYNR_VCOFRQ = 0x01; /*48MHz < fVCO<= 50MHz*/
while (!CPMUFLG_LOCK){} /* Wait for PLL to lock */
CPMUCLKS_PLLSEL = 1; /* select the PLLCLK/2 as the bus clock */
CPMUPOSTDIV = 0; /*FPLL = FVCO/(POSTDIV + 1) = 50MHz*/
/*FBUS = 25MHz*/
ECLKCTL_NECLK = 0; /*Mirror Bus clock to a PIN...Only use it for reference purposes not to clock another device*/
DDRT_DDRT0 = 1 ; // PT0 Output
PERT_PERT0 = 1 ; //PT0 Pull up
DDRT_DDRT1 = 1 ; // PT1 Output
PERT_PERT1 = 1 ; //PT1 Pull up
TSCR2_TOI = 1; /* Timer overflow interrupt enable */
TSCR1_TEN = 1; /* Timer Enable */
TSCR2_PR = 2 ; /* Timer prescaler select */
EnableInterrupts;
//--- PLL Initialization ---------------
SetPEEmodeBUSCLK(0x01, 0x80, 0x00); // 16MHz BUSCLK from 8 MHZ oscclk, PEE mode
ECLKCTL_NECLK = 0; // enable ECLK output (bus clock is visible on pin PS7)
//--------------------------------------
// INITIALIZE THE EEPROM
//------------------------------
EEPROM_Init(0x0F);// default settings:
// internal oscillator is used = 1MHz => bus clk 8MHz => divide by 0x07
// to achieve FCLK 1MHz
// Table 15-7. FDIV values for various BUSCLK Frequencies
//------------------------------
// check entire EEPROM whether required data are already written
if( (*(word*)(0x400)) != 0xAABB)
{
// the flag at 0x0400 says there are not correct data
// check the eeprom is erased
//------------------------------
if(EEPROM_Erase_Verify_Section(EEPROM_START,512) == NON_ERASED)
{
// if no then erase entire EEPROM
//------------------------------
for(addr = EEPROM_START; addr < EEPROM_END; addr+=EEPROM_SECTOR)
{
err = EEPROM_Erase_Sector(addr);
}
}
//...and write required data
//------------------------------
err = EEPROM_Program(EEPROM_START, buf, 4);
for(addr = EEPROM_START+8; addr < EEPROM_END; addr+=2)
{
err = EEPROM_Program(addr, &addr, 1);
}
}
for(;;) {
_FEED_COP(); /* feeds the dog */
PTT_PTT1 ^= 1 ;
delay(1000) ;
/*
err = EEPROM_Program(EEPROM_START, buf, 4);
for(addr = EEPROM_START+8; addr < EEPROM_END; addr+=2)
{
err = EEPROM_Program(addr, &addr, 1);
}
*/
} /* loop forever */
/* please make sure that you never leave main */
}
Hi,
an example code you can find in the appnote AN4448:
MC9S12VR Family Demonstration Lab Training
Inside the SW pack, there is a demo project for Flash (both Program and Data (EEPROM)). In the flash.c you can find the routines.
Regards,
iggi