Writing core firmware to external flash

Hello all.

I have a code of size 105944 bytes which is to be written to the core.From the memory mapping of spark core,108kb of core firmware is the maximum limit that can be written to the internal flash,But I need to add some code for other hardware devices which is to be interfaced with the core and hence the code size is going to exceed 108Kb.Is to possible to write the core firmware to the unused 1.5 Mb of external flash memory? I am basically looking for methods to reduce the size of the code.

Thank you for your time.

I fear this is not possible :cry:

Since the external flash is accessed via SPI but the processor needs to access the code direct (32bit parallel) this wonā€™t work.

You may have to wait for the Photon to give your firmware a new home :wink:

But - as Iā€™m not one to stop thinking outside the norm :stuck_out_tongue_winking_eye: - there might be a (very hypothetic) hardCore hackaround.
If the STM32F (which I donā€™t know enough) does allow it (which I donā€™t know either) and you can cleanly isolate some functions of your code, you may be able to perform some sort of code paging.
You store the compiled code of - seldomly needed - functions into external flash. When needed, you could load these functions into RAM and then execute the function in RAM.
The best chance for this to work youā€™d have with hand tailored machine code which does not need to call any other function, since it will most likely have no knowledge about the correct references to these functions to call them (unless you pass in the refernces as parameters).

I hope the Elites and Sparkies donā€™t think Iā€™m completely bonkers now, but maybe they could chime in - even only for proving me loony :moon: :wink:

That sure does sound interesting at the very least. Iā€™m unfortunately not capable enough to say whether or not that might work.
I would recommend posting your full code here, to see if there are any optimizations to be gained. In comparison with the Arduino Uno, the Spark has a lot more memory, and should suffice for most projects. Perhaps youā€™ve overlooked something thatā€™s clogging up your memory.
That ā€˜problemā€™ will also be solved with the arrival of the Photon :wink:

Running code from the external flash isnā€™t straightforward unfortunately as @ScruffR outlined.

If you compile locally you can remove unused portions of the firmware to save a few K.

If you donā€™t need the cloud connection, itā€™s also possible to remove the cloud connectivity to free up some 30K. You still have wifi and tcp.

Finally, use arm-none-eabi-nm to analyse the .elf file to see where the space is going. You may be able to rewrite your code to be more optimal.

Also note that the maximum size is 108KiB - thatā€™s 110592 bytes, so you have some 5000 bytes left - thatā€™s quite a lot of code. I would just write what you need and then optimize if you run out of room.

2 Likes

@ScruffR - youā€™re not bonkers, this is potentially workable, given enough effort. You donā€™t even need hand-tailred machine code - the compiler has a flag ā€œ-pieā€ which produces a position-independent executable. In principle, this means you store these functions in external flash and load them into RAM for execution.

Each function call would essentially be stubbed to load the appropriate function in ram, and when the function returns, return the previous contents.

Possible, but no walk in the park! :worried:

And as I said previously, this could be a case of premature optimization. :smile:

1 Like

Have you got much debugging code? I stripped all mine out and reduced all the serial prints I needed to codes and saved a good 40kb. Next step as I now need even more space is to use @kennethlimcp usd fram card to store the sounds and menu options for the serial programming

1 Like

Also, avoiding sprintf() will save 20Kb of code also :smile:

Thank you @ScruffR @Moors7 @mdma @Hootie81 @peekay123

@mdma
I am analyzing the .elf file using the above said command.I can see a 8 digit hexadecimal number and I guess it corresponds to a location in the internal flash memory.The third column contains symbols like ā€˜Dā€™,ā€˜dā€™,ā€˜Tā€™,ā€˜Bā€™,ā€˜Wā€™.What do these symbols indicate?

From the elf file i see this line
200018a3 00000001 B SPARK_FLASH_UPDATE

So if i dont want to update the core firmware over the cloud,I can remove this functionality isnt it?
I think this function is present in spark_utilities.cpp.
What are the other ways to remove the cloud connectivity?

Thanks

I donā€™t know enough about the elf file but I wouldnā€™t change it directly. Optimizing your code would be the easiest way Iā€™m sure. Stripping libraries back to bare minimum and reusing as much code as possible.

What libraries are you using and whatā€™s causing the compiled code to be so big?

I am using Adafruit_mfGFX,Adafruit SSD1351,I2Cdev,MPU6050 and SD library.I tried trimming out the libraries but most functions in it are being used.How can I reduce it further? I found the functions being used from the .elf file.

Also I noticed that removing large comments reduces the code size when compiled locally but does not affect the code size when compiled in the IDE.Why is it so?

@adithyalobo, removing comments should not have ANY effect on code size! Can you elaborate on what you are removing and the code size differences regardless of where itā€™s compiled!

As for library reductions, mfGFX may be the biggest space user if you are using several fonts. By default, the GLCDFONT is included and I realize I should have thought about that a little more (eg. if GLCDFONT is not to be included, another font should be the default).

1 Like

If you really donā€™t need the cloud at all (not just the OTA update, but variables, functions etcā€¦) thereā€™s an experimental branch at https://github.com/spark/firmware/tree/feature/hal-no-cloud that compiles without cloud support.

You build using the command line, and add SPARK_CLOUD=n. This will reduce the binary size by some 40k. Please keep in mind that this is experimental, and the branch might not be around forever, but might help you solve your size problem in the short term, or until the Photon is available! :smile:

I also have that size problem and tried to use the above hal-no-cloud version.
I can compile it, but it has a totally different design, so now I have to learn anew how to use libraries and how to add my own application.

In my old build environment (I donā€™t know which version it was, where can I see it?), I could add ā€œAPP=Helloā€ to show the build which application to build. This seems to be not working with this build.

I even donā€™t know where is the actual application.cpp and which makefile is the right one to use? Is it the one in the root dir, or the one in the main dir (i think that).

Or maybe the SPARK_CLOUD=n switch is even in the main version now? I am lost, I donā€™t know what to use.

Thanks for help
Thorsten

@Bluescreen, Iā€™ll take a look later and get back to you unless @mdma beats me to it :smile:

@Bluescreen, your app needs to go under the ā€œmainā€ directory and can be compiled with ā€œAPP=appnameā€. Look at the way the tinker application is done to give you some guidance. The SPARK_CLOUD=n switch only exists in this branch of the master. :smile:

Ok, I now find the time to try and it works. But there is a strange behaviour of the WiFi Class. If I print out the IP adress of the Core like this:

str->print( "IP Address: "); str->println(WiFi.localIP());
str->print( "Subnetmask: "); str->println(WiFi.subnetMask());
str->print( "Gateway   : "); str->println(WiFi.gatewayIP());

I get the adresses in the wrong order. If my IP is 192.168.42.53 I get this output:

IP Address: 53.42.168.192
Subnetmask: 0.255.255.255
Gateway : 1.42.168.192

If I compile using the standard master branch everything is ok. It has nothing to with the SPARC_CLOUD=n setting, itā€™s wrong if I use either setting. Maybe itā€™s some thing with the platform stuff and itā€™s endian settings.

@peekay123 Avoiding sprintf() will save 20KB of code? Well, I did a quick test. I compiled the ā€œled_blinkā€ example in the Particle IDE. The output BIN file size: 77,360 bytes. I added the following lines (grabbed from an example):

char publishString[100];
sprintf(publishString,"{ā€œmVā€: %i}",12456);

After rebuilding the project (yes, I saved the INO file first ;-)), the BIN file size is 77,456 bytes, or only 96 bytes more. Is there really a way to save 20KB by not referencing sprintf? Or is the entire sprintf library getting automatically included in the build, and not optimized out?

@WebDust21, it cannot be analysized from the .bin file size but more of the output.

eg.

1 Like

@kennethlimcp : Not meaning to hijack this thread at all, but where is that compiler output displayed ? Iā€™ve been using the Web IDE and before the change from spark to particle it was displaying every time - these days it seems to have vanished.

The introduction of photon firmware compiling in the :cloud: somehow ended with this feature not existing.