Pages: 1 2 [3]   Go Down
Author Topic: Get program size (flash used) RUNTIME - possible?  (Read 1603 times)
0 Members and 1 Guest are viewing this topic.
Valencia, Spain
Offline Offline
Faraday Member
**
Karma: 146
Posts: 5522
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Yes, but writing to flash (program memory) at runtime isn't really a desirable thing to do. Sure, we can be open about it. But if you do it 10 times a day, and the flash can be written to 10,000 times, your app will fail after 3 years.

And if you write the EEPROM 100 times a day it will fail too.

The idea is to design for that (by minimizing writes, wear-levelling...etc).

Plus, it would be easy, if you enable writing to flash, to corrupt the running program. Do you want that?

There's dozens of other bad things that can happen as well. It doesn't mean we should prohibit people from doing them. I think 'String' is a much worse problem than this.

Logged

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

Worst state in America
Offline Offline
God Member
*****
Karma: 32
Posts: 799
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

This is an interesting thread.

Quote
Don't ask me why... I don't know. I'm just doing what I'm told!

Is that wise?

Not always, but in the case of "professor asks staff to do it a certain way", it is wise to do as told.  smiley
Logged

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

Worst state in America
Offline Offline
God Member
*****
Karma: 32
Posts: 799
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

OK! Should be right now. The new code does the correct math by determining which board it's talking to and then subtracting the flash which is unavailable due to the bootloader!

Also, there is a 256 byte correction for small (i.e. UNO) boards and 512 bytes for large (MEGA 2560 boards). Not sure what the difference is - maybe a larger interrupt vector table? I have no idea.

Anyway, I am sure it's right NOW... so anyone who would be so kind please try it and see if it works for you.

Thanks!

-- Roger

(edit): Fixed the ")" mistake.

* MemoryFree.zip (2.33 KB - downloaded 9 times.)
« Last Edit: November 01, 2012, 07:07:21 pm by Krupski » Logged

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

France
Offline Offline
Edison Member
*
Karma: 38
Posts: 1009
Scientia potentia est.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No still isn't right, not sure for the PROGMEM, but it is obvious for the SRAM.

I tried your code as is, first there is a missing ')' on line 74, then once compiled:
Code:
Binary sketch size: 3 962 bytes (of a 258 048 byte maximum)
Estimated used SRAM memory: 733 bytes (of a 8192 byte maximum)
Code:
Free SRAM: 7440 bytes
Free PROGMEM: 249938 bytes

Then I added a big array to fill the SRAM:
Code:
char a[7458]; //8192 - 733 - 1
void setup(void)
{
        a[0] = 0;
        //...rest of your code here
Code:
Binary sketch size: 3 966 bytes (of a 258 048 byte maximum)
Estimated used SRAM memory: 8 191 bytes (of a 8192 byte maximum)
Code:
Free SRAM: 15853 bytes
Free PROGMEM: 249934 bytes

I will try to fill the PROGMEM just to see smiley

Edit: I can't test, apparently filling the PROGMEM is a bad thing because the program doesn't ouput anything to serial once uploaded :/. Also I can fill max 134828 of the 258048 bytes available :/

By the way, where do you get your estimated values from?  Does the Arduino IDE have that option, or are you using something else?

I am using the Arduino Enhanced IDE smiley
« Last Edit: November 01, 2012, 05:56:32 pm by guix » Logged

Worst state in America
Offline Offline
God Member
*****
Karma: 32
Posts: 799
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I tried your code as is, first there is a missing ')' on line 74, then once compiled:

VERY strange. I just downloaded my own upload and tested it here... it compiles perfectly.

Here's what I get when I run the code here:

UNO R3 board:
Free SRAM: 1800 bytes
Free PROGMEM: 29634 bytes



MEGA2560 (with a 2K bootloader):
Free SRAM: 7440 bytes
Free PROGMEM: 249906 bytes



(by the way, found the error you were mentioning... a missing right parentheses - in MemoryFree.cpp):
this: return (FLASHEND - 8191 - SketchSize();
should be this: return (FLASHEND - 8191) - SketchSize();


OK... for the MEGA 2560, my IDE (version 1.0.1) says the sketch is 4,046 bytes. The MEGA has 242144 bytes minus 8K for the bootloader is 253952 bytes. Subtract 4046 from that (the sketch size) and you get 249906 bytes which is what the code reports.

Of course, *MY* mega board has a 2K bootloader instead of an 8K bootloader and in reality I have 6K more free, but the MemoryFree code doesn't know that (as expected).

I'll try to stuff a lot of PROGMEM into the MEGA and see how much works!
Logged

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

Dallas, TX USA
Online Online
Faraday Member
**
Karma: 67
Posts: 2705
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Instead of thinking all the things you shouldn't do and 'just saying no', what about the things reasonable that may deserve a 'yes'? An open approach instead of closed?

Yes, but writing to flash (program memory) at runtime isn't really a desirable thing to do. Sure, we can be open about it. But if you do it 10 times a day, and the flash can be written to 10,000 times, your app will fail after 3 years.
It might be. There are some legitimate uses to overwrite the running code in flash.

With respect to the number of writes, it depends on where the write(s) is done.
The 10,000 times is per page. If you are updating the flash with a minimal
change it will potentially only impact a single page. Since there are many pages in flash the actual number
of writes could be much higher than 10,000 times if the writes are being done on different pages.

Quote
Plus, it would be easy, if you enable writing to flash, to corrupt the running program. Do you want that?
I could think of reason to want to do this: Debugging.
Suppose you want to run gdb for source level debugging and insert a break point.
The way to do this is to "corrupt" the running code with a new bit of code where you
want the breakpoint to be.
The Atmel ICE products do this by "corrupting" (overwriting) the existing code
with a BREAK instruction. They read the appropriate flash page
and re-write the page with the BREAK instruction inserted in the correct place.

It is possible to do the same (overwrite code with a special instruction)
without an ICE in the code itself to allow gdb to talk to through the serial port on the AVR by
using a similar approach. You can't use the BREAK instruction because that is reserved by ATMEL when
the OCDEN fuse enables 1 wire debugging (debugwire).
You can do it through a cleaver use of an instruction to trigger a hardware interrupt
(INT0 is best to gain full control) to cause a trap into an ISR.
From there the code can take over and talk out the serial port and eventually
back to gdb to transfer all the relevant information using gdbmon messages.
Yes it is a bit tricky and it does require the ability to overwrite flash pages
but it allows using the AVR serial port for source level debugging.
It also requires a custom version of gdb to modify the "breakpoint" instruction
to the needed instruction opcode to trigger the interrupt because currently the opcode
for the "breakpoint" instruction is hard coded into gdb as BREAK and BREAK
can't be used since it only works for debugwire.

--- bill
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4808
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Or perhaps I might make a generic combo PDA and electronic key that a user would enter personal data that won't change any time soon. It might have certain code and data but also have room for more without overwriting anything but empty space. I could do that now if my users were expected to load the device from a PC/ISP but maybe I'd rather not have them do that for whatever reason.
It's hard to say before the app is thought of except yo, I'd like the freedom to do that.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Dallas, TX USA
Online Online
Faraday Member
**
Karma: 67
Posts: 2705
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A real-world application that I've tossed around is a serial glcd backpack.
glcd fonts and bitmaps can be quite large and as such are stored in flash.
In a backpack product, it might be useful to provide a way to
update/modify a font or a bitmap splash image.
For that usage case it might be nice to be able to reserve areas in flash
for font/bitmap storage that can be updated and overwritten using the serial communication
interface.

So in this usage case it really isn't updating "code" but rather an area of the flash that is
reserved for data that can be modified because eeprom is not large enough.
And if that area starts right after the end of the real code vs a hard coded location,
knowing where the code ends becomes quite useful.
Even if the data starts high and starts to move down towards the code, knowing how much
room is available is needed to determine how space is available for data storage.

--- bill
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4808
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You could PROGMEM the initial data and use a pre-set pointer to tell where it is.

Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Pages: 1 2 [3]   Go Up
Jump to: