1
\$\begingroup\$

I bought an ATmega32 IC recently, but now I found out the program I wrote in Atmel Studio reports an error due to an overflow of memory. It is 134.1% over the recommended memory of this chip. Are there alternatives that exist?

I don't want to go and buy another chip as they are quite expensive.

\$\endgroup\$
  • 14
    \$\begingroup\$ If you insist on using that chip then your only option is to improve your code. \$\endgroup\$ – Transistor Aug 21 '18 at 11:49
  • 8
    \$\begingroup\$ 32KB is a lot of program memory, which suggests either you have a very complex application or you should be able to find a lot of ways of reducing size. Are you using any add-on libraries or an RTOS, if so can you try rewriting without them? If you're using floating point, can you rewrite to only use integer arithmetic? \$\endgroup\$ – Jules Aug 21 '18 at 11:52
  • 5
    \$\begingroup\$ Do you have -Os optimisations turned on? \$\endgroup\$ – Jon Aug 21 '18 at 11:59
  • 2
    \$\begingroup\$ It's also handy to minimize the amount of strings you (say) would want to print over the serial. Those can get pretty large fast. Also, you could also store some large, not too often accessed constants in the EEPROM, if you have any space left there. \$\endgroup\$ – Richard the Spacecat Aug 21 '18 at 12:04
  • 4
    \$\begingroup\$ Program memory or RAM? The latter is a lot smaller and easier to fill with e.g. constant data, which the compiler has to arrange to appear in RAM, since you can't access the program memory with the same instructions as RAM. \$\endgroup\$ – ilkkachu Aug 21 '18 at 15:26
3
\$\begingroup\$

Atmega32 is like a stripped down Atmega644x or Atmega1284P. Change the chip to get a lot more memory, more SRAM (up to 16K bytes), and dual hardware serial ports.

\$\endgroup\$
  • \$\begingroup\$ For some bizarre reason the atmega 1284 is priced alot cheaper than the atmega 32 but it has more memory. Wouldn't have expected that when I Google it. Thanks for the advice. This new chip does solve the whole problem \$\endgroup\$ – Joey Aug 25 '18 at 9:40
9
\$\begingroup\$

Global variables/types

  • Changing the type of global variables (e.g. use uint8_t or a similar 1 byte instead of long), or use bits to store boolean arrays.
  • Remove static variables and replace them by dynamic (local) variables if possible. Passing them as arguments might be used to keep the scope longer.

Data/precalculated tables

  • In case you now keep (fixed) data structures in your code (e.g. for pre calculated tables), than put these in external Flash. Executable code is hard to put in external Flash, but tables/data is not. Of course this comes with a performance loss. Another way is to calculate it on the fly (no calculated table needed at all).
  • Instead of using pre calculated data tables at all, calculate them; this might cause a performance loss.
  • In case you are using a lot of stored texts or data, 'compress' them if possible. The decompression code will cost some Flash, but if you have a lot of text, it might be worthwhile.

Executable code

  • Using for loops instead of calling functions one by one.
  • Check for repeated code and create functions of them, use parameters to differ between small changes; this will cause a (small) performance loss.
  • Prevent 'inline' or long #define statements/code, these are substituted (copied) wherever used.

Logging/tracing

logging strings can consume many bytes (e.g. for one log string like: "The current temperature is: " cost 29 bytes). Having many log strings can add up a lot. To prevent this you can:

  • Use shorter strings ("CurTemp: " is only 9 bytes).
  • Print an integer (cost 1 or 2 bytes, depending on the int size).
  • Send this integer to another microcontroller which converts it to human readable text. It cost a bit of overhead/peripheral overhead.
  • When debugging, put all logging in #ifdefs, and save Flash by reducing functionality you don't need for testing. When not debugging, all logging statements will not cost any bytes.

Libraries

  • Finding alternative libraries which are implemented differently but with the functionality you need.

Compiler options

  • Check compiler options to see if the code can be compiled in a different way; mostly it will be a trade off against performance.

What you should NOT do

  • Make your code a few bytes smaller by using obscure code implementation. This will bite you later when you maintain your application.
  • Removing unused functions does not help (the compiler is smart enough to do this for you).
\$\endgroup\$
  • 1
    \$\begingroup\$ Remember to differentiate between data and program size. The question probably refers to program size (though it does not actually say which). Things like buffers won't really figure into that, but various ways of handling data can cost more program size. \$\endgroup\$ – Chris Stratton Aug 21 '18 at 13:00
  • 1
    \$\begingroup\$ First point can be misleading: there's no guarantee (in general) that changing to a smaller variable size leads to savings. In this case, it should as it's an 8bit device. I would also avoid "char" for variables - use actual integer types like uint8_t, for example, rather than something that happens to be 8bits wide. \$\endgroup\$ – awjlogan Aug 21 '18 at 13:01
  • 1
    \$\begingroup\$ @awjlogan uint8_t is indeed better, and with int I meant a bigger type, I adapted my answer, thanks for the notification. \$\endgroup\$ – Michel Keijzers Aug 21 '18 at 13:49
  • 2
    \$\begingroup\$ @awjlogan uint8_t is not "actual integer type": it's a typedef, and most likely to unsigned char (dunno what types ATmega actually has). \$\endgroup\$ – Ruslan Aug 21 '18 at 15:34
  • 1
    \$\begingroup\$ @awjlogan I only use (u)int8/16/32t types for integer (like) types, to prevent microprocessor related issued. and char for characters like 'a'. For booleans I normally make an own type (bool_t which is defined as unsigned char_t). \$\endgroup\$ – Michel Keijzers Aug 21 '18 at 15:56
5
\$\begingroup\$

Unfortunately, adding external program memory is not usualy possible with this kind of chip. You could conceivably read and execute code from an external flash, but it would likely be slow and unstable.

You may be able to reduce the size of the compiled code, by eliminating static variables and removing unused libraries.

If you cannot find a way to to reduce the code size, you can look at MCUs of the same architecture here: https://www.microchip.com/design-centers/8-bit/avr-mcus

\$\endgroup\$
  • 1
    \$\begingroup\$ I wanted to add that an AVR controller can execute code only in its FLASH memory. Loading code from an external source would either require burning it into the internal flash, which is a stupid idea, or an emulator that parses the opcodes in software. A chip with more memory is the solution to go for if the code size cannot be reduced. \$\endgroup\$ – GNA Aug 21 '18 at 14:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.