Fimware too large for microcontroller (atmega32u4)

Hello, I am trying to use a Pro Micro (atmega32u4) as an adxl345 module, meaning I just connect a USB cable, bolt this module on to my print head, uncomment some lines in my config and be good to go.

To generate the firmware, I am doing this:

  1. make menuconfig:
    Micro-controller Firmware Architecture: Atmel AVR
    Processor Model: atmega32u4
    Processor Speed: 16mhz
    Manually Clear CPU prescaller: checked
    Communication interface: USB
    USB ID’s: default settings
  2. make clean
  3. make

At this point I am using ftp to copy the klipper.elf.hex file from the ./out on the pi to my laptop to use avrdude to flash.

  1. avrdude -C avrdude.conf -p m32u4 -P COM6 -c avr109 -U flash:w:klipper.elf.hex

AVRDude now fails, here’s the output:

Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
    Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.

Programmer supports the following devices:
    Device code: 0x44

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "klipper.elf.hex"
avrdude: input file klipper.elf.hex auto detected as Intel Hex
avrdude: writing flash (29292 bytes):

Writing | ################################################## | 100% 2.18s

avrdude: 29292 bytes of flash written
avrdude: verifying flash memory against klipper.elf.hex:
avrdude: input file klipper.elf.hex auto detected as Intel Hex

Reading | ################################################## | 100% 0.27s

avrdude: verification error, first mismatch at byte 0x7000
         0x55 != 0x80
avrdude: verification error; content mismatch

avrdude done.  Thank you.

So the 32u4 only has 32kb total flash space, and it appears that the sparkfun bootloader uses the last 4k, which leaves only 28k for programs. Is there a smaller bootloader that I should be using? Otherwise, how do I upload to klipper to a pro micro? Interestingly, when building klipper.elf.hex for my atmega2560/ramps controller board, that uses 28610kb of flash, which would fit on the 32u4. Why is the 32u4 firmware like 1k larger than the 2560 firmware, because that difference is currently preventing me from being able to upload.

might be related

The extra 1k is likely for the USB peripheral, the atmega2560 doesn’t have one.

Its possible that Klipper has outgrown the 28KiB available on the 32u4. It might be possible to trim it down by removing some items from the makefile in the src folder. For example, neopixel.c, sensor_angle.c, lcd_st7920.c, lcd_hd44780.c, and pulse_counter.c are all unnecessary for your application.

I have the exact same problem. It used to work until commit 324, it is not possible to flash newer versions to the atmega32u4. I think sensor_angle was added in commit 325 and now the firmware is too big for the 32u4.
Unfortunately I am not too familiar with coding, so what should i change in the sources?
Just delete the word ‘sensor_angle.c’ in the Makefile in src-dir? Thanks for your help.

It does look like recent versions of Klipper have exceeded 28KiB on the atmega32u4.

I’d guess the simplest solution would be to deploy a smaller bootloader if possible. I don’t have an atmega32u4 so I can not make any recommendations on bootloaders. A quick internet search does show that 1KiB bootloaders are available though.

As Arksine mentions, it is also possible to reduce the size of Klipper by removing unneeded modules from src/Makefile . Another option is to replace -O2 with -Os in the main Makefile. Again, though, using a smaller bootloader is likely the more scalable approach.

Cheers,
-Kevin

Ok, so I’ve figured out some things.

I used a smaller bootloader, and had success with using the hex file the current (at time of posting) klipper make generates.

The bootloader I used is here,
I uploaded to a pro micro clone using an arduinoISP. Everything went well execept for make program-lock, which complained about a mismatch. Im using Ubuntu under wsl2, so idk if thats an issue with my setup of the bootoader.
Also, I couldn’t get the cli python script to work since python2-pip apparently doesnt exist anymore, and idk how to install easyhid into python2 without pip.
There’s a GUI exe that works, and the kp_boot bootloader lets you flash over USB still (which I think you have to give up with optiboot). (Also, you press reset once to enter the bootloader and press it again to exit, Its not on a time delay which is nice IMO. Not to like shill the bootloader or anything, just that double pressing the reset button and then making sure youve timed it right is kinda a pain. And its like 1Kib)

Here is the pin mapping im using, I just copied from a pinout diagram online:

[mcu adxl345_module]
serial: /dev/serial/by-id/usb-Klipper_atmega32u4_69420-if00

[board_pins pro_micro]
mcu: adxl345_module
aliases:
    ar0=PD2, ar1=PD3, ar2=PD1, ar3=PD0, ar4=PD4, ar5=PC6, 
    ar6=PD7, ar8=PB4, ar9=PB5, ar10=PB6, ar14=PB3, ar15=PB1, 
    ar16=PB2, ar18=PF7, ar19=PF6, ar20=PF5, ar21=PF4, 
    analog0=PF7, analog1=PF6, analog2=PF5, analog3=PF4, 
    analog6=PD4, analog7=PD7, analog8=PB4, analog9=PB5, analog10=PB6,
    rx_led=PB0, tx_led=PD5,

I cant get the adxl345 module to work, accelerometer_querery errors with error Invalid *adxl345 id* (got *0* vs e5) but I setup some macros to test the builtin leds and those worked:

[output_pin pro_micro_rx_led]
pin: !adxl345_module:rx_led
pwm: True
value: 0
cycle_time: 0.010

[output_pin pro_micro_tx_led]
pin: !adxl345_module:tx_led
pwm: True
value: 0
cycle_time: 0.010

[gcode_macro promicro_rx_off]
gcode: SET_PIN PIN=pro_micro_rx_led VALUE=0

[gcode_macro promicro_rx_on]
gcode: SET_PIN PIN=pro_micro_rx_led VALUE=1

[gcode_macro promicro_tx_off]
gcode: SET_PIN PIN=pro_micro_tx_led VALUE=0

[gcode_macro promicro_tx_on]
gcode: SET_PIN PIN=pro_micro_tx_led VALUE=1

so aside from not being able to use the cli and the wonkyness setting (im assuming) the lock fuses, Im pretty sure the klipper firmware itself is working.

I replaced -O2 with -Os in the main Makefile and know it is possible to flash it again on promicro with original bootloader. Thanks!
Btw, can I leave that permanent? What happens, when I compile with that parameter for main mcu and linux process.

The -Os flag tells gcc to “optimize for size”. It produces slightly smaller binaries that run slightly slower.

-Kevin

Using
v0.10.0-571-g97a5b39a-dirty-20221008_215332-mainsailos
-Os flag
and removing a few .c from /klipper/src/Makefile like the lcds, neopixel, buttons, pulse counter
And QMK_toolbox’s autoflash since Kiauh flasher would not work for me

I managed to successfully compile and flash my Pro Micro with a 32u4 without any mismatch on the stock bootloader.

ADXL345 wired and it’s been picked up when configured as a mcu.

took me about 8 hours of trial and error as I figured out what needed to be done.

I don’t want to disappoint but I think the code base for klipper has grown since I compiled it and cut the fat, it might be no longer possible now.

If you have a bit of money and time you can get a raspberry pi Pico or a black PCB clone from AliExpress, some have 16MB of flash, making them quite future proof.

I have replaced my pro micro with a Pico because for this reason and also that the micro usb port snapped off.

I could give it a shot I just don’t have that much time unfortunately

Best of luck

I have a custom branch that allows to disable some parts of Klipper’s build. It also enables link-time optimizations.
Please use with care, I haven’t tested it AVR and disabling certain peripherals will break some functionality.

I just built fw for the m32u4 and wanted to share my config incase it can help anyone else:

At time of writing, the default build runs over by ~6kb. After make menuconfig edit the .config file and turn off displays (lcd) and bitbanging. (turning off bitbanging unselects neopixels, pulse counter, ect) I also modified the makefile for -Os, but that it isnt necessary at this time.

Im using this mcu as a usb adapter for an ADXL345 module, and so in the end my config turns off CONFIG_WANT_GPIO_BITBANGING, CONFIG_WANT_DISPLAYS, CONFIG_WANT_LIS2DW, CONFIG_INLINE_STEPPER_HACK, but the two important ones are bitbang and display.

Im using the standard arduino micro bootloader, (my board, physically, is a pro micro clone) and QMK Toolbox to flash the .hex file. Everything seems to be in working order, the specific build im running is v0.12.0-103-g6ce6fbbc-dirty.