cancel
Showing results for 
Search instead for 
Did you mean: 

How to control CubeProgrammer with External Loader?

Southbranch
Senior

Hi!

I am designing a custom external loader for a OCTO SPI HyperFlash with a page size of 512 bytes. I have most things in place but still struggles with the way CubeProgrammer seems to be calling the Write() function..

 

More specifically CubePogrammer:

1. Does not pack data in a full page size when programming smaller loads

For load sizes bigger than 64 bytes but less than a page size, CubeProgrammer always calls Write() twice. Why is this? In such case the second call always seems to have a size even divisible by 32. As an example, programming 84 bytes will result in a first and second call to Write() having 52 and 32 bytes sizes respectively. There is a similar effect also when writing bigger data sizes.

Unfortunately, this is a problem for me since the memory I am using does not allow writing data two loads in an address sequence unless the first write ends with an address even divisible with 32 bytes. By other words, the opposite to how CubeProgrammer works.

 

2. Sometimes calls Write() with half pages for larger loads

Without any obvious reason, CubeProgrammer sometimes starts writing half pages of 128 bytes instead of full 512 byte pages resulting in undesirable performance. Why is this?

 

-Please, is there a way to control and change the above behaviour of CubeProgrammer?

-Any settings that could be used in Dev_Inf?

Many thanks in advance

5 REPLIES 5

It's a bit of a black-box.

Can't say I've seen it make super small split transactions, is this from a .HEX file? .ELF at least are typically going to have quite large sections.

Write() is expected to deal with the parameters passed, and with any limitations / expectations of the device. Ideally Cube Programmer should be as minimally involved as possible. Having some minimal alignment seems reasonable given the width of flash lines both for ST's own devices internally, but for others.

You might have to de-block.

I would define the sector size quite large, no particular reason for it to be 256-bytes if the loader handles de-blocking. The small size just chokes performance.

@Nawres GHARBI @Aziz BRIGUI 

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

 

Thanks for your prompt reply

So far I have just tried to program test data files so neither using .HEX or .ELF. The loader itself is renamed from an .ELF to .STLDR but seems big (~ 2.5 MB) compared to other loaders. I am not sure if this could cause any negative effects but it takes up less than 25% of RAM_D1 in the H7-device I am using.

I am not sure if I understood what you meant by "de-block", are you saying stating “wrong” params such a sector sizes etc could be a trick? Could you please elaborate?

I am using the below params in Dev_Info.c

/* This structure containes information used by ST-LINK Utility to program and erase the device */
#if defined (__ICCARM__)
__root struct StorageInfo const StorageInfo  =  {
#else
				//struct StorageInfo const StorageInfo  = {
				struct StorageInfo __attribute__((section(".Dev_info"))) /*const*/ StorageInfo  = {
#endif
				"MyLoader", 		 					            // Device Name
				NOR_FLASH,                   			            // Device Type
				0x70000000,              			                // Device Start Address
				0x04000000,   						                // Device Size in bytes 64MB
				0x200,                            	                // Programming Page Size
				0xFF,                       					    // Initial Content of Erased Memory
				// Specify Size and Address of Sectors (view example below)
				{{
				  0x00000200, 0x00020000 },
				{ 0x00000000, 0x00000000 }}
		};

 

De-Blocking is a term I'd use in a Block Storage / File System context with dealing with the disparity of random user requests (small, spanning, amongst others) and the properties of the memory, block sizes, erase block sizes, etc.

You're expected to serve ALL requests, say writing two bytes that span two 128KB erase blocks, where you have to stage the data already on the device and erasing and writing the new/updated content without data loss..

I'm saying you could tell it you want 4K or 64KB pages, and deal with what it gives you, you have to either way.

If you have to address too-small transaction you might have to cache and write later. Although obviously it would be preferable that the tool works better, I've spent years getting nowhere on getting any of this addressed properly or optimized.

ST are impossible to deal with at this level, and I'm sick of working for nothing..

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

Thanks for clarifying.

However, the problem is not only for small data loads and here is an example:

Write() is called with X number of 512 bytes chunks and then for some reason the last two calls are sized 476 and 416 bytes. This will result in a programming fault of the last chunk since the previous chunk of 476 bytes is not even divisible with 32. A reversed order call with 416 and 476 would have worked or even better of course, if the calls would have been 512 and 380 bytes.

As you pointed out, I am considering using caching somehow but feel I need to fully understand how this tool work.

You have been helpful as always, thank you!

I will try to contact ST-support for a comment

Southbranch
Senior

Dear ST,

In a summary, I am struggling with these things in CubeProgrammer:

  1.  As the example above, last data chunk sent to Write() are often split up in two calls with each having smaller sizes rather than first filling-up a full page and then making a final call with a small chunk.
  2. Successive calls to Write() are sometimes done in half pages rather than full pages.
  3. Erase() are only called once for the first sector erase even though a flashing may span over mutiple sectors.

Some things might by solved by caching, but before jumping in to that, is this the normal behaviour for CubeProgrammer and is there any documentation available around how Write() and Erase() are called??

In addition I received this comment from Infineon regarding their OSPIs I am using:

Future silicon process generations of HYPERFLASH™ may no longer support multiple program operations, within the same half-page, without an erase operation on the sector containing the half-page. Planning for software migration to future generations should adopt data structures and data management methods that can support only one programming operation, per half-page, per erase.”

 

Please help me out to clarify!