Flash Write with FreeRTos

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

Flash Write with FreeRTos

4,898 Views
pietrodicastri
Senior Contributor II

Good morning

I am trying to write in the flash from inside a FreeRtos task. It craches miserabily.

Is there a known reason for ?

Thank You

 

Pietro

0 Kudos
16 Replies

4,890 Views
myke_predko
Senior Contributor III

Hey @pietrodicastri 

We've had some discussions on this recently (before this community site change).  

As noted, what part are you working with, what is the software/SDK and are you disabling interrupts before the write?  

myke

0 Kudos

4,706 Views
pietrodicastri
Senior Contributor II

Hei

I have been using the SDK for the flash writing and it is working. 

I have no wish to dig into the why the other library working on the K64 is not working here. 

I can erase all the flash application area and write in chunks of arbitrary size.

The FreeRtos is giving now different problems but not during the writing of the flash.

Thank You for the support

 

Pietro

0 Kudos

4,878 Views
pietrodicastri
Senior Contributor II

Just to clarify the previous. When I say try to write I mean write in the flash.

And more I write a chunk of 1KB of data. After the crash the data are written. 

From the task list in the debugger the other two tasks are still there but not the console task. 

With the debugger I try to write several time in the flash, stepping in the code. It is successful.

 

Thank You

Pietro

0 Kudos

4,846 Views
myke_predko
Senior Contributor III

@pietrodicastri ,

There's a big clue that you can single step through and not run freely.  

Can I suggest that you do some reading on how Flash works?  Writes to Flash do not work at an arbitrary number of bytes, they work at the sector level - you keep saying that you're writing 1kB of data, but it really doesn't work that way (unless the block size of the device you're working is 1k AND you are writing on a sector boundary).  If the address and data size you're writing to over a sector boundary, then you're going to have to write two sectors.  

I believe the SDK APIs accounts for this, but I have found it best to be meticulous about writing to one sector at a time (at the start of the sector).  Here is the method I use for writing to a sector of Flash:

uint32_t flashSectorEraseWrite(uint32_t sector
                             , uint32_t* source) {
uint32_t returnValue = FLASH_RESPONSE_NOERROR;
status_t status;


  __disable_irq();

  if (kStatus_FLASH_Success != (status = FLASH_Erase(&s_flashDriver
                                                   , sector
                                                   , FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE
                                                   , kFTFx_ApiEraseKey))) {
#if (2 != SDK_DEBUGCONSOLE)
    PRINTF("\nFLASH_Erase returned %i"
         , status);
#endif
    returnValue = FLASH_RESPONSE_WRITEFAILURE;
  }
  __enable_irq();

  if (FLASH_RESPONSE_NOERROR == returnValue) {
    __disable_irq();
    if (kStatus_FLASH_Success != (status = FLASH_Program(&s_flashDriver
                                                       , sector
                                                       , (uint8_t*)source
                                                       , FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE))) {
#if (2 != SDK_DEBUGCONSOLE)
      PRINTF("\nFLASH_Program returned %i"
           , status);
#endif
      returnValue = FLASH_RESPONSE_WRITEFAILURE;
    }
    __enable_irq();
  }

  return returnValue;

}

myke

0 Kudos

4,844 Views
pietrodicastri
Senior Contributor II

Hi mykepredkomimet

Thank You for the suggestion.

The driver for writing the flash is already running without problems on another bootloader using the serial port. The driver needs to be feeded byte by byte, and the data are processed and written. I will give more detail. I send to the target the hex file with the console ( TERATERM ), the driver will interpret real time the hex file byte by byte will produce the binary data and when it is time to write will do in chunks of 1KB. A double buffer is using for this action so the buffer is written while the other is in use.

Since I cannot afford to erase incrementally the sectors I delete all the application area in advance. Once the erasing is complete I can write the data with the granularity I want. The incremental writing is not allowed on the kinetis and it is respected.

I can well say I can trust the driver. It is working fine. The problem is the context of the RTOS. It does not like to be intruded with the flash writing. 

If You have time to share this experience I can attach the source code. 

Thank You

Let me know

Pietro

0 Kudos

4,812 Views
myke_predko
Senior Contributor III

@pietrodicastri ,

Please post your source code - I can take a quick look at it.  

Just to be clear you:

  1. Erase the Sector
  2. Perform Multiple writes to the Sector

I'm not sure that's going to work - I've had problems do that, which is why I:

  1. Copy the existing contents of the sector into a buffer
  2. Make the changes in the sector in the buffer
  3. Call the Erase/Write method (that I shared with you above)

I would prefer to do writes withou the erase, but that doesn't seem to work.  

Could you try doing the writes the way I suggest and see if that works?  I know it probably won't be optimal in terms of speed, but it could give you a clue as to how to get your application running as you would like it to.

myke

0 Kudos

4,792 Views
pietrodicastri
Senior Contributor II

Hi mykepredkomimet

I attach definitely the project.

in the main.c All the freertos resources are created. The vAConsoleTask() has some lines of code to test the writing in the flash. These lines are not part of the application in itself are there for testing. 

If the code is executed stepping with the debugger it works. If it is free to run the task will crash.

the console is called in this task as run_cmd();

If the bootloader is activated in the console the hex_is_download_active() will give true and the incoming bytes are read with the 

if ( xQueueReceive( xQueueRx, &buf, ( TickType_t )40000 ) == pdPASS )
{
    hex_get_data( buf );
}

The hex_get_data( ) will process each byte from the hex file, until the writing in flash. All the infrastructure is working correctly in another bootloader without the ROTS. 

It is several years now the bootloader is running with this solution. I do not read any problem in deleting all the flash and writing in chuncks of arbitrary ( but limited by the buffer ram ) length. The only limitation is not to write two times to the same address, not cumulative writes are admitted in Kinetis.

The linkker script is tailored for the TWR100 kit, with the TWR SER board

If You can test just connect the USB as a com with the bit rate You want.

from the console type DLOAD APP .

This will delete all the APP AREA flash and will begin to liste all of the bytes. From TeraTerm drop or send the HEX file and the bootload begins.

I remark all of this is already working so I trust the console. I am quite sure the problem is the compliance with the RTOS.

I am extremely grateful for your interest and help.

Be blessed.

Thank You

Pietro

 

 

0 Kudos

4,785 Views
myke_predko
Senior Contributor III

Hi @pietrodicastri ,

Going through the code, I have one big question/comment:

Why aren't you using the SDK for your FlashInit method?  I'm going to have to take your word for it that it works (I'm not going to read through it and confirm it). 

Now, when I read through things, it looks like from hex_proc.c and the hex_get_data method, you're calling hex_write_bin (which is also in (hex_proc.c) which ends up calling hex_write_index (also in hex_procs.c) and that calls flash_ops_write_fast (which is in flash_ops.c) which then calls FlashProgramSection (in FlashProgramSection.c).  

When I look through FlashProgramSection, I don't see:

  1. Interrupts being disabled.  
  2. No erase of the Flash before writing.  

Please confirm that my admittedly high level search is correct, but I have to go back to my original assertion that when writing to Flash you have to disable interrupts and erase the sector you're going to write to first.  

I'm not really sure why the code works with stepping through, but based on my experience you're not writing to the Flash correctly.  My recommendation to you is to look at the pflash example code and copy the APIs into your code and try it your application again.  

Sorry, maybe I'm really off base, but I don't see what I expect in the code.  Please point to me where I'm wrong.  

myke

0 Kudos

4,773 Views
pietrodicastri
Senior Contributor II

Hi mykepredkomimet

I mentioned previously the flash address range of the application area is deleted totally in advance. 

After the deleting I write the decoded data from the incoming hex file. The data are coming too much fast to delete incrementally the sector. This system is already tested and running since years on another application using the physical serial port. I do not see any problem in this. In The manual I did not see contraddiction in this way of using the flash. And it is working. The bootloader was written long time ago and the SDK was not tailored for the flash operations. I used this support library that works perfectly. The interrupts are tested to be enabled or disabled during the operation but the crash happens anyway. In the moment are incidentally disabled, but I did this test.

The level of attention is not the flash writing, but the FreeRtos integration does not welcome this operation. If You have a working example of flash writing inside a FreeRtos task let me have it. 

Thank You

 

Pietro

0 Kudos

4,768 Views
myke_predko
Senior Contributor III

Hi @pietrodicastri ,

Thank you for the explanation of the code.  

What I shared with you above works fine in FreeRTOS, it's the code that I use in my application to write to the Flash. 

Now, Flash Write that I use is in its own task to avoid reentrency issues - that leads me to the question, could your write code be called repeatedly by an other task while it is still doing a write from a first task?   In a previous post you noted that the initating the write is:

if ( xQueueReceive( xQueueRx, &buf, ( TickType_t )40000 ) == pdPASS )
{
    hex_get_data( buf );
}

Could you be calling "hex_get_data" repeatedly before the write has completed?  

myke

0 Kudos

4,751 Views
myke_predko
Senior Contributor III

Hey @pietrodicastri 

Same question as above, do you disable interrupts during write operations?  

Here is my code for reading and writing a sector:

uint32_t flashSectorEraseWrite(uint32_t sector
                                                 , uint32_t* source) {
uint32_t returnValue = FLASH_RESPONSE_NOERROR;
status_t status;


  __disable_irq();

  if (kStatus_FLASH_Success != (status = FLASH_Erase(&s_flashDriver
                                                                                            , sector
                                                                                            , FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE
                                                                                            , kFTFx_ApiEraseKey))) {
#if (2 != SDK_DEBUGCONSOLE)
    PRINTF("\nFLASH_Erase returned %i"
                , status);
#endif
    returnValue = FLASH_RESPONSE_WRITEFAILURE;
  }
  __enable_irq();
  if (FLASH_RESPONSE_NOERROR == returnValue) {
    __disable_irq();
    if (kStatus_FLASH_Success != (status = FLASH_Program(&s_flashDriver
                                                                                                  , sector
                                                                                                  , (uint8_t*)source
                                                                                                  , FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE))) {
#if (2 != SDK_DEBUGCONSOLE)
      PRINTF("\nFLASH_Program returned %i"
                  , status);
#endif
      returnValue = FLASH_RESPONSE_WRITEFAILURE;
    }
    __enable_irq();
  }

  return returnValue;

}

Note that before doing any writing to Flash, you must:

  1. Disable interrupts
  2. Erase the sector of the Flash you're writing to first
    • This means that I keep a buffer with what I want for the entire sector
    • It doesn't make sense that you have to erase the sector first (you should be able to write zero's to the various Flash bits rather than erase (set to one's) the Flash sector, but there you go.  

myke

0 Kudos

4,728 Views
pietrodicastri
Senior Contributor II

Thank You 

for all support. I am still fighting for a solution. I am in the middle of different works so I cannot be continuous. I will try today to use the SDK as is in the actual revision.

Thank you

 

Pietro

 

0 Kudos

4,726 Views
myke_predko
Senior Contributor III

Hi @pietrodicastri ,

Could you outline how you architecting your code?  

I think I'm doing something similar to you (receiving packets 1 to 48 bytes at a time, buffering them until either a) the "file" is finished b) the code block I'm writing to do do a firmware Block 0 swap is finished or c) the link is lost, at which point I wait 5 seconds and if nothing more is coming I reset the buffer and mark any written sectors as "invalid").  The data can come from one or another source (BT or USB), but I do NOT allow both sources to write to the Flash simultaneously.  The application is running FreeRTOS.  

I still suspect your problem is in not erasing the sector you're going to write to.  I'm not sure why it works for single stepping, but I know it doesn't work when running freely.  

myke

0 Kudos

4,880 Views
pietrodicastri
Senior Contributor II

Good morning

Thank you for the attention.

I am using the TWR-K60F100M kit with the TWR SER . I have the example from the SDK for having the MSD  and the CDC. I want to use for now the CDC for bootloading as a serial port.

I have modified the example. I have two separate tasks for sending and receiving the bytes from and to the serial CDC, and another task for the console. The incoming bytes are written ina queue, the outgoing bytes are written in another queue. The console works fine. 

When I try to write in the console task it does not work. The task is terminated iwth a hard fault.

If I try to step with the debugger everything works. The flask is written correctly. 

Every help is welcome. I can dump here the project.

Thank You

0 Kudos

4,895 Views
Fabian_R
NXP TechSupport
NXP TechSupport

Hello Pietro,

Could you give me more information about the NXP product you are using and a bit more elaborate explanation on the issue?

Regards,

Fabian

Best Regards,
Fabian
0 Kudos

4,850 Views
pietrodicastri
Senior Contributor II

Hei

Are You going to share this experience???

I do not find a light myself

Thank You

Pietro

0 Kudos