[Patch] Replacing boolean flag variables with bit field
[Patch] Replacing boolean flag variables with bit field
The Multiwii firmware is riddled with a lot of boolean flag variables,
each needing one byte of RAM. Since memory is a scarce ressource, this
commit groups all (most) of these variables into a single bit array that
it accessed through the convinience functions get_flag/set_flag. Instead
of defining new variables, please just ammend the enum mwc_flags; the
array size is adapted automatically.
Any ideas about this change? Works fine for me and hould be easily extendable:
https://github.com/wertarbyte/multiwii- ... 02c08279ae
Hint: I originally wanted to add the enumeration to MultiWii.ino, but it breaks the build process for me since function prototypes are inserted before the enum definition :-/
each needing one byte of RAM. Since memory is a scarce ressource, this
commit groups all (most) of these variables into a single bit array that
it accessed through the convinience functions get_flag/set_flag. Instead
of defining new variables, please just ammend the enum mwc_flags; the
array size is adapted automatically.
Any ideas about this change? Works fine for me and hould be easily extendable:
https://github.com/wertarbyte/multiwii- ... 02c08279ae
Hint: I originally wanted to add the enumeration to MultiWii.ino, but it breaks the build process for me since function prototypes are inserted before the enum definition :-/
Re: [Patch] Replacing boolean flag variables with bit field
I made a few additional patches to reduce the memory (both RAM and ROM) footprint:
Omit servo variables unless needed: https://github.com/wertarbyte/multiwii- ... 5b4bfaaaeb
Shrink rcalue array for standard receivers: https://github.com/wertarbyte/multiwii- ... 7dc0c8b08d
make Buzzer optional: https://github.com/wertarbyte/multiwii- ... 2b77fb0309
Feel free to discuss
Omit servo variables unless needed: https://github.com/wertarbyte/multiwii- ... 5b4bfaaaeb
Shrink rcalue array for standard receivers: https://github.com/wertarbyte/multiwii- ... 7dc0c8b08d
make Buzzer optional: https://github.com/wertarbyte/multiwii- ... 2b77fb0309
Feel free to discuss
Re: [Patch] Replacing boolean flag variables with bit field
Hi Tommie,
Nice!
i dont really know how flags work .. but that sounds good. maybe you can explain why this uses less RAM & ROM and how it works?
regards Felix
Nice!
i dont really know how flags work .. but that sounds good. maybe you can explain why this uses less RAM & ROM and how it works?
regards Felix
Re: [Patch] Replacing boolean flag variables with bit field
ronco wrote:i dont really know how flags work .. but that sounds good. maybe you can explain why this uses less RAM & ROM and how it works?
It preserves RAM because having a uint8_t in memory will require a complete byte, even if you are only using one bit of it (like a boolean flag, 1/0). By using a bitmask (flag_mask[]), we can aggregate eight boolean variables into a single byte and assign one bit for each.
At the moment, 16 former flag variables are combined into the bit field; instead of requiring 16 uint8_t variables and wasting 16 Byte, these flags now only afford two bytes; if additional variables are added, the code automatically increases the size of the byte array used:
Code: Select all
enum mwc_flag {
FLAG_OK_TO_ARM,
FLAG_ARMED,
FLAG_I2C_INIT_DONE,
FLAG_ACC_CALIBRATED,
FLAG_NUNCHUKDATA,
FLAG_ACC_MODE,
FLAG_MAG_MODE,
FLAG_BARO_MODE,
FLAG_GPS_HOME_MODE,
FLAG_GPS_HOLD_MODE,
FLAG_HEADFREE_MODE,
FLAG_PASSTHRU_MODE,
FLAG_GPS_FIX,
FLAG_GPS_FIX_HOME,
FLAG_SMALL_ANGLES_25,
FLAG_CALIBRATE_MAG,
FLAG_CNT
};
...
/* bitmask for all the flags specified in def.h */
uint8_t flag_mask[FLAG_CNT+7 / 8] = {0};
Re: [Patch] Replacing boolean flag variables with bit field
Already commented on that
-
- Posts: 1630
- Joined: Wed Jan 19, 2011 9:07 pm
Re: [Patch] Replacing boolean flag variables with bit field
Hi,
So around 16 bytes saved in RAM, but what is the trade off with flash size ?
So around 16 bytes saved in RAM, but what is the trade off with flash size ?
Re: [Patch] Replacing boolean flag variables with bit field
Don't know, but acceptable. If you exceed flash size, you notive while flashing. If your stack crashes into your heap, you only notice when your ISRs are trashed and the copter takes off to location unknown. Luckily, I was able to grab it before it could deal some real damage.
Therefore, SRAM is far more important than flash size. My firmware is now at 27064 byte, including GPS, Sonar, MAG, some larger custom stuff (data transfer framework), LED flashers, landing lights and the new descriptive strings for PIDITEMS and BOXITEMS.
Therefore, SRAM is far more important than flash size. My firmware is now at 27064 byte, including GPS, Sonar, MAG, some larger custom stuff (data transfer framework), LED flashers, landing lights and the new descriptive strings for PIDITEMS and BOXITEMS.
Re: [Patch] Replacing boolean flag variables with bit field
Tommie wrote:Don't know, but acceptable. If you exceed flash size, you notive while flashing. If your stack crashes into your heap, you only notice when your ISRs are trashed and the copter takes off to location unknown. Luckily, I was able to grab it before it could deal some real damage.
Therefore, SRAM is far more important than flash size. My firmware is now at 27064 byte, including GPS, Sonar, MAG, some larger custom stuff (data transfer framework), LED flashers, landing lights and the new descriptive strings for PIDITEMS and BOXITEMS.
Tommie,
What about implementing a safeguard for the stack/heap limit ? We are walking on a thin line, so it would be better to know how much memory do we left....
EOSBandi
Re: [Patch] Replacing boolean flag variables with bit field
EOSBandi wrote:What about implementing a safeguard for the stack/heap limit ? We are walking on a thin line, so it would be better to know how much memory do we left....
How would you implement this? If I call a method with a local variable "uint8_t buf[TOO_LARGE_FOR_MY_STACK]", how will you detect if the stack pointer just tripped over the heap? And far more important, how would you handle that?
One could think about using "malloc" for local buffers; but I'm not sure whether the ATMega can handle it gracefully. And even with that you'd still need to have a way to bail out of your function.
//edit: http://www.nongnu.org/avr-libc/user-manual/malloc.html
doesn't look so bad at all. I'll see what can be done with that...
//edit: OK, it looks bad at all. Using malloc adds about 600 byte to the firmware. Even I have to admit that this is too much.
Re: [Patch] Replacing boolean flag variables with bit field
What about this : http://forum.pololu.com/viewtopic.php?f ... read#p4218
It does not use malloc. We can check free mem in the main loop and activate a failsafe or a buzzer below a given treshold.
It does not use malloc. We can check free mem in the main loop and activate a failsafe or a buzzer below a given treshold.
Re: [Patch] Replacing boolean flag variables with bit field
In the mainloop, the stack has already collapsed again. You'd need probes throughout the program (see my latest patch), but if you encounter the situation, it's probably already to late.
That's the problem with Turing machines: You cannot decide whether they fill your memory or terminate. Greetings to the busy beaver and Rice's theorem.
So all you can do is compile your firmware, place probes in strategic locations (ISR, some bigger and deeper functions), watch the min_mem value and hope for the best.
Static verification is probably out of the window with that big pile of C++
That's the problem with Turing machines: You cannot decide whether they fill your memory or terminate. Greetings to the busy beaver and Rice's theorem.
So all you can do is compile your firmware, place probes in strategic locations (ISR, some bigger and deeper functions), watch the min_mem value and hope for the best.
Static verification is probably out of the window with that big pile of C++