how to configure and write code for flash module in MC9S12ZVCRMV1 controller.How to configure protection register and FCCOB register.It will be great if i get a sample code for flash and eeprom.

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

how to configure and write code for flash module in MC9S12ZVCRMV1 controller.How to configure protection register and FCCOB register.It will be great if i get a sample code for flash and eeprom.

4,832 Views
sathishkannan
Contributor III

please explain about FFCOB register.in that command ,address and data's are there .what they mean ?

Labels (1)
29 Replies

2,522 Views
sathishkannan
Contributor III

Hi,

I am developing bootloader for my controller.as part of i want to edit the linker file .i need to some of the information about linker file editing.

please explain each in placement

PLACEMENT /* here all predefined and user segments are placed into the SEGMENTS defined above. */

      _PRESTART,              /* Used in HIWARE format: jump to _Startup at the code start */

      STARTUP,                /* startup data structures */

      ROM_VAR,                /* constant variables */

      STRINGS,                /* string literals */

      VIRTUAL_TABLE_SEGMENT,  /* C++ virtual table segment */

    //.ostext,                /* OSEK */

      NON_BANKED,             /* runtime routines which must not be banked */

      DEFAULT_ROM,

      COPY              INTO  ROM;

      SHADOW_ROM INTO  SHADOW_ROM_S;

i am refering AN4723 example code in that i configured linker as ROM starting address 0xFD0000.but start up address is changed to some other address (0XFD003E)with reference to map file.why there is small gap in address ?

STARTUP SECTION

---------------------------------------------------------------------------------------------

Entry point: 0xFD002E (_Startup)

_startupData is allocated at 0xFD003E and uses 20 Bytes

extern struct _tagStartup {

  unsigned nofZeroOut     1

  _Range   pZeroOut       0x1100     4793

  _Copy    *toCopyDownBeg 0xFDBDB5

  int      nofInitBodies  0

  _Cpp     *initBodies    0xFD0059

  int      nofFiniBodies  0

  _Cpp     *finiBodies    0xFD0059

} _startupData;

please explain about Entry point address 0xFD002E .what does location means anything reserved for 2E bytes.

SECTION-ALLOCATION SECTION

Section Name                    Size  Type     From       To       Segment

---------------------------------------------------------------------------------------------

.init                             62     R   0xFD0000   0xFD003D   ROM

.startData                        27     R   0xFD003E   0xFD0058   ROM

.rodata                         1736     R   0xFD0059   0xFD0720   ROM

.text                          45695     R   0xFD0721   0xFDB99F   ROM

.copy                            529     R   0xFDB9A0   0xFDBBB0   ROM

.stack                           256   R/W     0x1000     0x10FF   RAM

.data                            578   R/W     0x1100     0x1341   RAM

will .init change based on application code ?

please explain .init,.startData ,.rodata

can u explain with a small example of bootloader code ,and what all the precautions has to be taken as taking care of linker file.

0 Kudos

2,522 Views
sathishkannan
Contributor III

Thanks,

if i want to write by bytes (8 different bytes) in to 1 phrase .is it possible ?.i checked it shows some magic values in memory of every high registers(FCCOB1HI,FCCOB2HI....).What may be the reason ?

0 Kudos

2,522 Views
RadekS
NXP Employee
NXP Employee

Hi Sathish,

Yes, you could (rather say you have to) program P-Flash per 8 bytes = 4 words.

There are no magic numbers. Please look at Table 22-26. FCCOB - NVM Command Mode (Typical Usage) in RM. There you could see that FCCOB1HI have to contain Global address [15:8] = (middle byte from global address). The FCCOB2HI have to consist Data 0 [15:8] = higher byte from first word.

If you use PFLASH_Program() function from my example code, input should be array filed by words.

If you want that input buffer is byte array, you have to convert it into word array prior use PFLASH_Program() function or you have to directly modify (or create your own) PFLASH_Program() function.

In second case, input parameter should be “unsigned char *ptr” and commands

  FCCOB2 = ptr[0];

  FCCOB3 = ptr[1];

  FCCOB4 = ptr[2];

  FCCOB5 = ptr[3];

Have to be replaced by

  FCCOB2LO = ptr[0];

  FCCOB2HI = ptr[1];

  FCCOB3LO = ptr[2];

  FCCOB3HI = ptr[3];

  FCCOB4LO = ptr[4];

  FCCOB4HI = ptr[5];

  FCCOB5LO = ptr[6];

  FCCOB5HI = ptr[7];

Note: Optionally you could use some simple loop with pointers instead of this sequence of commands.  


I hope it helps you.

Have a great day,
RadekS

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,522 Views
sathishkannan
Contributor III

Is it possible to program as a single word in flash memory as in eeprom .? then i am getting access error while erasing flash memory what may be reason ?

0 Kudos

2,522 Views
RadekS
NXP Employee
NXP Employee

Hi Sathish,

Minimum part for P-Flash erase is sectors (aligned 512B for S12ZVC).

Minimum part for P-Flash program is phrase (aligned 8B for S12ZVC).

So, even if your data is just one word, you have to program 4 words. Area in P-Flash for these 4 words must be in erased state (all bytes are 0xFF) prior programming. You should check these words prior programming and these words has to be aligned (lowest three bits from address has to be 0).

Please check Table 22-41. Program P-Flash Command Error Handling and Table 22-50. Erase P-Flash Sector Command Error Handling in RM.

There you could see error conditions which results as ACCERR error flag.

At least critical part (start flash command and wait until command finish) of code must be executed from RAM.


I hope it helps you.

Have a great day,
RadekS

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,526 Views
sathishkannan
Contributor III

I Tried your program with code warrior,

1)I am not able to erase the memory location.I checked with the MGSTAT flags they are stays clear  so it indicates that blank check passed.(not reflecting in memory regions)

2)I am able to write the FFCOB data registers,but how to check whether the data successfully written in flash memory ?

3)With reference to your code,in erase function if i am giving  address it has to erase memory of 512 bytes starting from that ,Is nt it?

4)How to know the free memory in flash,Is it visible in code warrior debugger.

5) I found some points from other forum about the code warrior debugger.

     How do verify that flash contents doesn't change? If it's Codewarrior debugger, you should keep in mind that by default it caches flash and EEPROM contents and doesn't display actual flash contents, unless you make modifications to debugger memory map (in debugger go to Multtilink menu)

What this means ?

6) Guide me step by step procedure to check the memory regions in debugger.

0 Kudos

2,526 Views
RadekS
NXP Employee
NXP Employee

Hi sathish,

  1. Did you use code which I provided to you few replies above?
  2. For example you could read that flash. See PFLASH_Read_Byte() function.
  3. Yes
  4. No, there isn’t such tool which directly told you occupancy of you flash (rather say, I do not know about such tool for S12Z). Please look at your map file and check amount of used flash and area where linker placed your code/data. In prm file are defined available areas for linker.
  5. In fact, this note is related to CW5.1 or older – Classic IDE. CW10 - Eclipse IDE do not have such configuration of debugger memory map. So, you could simply use memory monitor in debugger for display any area for MCU memory map. Since programming takes some time and debugger refresh data when MCU halts, new changes in flash memory could be displayed with small delay (typically one step) during stepping over code.
  6. Go to Debugger Memory Monitor window, click on “+” icon and fill target memory address in flash…


I hope it helps you.

Have a great day,
RadekS

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,525 Views
sathishkannan
Contributor III

Hi

1) yes .i checked the erase function with memory regions where the memory locations are already flashed by application.Will it take time to reflect in debugger address map ?

2) If i use PFLASH_Read_Byte() to read the memory locations I am not possible to get the data from locations where the locations are already programmed by application.

5)Right now i am stepping the debugger to see the change in memory map.Do i need to do anything else to see the programmed memory region ?

7)i am not moving my code to ram will it be a problem to erase and program flash memory ?If yes explain the reason.

"     Erasing a sector will set all its bits to 1. After erasing a sector, the FTMRZ can try to write data into it but this can’t be done

while executing code from Flash, since Flash can’t be read-from and written-to at the same time. To write to a Flash sector,

the application must be executing code from RAM"

What this means ?

0 Kudos

2,526 Views
RadekS
NXP Employee
NXP Employee

Hi sathish,

1)Yes, see Table K-2. NVM Timing Characteristics 32 MHz in RM. Erase P-Flash Sector takes 20ms. Also reading trough BDM interface takes some time.

2)That is strange. Could you please let me know which address you erase and try program?

5) no, that should be enough.

7) Yes, it is a problem. It is not possible to read from P-Flash memory while some commands are executing on the same P-Flash block. If a Flash block is read during execution of an algorithm (CCIF = 0) on that same block, the read operation may return invalid data resulting in an illegal access. So, there is high chance that CPU will execute something different instead of main code. Debugger will be confused and/or MCU could go into reset due to Illegal opcode or Illegal address.

CW10 typically reports that issue by opening new window with some numbers. Only way how to back synchronize debugger with MCU is trough MCU reset.


I hope it helps you.

Have a great day,
RadekS

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,526 Views
sathishkannan
Contributor III

Hi ,

I tried to erase a memory location which contained flashed code.In that location i am not able to erase as well as program.

how to get the address from prm file can you explain with an example ?

0 Kudos

2,526 Views
RadekS
NXP Employee
NXP Employee

Hi sathish,

Prm file defines available RAM/EEPROM/Flash space for linker.

So, if we want use some part of flash for our data, we should exclude this part of flash from linker memory map otherwise we could meet with situation that we will rewrite our code – this typically means crash of code.

Example:

Default Flash range for S12ZVC is defined as:

ROM          = READ_ONLY  0xFD0000 TO 0xFFFDFF;

Note: Range 0xFFFE00 to 0xFFFFFF is used for vectors.

We want use for example range 0xFE0000 to 0xFE7FFF (32kB) to storage our user data. In that case we should define Flash as:

ROM1          = READ_ONLY  0xFD0000 TO 0xFDFFFF;

ROM2          = READ_ONLY  0xFE0000 TO 0xFE7FFF;

ROM3          = READ_ONLY  0xFE8000 TO 0xFFFDFF;

And section “PLACEMENT” will contain:

      DEFAULT_ROM,

      COPY              INTO  ROM1, ROM3;

In that case, default code cannot be placed into ROM2 area since this area is not in default placement.

When we want store also some data (code or constants) into ROM2 area as part of our project, we could create our own segment in section “PLACEMENT”. For example:

MY_DATA  INTO ROM2;

In our C file we could place our data into this segment by pragmas. For example:

#pragma CONST_SEG MY_DATA

const unsigned char test1 = 0xAA;

#pragma CONST_SEG DEFAULT

Note: CONST_SEG pragmas are used for constants placement. CODE_SEG pragmas are used for code placement. DATA_SEG pragmas are used for variables placement.

Note: these pragmas are not limited by end of file, therefore I would like to strictly recommend return to default settings (#pragma xxxx_SEG DEFAULT) inside this file.

This way we could simply drive placement of code/constants/variables in MCU memory map.

Note: If possible, I would like to recommend do not use direct placement like:

const unsigned char temp1 @0xFE0000 = 0xAA;

without exclude this area from linker memory map. Linker does not aware about that data in code placement and any overlapping just lead to warning message. Unfortunately default CW10.6 project has disabled these warnings due to 24bit register constructions in S12Z derivative header file.

Disabled overlapping warnings.png


I hope it helps you.

Have a great day,
RadekS

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,526 Views
sathishkannan
Contributor III

Hi,

thanks alot for the explanation.

Can you explain how to open and see the linker file from codewarrior for particular project.

0 Kudos

2,526 Views
RadekS
NXP Employee
NXP Employee

CW10_6 prm file.png


I hope it helps you.

Have a great day,
RadekS

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

2,526 Views
sathishkannan
Contributor III

Hi My linker file is defined as below.I need to know the free address for writing data .How to edit this file ?

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

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. */

/* Register space  */

/*    IO_SEG        = PAGED         0x000000 TO   0x000FFF; intentionally not defined */

/* RAM */

      RAM           = READ_WRITE  0x001000 TO 0x001FFF;

/* EEPROM */

      EEPROM        = READ_ONLY   0x100000 TO 0x1003FF;

/* non-paged FLASHs */

      ROM           = READ_ONLY   0xFF0000 TO 0xFFFDFF;

/*   VECTORS       = READ_ONLY     0xFFFE00 TO   0xFFFFFF; intentionally not defined: used for VECTOR commands below */

   //OSVECTORS      = READ_ONLY     0xFFFE10 TO   0xFFFFFF;   /* OSEK interrupt vectors (use your vector.o) */

 

END

PLACEMENT /* here all predefined and user segments are placed into the SEGMENTS defined above. */

      _PRESTART,              /* Used in HIWARE format: jump to _Startup at the code start */

      STARTUP,                /* startup data structures */

      ROM_VAR,                /* constant variables */

      STRINGS,                /* string literals */

      VIRTUAL_TABLE_SEGMENT,  /* C++ virtual table segment */

    //.ostext,                /* OSEK */

      NON_BANKED,             /* runtime routines which must not be banked */

   

       DEFAULT_ROM,

      COPY              INTO  ROM;

    //.stackstart,            /* eventually used for OSEK kernel awareness: Main-Stack Start */

      SSTACK,                 /* allocate stack first to avoid overwriting variables on overflow */

    //.stackend,              /* eventually used for OSEK kernel awareness: Main-Stack End */

    DEFAULT_RAM         INTO  RAM;

  //.vectors            INTO  OSVECTORS; /* OSEK */

END

ENTRIES /* keep the following unreferenced variables */

    /* OSEK: always allocate the vector table and all dependent objects */

  //_vectab OsBuildNumber _OsOrtiStackStart _OsOrtiStart

END

STACKSIZE 0x100

VECTOR 0 _Startup /* reset vector: this is the default entry point for a C/C++ application. */

//VECTOR 0 Entry  /* reset vector: this is the default entry point for an Assembly application. */

//INIT Entry      /* for assembly applications: that this is as well the initialization entry point */

2,526 Views
RadekS
NXP Employee
NXP Employee

Hi sathish,

Please use procedure four posts above for modification in your prm file.

EEPROM or P-Flash (marked as ROM for linker) could be used for storage your data.

User data placement depends on your needs however I would like to recommend keeps user segments (which you plan to rewrite by code) aligned with sector size.

More details about linker and prm file could be found in file:

"c:\Freescale\CW MCU v10.6\MCU\Help\PDF\MCU_Build_Tools_Utilities.pdf"


I hope it helps you.

Have a great day,
RadekS

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,526 Views
sathishkannan
Contributor III

Hi ,

Still not able to erase as well as write to flash memory .i shared my code please have a look at this with reference to .prm file

1) i used pragmas for moving code in to ram .correct me if i am wrong.

///////////////////////////////////////////////////////////////////

/* RAM */

      RAM          = READ_WRITE  0x001000 TO 0x001FFF;

/* EEPROM */

      EEPROM        = READ_ONLY  0x100000 TO 0x1003FF;

/* non-paged FLASHs */

      ROM          = READ_ONLY  0xFF0000 TO 0xFFFDFF;

/*  VECTORS      = READ_ONLY    0xFFFE00 TO  0xFFFFFF; intentionally not defined: used for VECTOR commands below */

  //OSVECTORS      = READ_ONLY    0xFFFE10 TO  0xFFFFFF;  /* OSEK interrupt vectors (use your vector.o) */

END

PLACEMENT /* here all predefined and user segments are placed into the SEGMENTS defined above. */

      _PRESTART,              /* Used in HIWARE format: jump to _Startup at the code start */

      STARTUP,                /* startup data structures */

      ROM_VAR,                /* constant variables */

      STRINGS,                /* string literals */

      VIRTUAL_TABLE_SEGMENT,  /* C++ virtual table segment */

    //.ostext,                /* OSEK */

      NON_BANKED,            /* runtime routines which must not be banked */

      DEFAULT_ROM,

      COPY              INTO  ROM;

    //.stackstart,            /* eventually used for OSEK kernel awareness: Main-Stack Start */

      SSTACK,                /* allocate stack first to avoid overwriting variables on overflow */

    //.stackend,              /* eventually used for OSEK kernel awareness: Main-Stack End */

    DEFAULT_RAM        INTO  RAM;

////////////////////////////////////////////////////////////////////////////////////

0 Kudos

2,526 Views
RadekS
NXP Employee
NXP Employee

Hi sathish,

I shortly checked your files.

You didn’t use either Send_Command() or PFLASH_Send_Command() function from example code (from my first reply to this thread).

Send_Command() missing in your code and PFLASH_Send_Command() is commented out.

One of these functions has to be used for trigger flash command (by clearing CCIF flag).

You code just modify FCCOBx registers, but it never starts such flash command.

Please use one of commands (PFLASH_Send_Command(); or asm JSR Send_Command;) in your LLD_FLS_Erase_Verify_Section(),LLD_FLS_Program() and LLD_FLS_Erase_Sector() functions.


I hope it helps you.

Have a great day,
RadekS

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,526 Views
sathishkannan
Contributor III

Hi ,

Thanks alot for pointing out the mistake.

I modified the flash program file as you said .If it has mistake correct me.Which is in bold colour.Why we are using that PFLASH_Send_Command(); function.

Do i need to change anything in main.

//////////////////////////////////////////////////////////

#include <hidef.h>

#include "lld_flash.h"

//or we can use linker pragmas for placing this function into RAM:

#pragma CODE_SEG DEFAULT_RAM

void PFLASH_Send_Command(void)

{

   DisableInterrupts;

   FSTAT_CCIF = 1;           //launch command

   while(FSTAT_CCIF == 0){}; //wait for done

   EnableInterrupts;

}

#pragma CODE_SEG DEFAULT

                                   

//==============================================================================

//LLD_FLS_Erase_Verify_Section

//==============================================================================

u8 LLD_FLS_Erase_Verify_Section(u32 address, u32 number_of_phrases)

{

  //check if address is aligned (global address [2:0] = 000)

  if((address & 0x00000007) != 0)

    return MISALIGNED_ADDRESS;

 

  while(FSTAT_CCIF == 0){};   //wait if command in progress

  FSTAT = 0x30;               //clear ACCERR and PVIOL

 

  FCCOBIX = 0x02;             //we will write command up to FCCOB2

  FCCOB0HI = 0x03;

  FCCOB0LO = ((address & 0x00FF0000)>>16);

 

  FCCOB1 = (address & 0x0000FFFF);

 

  FCCOB2 = number_of_phrases;

 

 

  PFLASH_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;

}

//==============================================================================

//LLD_FLS_Program

//==============================================================================

u8 LLD_FLS_Program(u32 address, u8 *ptr)

{

  u8 i;

 

  //check if address is aligned (global address [2:0] != 000)

  if((address & 0x00000007) != 0)

    return MISALIGNED_ADDRESS;

 

  //check if the phrase is erased   

  if((LLD_FLS_Erase_Verify_Section(address, 1)) == NON_ERASED)

    return NON_ERASED; 

   

  while(FSTAT_CCIF == 0){};   //wait if command in progress

  FSTAT = 0x30;               //clear ACCERR and PVIOL   

 

  FCCOBIX = 0x05;             //we will write command up to FCCOB5

  FCCOB0HI = 0x06;

  FCCOB0LO = ((address & 0x00FF0000)>>16);

 

  FCCOB1 = (address & 0x0000FFFF);

 

  FCCOB2 = ptr[0];

  FCCOB3 = ptr[1];

  FCCOB4 = ptr[2];

  FCCOB5 = ptr[3];

     

PFLASH_Send_Command();

  if((FSTAT & (FSTAT_ACCERR_MASK | FSTAT_FPVIOL_MASK)) != 0)

    return ACCESS_ERROR;

  else   

    return OK;

}

//==============================================================================

//LLD_FLS_Erase_Sector

//==============================================================================

u8 LLD_FLS_Erase_Sector(u32 address)

{

  //size of sector is 512B

 

  //check if address is aligned (global address [2:0] != 000) 

  if((address & 0x00000007) != 0)

    return MISALIGNED_ADDRESS;

   

  while(FSTAT_CCIF == 0){};   //wait if command in progress

  FSTAT = 0x30;               //clear ACCERR and PVIOL

 

  FCCOBIX = 0x01;             //we will write command up to FCCOB1

  FCCOB0HI = 0x0A;

  FCCOB0LO = ((address & 0x00FF0000)>>16);

  

  FCCOB1 = (address & 0x0000FFFF);

 

PFLASH_Send_Command();

 

  if((FSTAT & (FSTAT_ACCERR_MASK | FSTAT_FPVIOL_MASK)) != 0)

    return ACCESS_ERROR;

  else   

    return OK;

}

//==============================================================================

//LLD_FLS_Read_Byte

//==============================================================================

u8 LLD_FLS_Read_Byte(u32 address)

{

  u8 data8;

  data8 = *(u8 *)address;

  return data8;

}

//==============================================================================

//LLD_FLS_Read_Word

//==============================================================================

u32 LLD_FLS_Read_Word(u32 address)

{

  u32 data16;

 

  data16 = *(u32 *)address;

  return data16;

}

//==============================================================================

//LLD_FLS_Init

//==============================================================================

void LLD_FLS_Init(u8 fdiv)

{

  while(FSTAT_CCIF == 0){};   //wait if command in progress 

  FCLKDIV = fdiv;             //osc = ? MHz   

}

0 Kudos

2,526 Views
RadekS
NXP Employee
NXP Employee

Hi sathish,

I am sorry, but I didn’t check your main code.

Please delete these lines in main():

#pragma CODE_SEG DEFAULT_RAM

  DisableInterrupts;

  FSTAT_CCIF = 1;          //launch command

  while(FSTAT_CCIF == 0){}; //wait for done

  EnableInterrupts;

#pragma CODE_SEG DEFAULT

They have no sense here since we didn’t configure FCCOBx registers before that code.

This part of code is called as PFLASH_Send_Command().

We cannot execute code flash block which we currently erase/program. Therefore we just configure flash command, jump to code in RAM (PFLASH_Send_Command()) and start execution of flash command from there. We also waits until flash command finish and return back to code in flash.

Since default vector table and interrupt routines are stored in the same flash block, we should also disable interrupts during execution of flash command. If time critical interrupts has to be executed during flash command, we have to also move vector table and interrupt routines into RAM (in that case we will not disable interrupt during flash command execution).


I hope it helps you.

Have a great day,
RadekS

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,524 Views
sathishkannan
Contributor III

Hi ,

Is it possible to erase and program in a single program ?

0 Kudos