K64 Programming Flash

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

K64 Programming Flash

Jump to solution
2,035 Views
JHinkle
Senior Contributor I

How do you place code in a post?  I tried the "code" block selection in the toolbar "<>" but it just garbles things up.

Let me explain my question.  If someone can tell me how to post code that shows proper format -- I can then include it for clarity.

I have written my own flash programming routines in an attempt to understand the process.

I am using a K64 with NO FlexNVM

If I understand the documentation correctly, you can not execute code from the same flash block you are attempting to program.  I read somewhere that code executing in RAM allows you to program and flash block without a collision error.

I believe the the code that needs to run from ram is code that actually read and writes to FTFE_FSTAT.

I wrote a small function that perform 2 functions based on an argument passed to it.

1.  Read FTFE_FSTAT and check that CCIF is not zero which would indicate active flash operation in progress.  Once set, clear any of the error flags from the last flash operation.  Leave function with only CCIF set.

2.  Enter with FTFE_FSTAT having only CCIF set.  Perform FTFE_FSTAT = FTFE_FSTAT_CCIF_MASK; which should start the flash operation.  Wait until FTFE_FSTAT - CCIF mis set indicating flash operation is complete.  Return FTFE_FSTAT to return any errors that may have occurred.

I acquire 4 byte align space in RAM and copy the function above into that ram space.  I assign a ram pointer to that RAM space cast to be my function.  Now I can just call the function I described above from its ram image.

I have reserved 16 bytes a flash at address 0x410 to hold my MAC address.  When I start, this address range contains all FF's.

I perform the following (I wish I knew how to post code)

FTFE_FCCOB0 = 7; // PGM8
FTFE_FCCOB1 = (byte)(Address >> 16);
FTFE_FCCOB2 = (byte)(Address >> 8);
FTFE_FCCOB3 = (byte)(Address);
FTFE_FCCOB4 = D[0];
FTFE_FCCOB5 = D[1];
FTFE_FCCOB6 = D[2];
FTFE_FCCOB7 = D[3];
FTFE_FCCOB8 = D[4];
FTFE_FCCOB9 = D[5];
FTFE_FCCOBA = D[6];
FTFE_FCCOBB = D[7];

Where Address is 0x410 and array D contains my 6 byte MAC and 2 bytes of FF.

I call my ram function and it return zero indicating a successful write .. BUT ... flash has NOT changed.

I set the Address to 0x414 which violates the 64 bit alignment requirement for phase programming as a test and get a return value indicating ACCERR error which is valid and also indicates my ram function is functioning properly.

This is the Function that is moved from flash into ram .. sorry for the formatting .

byte FlashBased_Perform_Flash_Operation(byte Operation)
{
       hwInterruptsDisable();
        switch(Operation)
         {
               case Flash_Operation_WaitTilReady:
                while(1)
                {
                     if((FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK))
                              break;
                 }

                 FTFE_FSTAT = (FTFE_FSTAT_RDCOLERR_MASK | FTFE_FSTAT_ACCERR_MASK |                               FTFE_FSTAT_FPVIOL_MASK); // clear any errors;

                 hwInterruptsEnable();

                 return (FTFE_FSTAT & ~FTFE_FSTAT_CCIF_MASK);
                 break;

     case Flash_Operation_PerformWrite:
             FTFE_FSTAT = FTFE_FSTAT_CCIF_MASK;  // start flash operation
                while(1)
                 {
                       if((FTFE_FSTAT & FTFE_FSTAT_CCIF_MASK))
                            break;
                   }

                   hwInterruptsEnable();

                   return (FTFE_FSTAT & ~FTFE_FSTAT_CCIF_MASK);
                  break;

          }  // end of switch
}

The process should be simple but I'm not write to flash.

Any comment or suggestions?

Thanks.

Joe

0 Kudos
1 Solution
906 Views
JHinkle
Senior Contributor I

Code is working fine.

I'm using Crossworks for development.

Debug memory view always shows al FF's after a lower flash block write -- even after I ask it to refresh.

As a debugging aid, I copied the contents of the newly flash memory into a ram array and view it -- and it shows it programmed properly so I have a tool issue - not a code issue.

Tools are meant to help you with problems, NOT be the source of problems.

Thanks for all for help and comments -- Now I have a tool issue to resolve.

Joe

View solution in original post

0 Kudos
5 Replies
906 Views
JHinkle
Senior Contributor I

Any help NXP.

Upper flash blocks writes just fine.

Lower flash block does NOT write at all AND does not produce any errors in FTFE_FSTAT

Thanks.

Joe

0 Kudos
907 Views
JHinkle
Senior Contributor I

Code is working fine.

I'm using Crossworks for development.

Debug memory view always shows al FF's after a lower flash block write -- even after I ask it to refresh.

As a debugging aid, I copied the contents of the newly flash memory into a ram array and view it -- and it shows it programmed properly so I have a tool issue - not a code issue.

Tools are meant to help you with problems, NOT be the source of problems.

Thanks for all for help and comments -- Now I have a tool issue to resolve.

Joe

0 Kudos
906 Views
mjbcswitzerland
Specialist V

Joe

You always need to question what debugging tools are doing/showing you - always keep a healthy mistrust relationship and double check when in doubt with a second or third tool.

I always have internal code that can double-check things (like in the menu I used) and simulate to cross-check expected with unexpected (possibly compiler or tool influenced) occurances to avoid unnecessary loss of time when developing.

Regards

Mark

0 Kudos
906 Views
mjbcswitzerland
Specialist V

Joe

To post code you need to :

1. Activate "Use advanced editor" - click the link above right of the input area.

2. Click on the "Expand Toolbar" (...)
3. Now click on the "More" drop-down an select "Syntax highlighter"
4. Choose Language "C" and paste the code into the box.
5. Close the box and continue with normal typing

I didn't see the problem with your code but this is how to do it (I stripped out just for phrase programming):

static int fnProgram(unsigned long *ptrWord, unsigned long *ptr_ulWord)
{
    while ((FTFL_FSTAT & FTFL_STAT_CCIF) == 0) {}                // wait for previous commands to complete

    if ((FTFL_FSTAT & (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL | FTFL_STAT_RDCOLERR)) != 0) { // check for errors in previous command 
        FTFL_FSTAT = (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL | FTFL_STAT_RDCOLERR); // clear old errors
    }

    FTFL_FCCOB0 = FCMD_PROGRAM;                                  // enter the command sequence
    FTFL_FCCOB1 = (unsigned char)(((CAST_POINTER_ARITHMETIC)ptrWord) >> 16); // set address in flash
    FTFL_FCCOB2 = (unsigned char)(((CAST_POINTER_ARITHMETIC)ptrWord) >> 8);
    FTFL_FCCOB3 = (unsigned char)((CAST_POINTER_ARITHMETIC)ptrWord);
    FTFL_FCCOB7_4 = *ptr_ulWord++;                               // enter the long word to be programmed
    FTFL_FCCOBB_8 = *ptr_ulWord;                                 // enter the second long word to be programmed
    uDisable_Interrupt();                                        // protect this region from interrupts
        fnRAM_code((volatile unsigned char *)FLASH_STATUS_REGISTER); // execute the command from SRAM
    uEnable_Interrupt();                                         // safe to accept interrupts again
    return (FTFL_FSTAT & (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL | FTFL_STAT_MGSTAT0)); // if there was an error this will be non-zero
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The only code that needs to be in RAM is this:

static void fnFlashRoutineInRam(volatile unsigned char *ptrFTFL_BLOCK)
{
    *ptrFTFL_BLOCK = FTFL_STAT_CCIF;                                     // launch the command - this clears the FTFL_STAT_CCIF flag (register is FTFL_FSTAT)
    while ((*ptrFTFL_BLOCK & FTFL_STAT_CCIF) == 0) {}                    // wait for the command to terminate
}
‍‍‍‍‍

Attached is the uTasker flash driver which is compatible with long-word and phrase programing of KE, KEA, KL, KV, KM  and K parts, including PROGRAM ONCE (useful for MAC addresses that are programmed once and can't be erased), Flash swap (for K64 for example), FlexData, section programming option and soem other stuff (fail-safe parameter system and mixing external and internal Flash programming into a virtual linear address space).

A simple method to learn Flash programming is to type in these sequences in the debugger (directly accessing the Flash registers and monitoring the memory content). Once you are familiar with the actual writes to do (and possibly ones to avoid) you can then implement in code in the same sequence.

If you want to speed up your learning and progress you can simply download the uTasker project and use its Kinetis simulator (which also emulates all Flash operations) so that you can see how it works and either directly use the solutions (that have been in operation for a number of years in many varied industrial products based on various Kinetis processors) or copy them to build your own library.

Regards

Mark

0 Kudos
906 Views
JHinkle
Senior Contributor I

Mark:

Thanks for your reply.

I moved my test address to the second flash block so I could test my flash based programming function AND the ram version.  Both worked as expected.

I tried writing again to an address in the FIRST flash block and no write occurs.

I know my routines work ... so issue has to be with an interaction with the debugger (JLink) OR my writes to the Lower flash block (where code is running) is blocking it for some reason.

No errors occur during write attempt, just no write.

Thanks.

Joe

0 Kudos