Reducing Memory on Atmega16U4/Atmega32U4


I managed to add a custom board into the IDE (custom design using Atmega16U4). I based the addition in the the boards.txt file from the Leonardo (similarly in avrdude.conf). Everything is working as it should but I would like to reduce the memory in a blank sketch because I'm trying to use the FUSB302 PD controlller in my design and the protocol portion takes up a ton of memory. The blank sketch uses 3462 bytes which takes up about 24 percent of memory. Any way to reduce this? I'm not using any of the USB functionlity (using ATMEL ICE to load firmware).

The FUSB302B targets system designers looking to implement
a DRP/SRC/SNK USB Type-C connector with low amount of
The FUSB302B enables the USB Type-C detection including
attach, and orientation. The FUSB302B integrates the physical layer
of the USB BMC power delivery protocol to allow up to 100 W of
power and role swap. The BMC PD block enables full support for
alternative interfaces of the Type-C specification.

Arduino has a goodly amount of overhead.
I would suggest you drop to C++ and build leaner code.

You can even do assembler from within the IDE:

So no suggestions for what I was actually asking? How to reduce the memory that blank sketch uses?

ATmega16U4/32U4 from datasheet:

Non-volatile Program and Data Memories
– 16/32KB of In-System Self-Programmable Flash
– 1.25/2.5KB Internal SRAM
– 512Bytes/1KB Internal EEPROM
– Write/Erase Cycles: 10,000 Flash/100,000 EEPROM
– Data retention: 20 years at 85C/ 100 years at 25C(1)
– Optional Boot Code Section with Independent Lock Bits

  • Bit terse, but you can create your own Arduino core and rework the default C++ start-up code. *

  • You can program in assembler, create your own bare-bones low-level routines.

Or, you can just suck-it-up and know that the marjority of "default structures and initialization code" has been selected by experts to represent the best mix for the most users.

You always can throw hardware at the concern: use an Arduino model that has more SRAM and more flash.

Folks have written "cores" for AVR'ish uC with far less resources, like the ATtiny85.

And on the same subject of reducing blank-sketch resources:

Create a .lss file and look at what got linked in.
That will tell you where to focus your efforts as you will see all the code that is linked in and how big everything is.
Doing anything else is pretty much just tossing darts.

You will need to go to the location where the IDE builds the image and run avr-objdump on the elf file.

If you are using linux I can provide you a script that you can install in your IDE build tools that can generate it from the IDe whenever you do a build.

--- bill

That hardly seems necessary. The Leonardo and similar "boards" always include the USB code, in order to handle the weird re-boot handshake that they use. To reduce the size, you have to figure out how to omit the USB code. That's easy enough if you design a new board type (perhaps not; code seems to be conditional on whether the USBCON register is defined), and probably difficult otherwise.

I don't understand why you're using a 16u4 CPU if you're not using USB?

>  avr-nm -SC --size-sort /tmp/Arduino1.8.13Build/*.elf 
000001cc 00000022 t USB_SendSpace(unsigned char) [clone .constprop.3]
000001ee 00000028 t PluggableUSB()
00000bf4 0000002a t _GLOBAL__sub_I__cdcInterface
00000216 0000002c t Serial_::write(unsigned char)
000004ec 00000030 t delay.constprop.10
000002e4 00000034 t Serial_::available()
00000260 0000003c t Serial_::read()
000000ac 00000042 t _cdcInterface
0000029c 00000048 t Serial_::peek()
000004a2 0000004a t micros
000003da 0000004c t USB_SendControl(unsigned char, void const*, int)
00800137 00000050 b Serial
00000178 00000054 t USB_Recv(unsigned char, void*, int) [clone .constprop.5]
00000318 0000005c t SendControl(unsigned char)
00000426 00000062 t SendInterfaces()
00000374 00000066 t USB_SendStringDescriptor(unsigned char const*, unsigned char, unsigned char)
00000b60 00000094 T __vector_23
0000061e 000000de T __vector_10    // USB General Interrupt
0000051c 00000102 t Serial_::write(unsigned char const*, unsigned int)
00000c1e 00000132 T main
000006fc 00000464 T __vector_11    // USB Endpoint interrupt.

ok, maybe I should have said look at the .lss listing file or a symbol table.
But I'd still say for being able to actually see what is really pulled in and how big individual things are, I find looking at the .lss file is the most useful to know where to actually start looking for things to try to remove.

The script I use actually generates both each time the IDE builds a sketch.
And while I do use the symbol table some, I use the listing file much more often when I want home on things like what code is actually generated by the compiler, and trying to do space optimizations.

--- bill

I agree that a listing file (from avr-objdump; the ones from the compiler are relatively useless and extremely cluttered with "debug" info) is generally more useful than dumping the symbol table, IF you are trying to optimize the size of your own code and need to see what it looks like.
It's less useful if you're trying to analyze the core itself, where you don't know the actual structure and generally need to know "what's it pulling in", rather than "how big is each individual function."


That processor is like my 5th choice for a processor by the suppply constraint. I have the USB portion available on the board but I have a signal integrity issue with my external crystal and that is needed for USB to work. So I have the bread board the chip, change the fuses so I can use the internal clock so I can flash the device with the ATMEL ICE. The next iteration, we will more than likely use the ATMEGA88 MCU and use a PD controller that has the PD protocol already loaded. By the way, I did make a new board but I think that USBCON register is set in avrdude.conf maybe. Still exploring that.


Unfortunatley I am not using Linux ( I want to migrate but it's hard with other software like Altium isn't support on linux)

I managed to get the blank sketch down to 19% of memory used which is better for sure. ( I did this by commenting out the CDC.c code in the core libraries).

Well, there's a really gross patch you could make to iom16u4.h (that's the atmel set of peripheral register defines; the one that users should never modify!)

#if 0
#define USBCON  _SFR_MEM8(0xD8)

All the Arduino USB code is inside #ifdef USBCON conditionals, so this ends up cutting an empty sketch down to about 600 bytes (instead of 4000)
I'm not sure what other effects it will have.

(the iom16u4.h file is normally buried deep down inside the "latest" tools directory. Something like C:\Users\billw\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino5\avr\include\avr\iom16u4.h on my PC.)

A better fix is probably to copy that file into your sketch directory and edit it there. I think that the various #includes will pick up the local copy instead of the default tool copy.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.