If I put this in my arduino program, in main.cpp, I suddenly run out of memory for flash program size:
if(msgSize > 2) {
//sr::sequentialRead(&serialRead, newTram.hash);
uint8_t bytes[4];
Serial.readBytes(&bytes[0], 2);
}
Without that I see this:
avr-size -C --mcu=atmega328p connections_display.elf
AVR Memory Usage
----------------
Device: atmega328p
Program: 26348 bytes (80.4% Full)
(.text + .data + .bootloader)
Data: 598 bytes (29.2% Full)
(.data + .bss + .noinit)
But if I use Serial.readBytes
, I get:
avr-size -C --mcu=atmega328p connections_display.elf
AVR Memory Usage
----------------
Device: atmega328p
Program: 36404 bytes (111.1% Full)
(.text + .data + .bootloader)
Data: 601 bytes (29.3% Full)
(.data + .bss + .noinit)
I have tried this in blank arduino sketch too, and it doesn't have that problem, so it is something in my build commands.
This is my CMake:
cmake_minimum_required(VERSION 3.11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_SYSTEM_NAME Generic)
# Project name
project("MyProject" VERSION 0.1 LANGUAGES CXX C)
# Product filename (name of the compiled file)
set(PRODUCT_NAME connections_display)
set(ARDUINO_BOARD "UNO")
## AVR Chip Configuration
# 8Mhz, this should match the crystal on your board,
# I use 8Mhz and 3.3V for the lowest power consumption
set(F_CPU 16000000L)
# CPU, you can find the list here:
# https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html
set(MCU atmega328p)
# The programmer to use, read avrdude manual for list
# avrispmkII
set(ARDUINO_PROGRAMMER_TYPE arduino)
set(ARDUINO_PROGRAMMER_COM_ID "COM6")
set(ARDUINO_PROGRAMMER_BAUD 115200)
# AVR Fuses, must be in concordance with your hardware and F_CPU
# http://eleccelerator.com/fusecalc/fusecalc.php?chip=atmega328p
set(E_FUSE 0xfd)
set(H_FUSE 0xda)
set(L_FUSE 0xfd)
set(LOCK_BIT 0xff)
# set(CMAKE_AVR_TOOL_COMPILERS "%APPDATA%\\..\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\7円.3.0-atmel3.6.1-arduino7\\bin")
set(ARDUINO_TOOLKIT "%APPDATA%/../Local/Arduino15/packages/arduino")
set(ARDUINO_COMPILERS "${ARDUINO_TOOLKIT}/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin")
set(ARDUINO_AVRDUDE "${ARDUINO_TOOLKIT}/tools/avrdude/6.3.0-arduino17/bin")
set(ARDUINO_AVR_DIRECTORY "${ARDUINO_TOOLKIT}/hardware/avr/1.8.6")
set(ARDUINO_LIBRARIES_HOME "${ARDUINO_AVR_DIRECTORY}/libraries")
set(ARDUINO_CORES_HOME "${ARDUINO_AVR_DIRECTORY}/cores")
get_filename_component(ARDUINO_COMPILER_DIR ${CMAKE_CXX_COMPILER} DIRECTORY)
set(AVR_STRIP_COMMAND ${ARDUINO_COMPILER_DIR}/avr-strip)
set(AVR_OBJCOPY_COMMAND ${ARDUINO_COMPILER_DIR}/avr-objcopy)
set(AVR_SIZE_COMMAND ${ARDUINO_COMPILER_DIR}/avr-size)
set(AVR_AVRDUDE_COMMAND ${ARDUINO_AVRDUDE}/avrdude)
set(AVR_AVRDUDE_CONFIG ${ARDUINO_AVRDUDE}/../etc/avrdude.conf)
# Pass defines to compiler
add_definitions(
-DF_CPU=${F_CPU}
-DBAUD=${BAUD}
-DARDUINO=10607
-DARDUINO_AVR_UNO
-DARDUINO_ARCH_AVR
# disable some extra display functions
-DENA_SCR_DIA=0
-DENA_MISC=0
-DENA_OPNCLS=0
-DENA_GROW=0
)
# mmcu MUST be passed to bot the compiler and linker, this handle the linker
set(CMAKE_EXE_LINKER_FLAGS
-mmcu=${MCU}
)
add_compile_options(
-mmcu=${MCU} # MCU
-Os # optimize
-Wall # enable warnings
-Wno-main
-Wundef
-pedantic
-Wno-error=expansion-to-defined
-Wno-expansion-to-defined
-Wno-error=cpp
-Wno-cpp
-Wl,--relax,--gc-sections
-g
-gdwarf-2
-fno-threadsafe-statics
-funsigned-char # a few optimizations
-funsigned-bitfields
#-fpack-struct
-fshort-enums
-ffunction-sections
-fdata-sections
#-fno-split-wide-types
-fno-tree-scev-cprop
)
file(GLOB SRC_FILES "src/*.cpp" "src/*.c") # Load all files in src folder
# Create one target
add_executable(${PRODUCT_NAME} ${SRC_FILES})
target_include_directories(${PRODUCT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/display_controller)
target_include_directories(${PRODUCT_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include/)
# Rename the output to .elf as we will create multiple files
set_target_properties(${PRODUCT_NAME} PROPERTIES OUTPUT_NAME ${PRODUCT_NAME}.elf)
target_link_libraries(${PRODUCT_NAME} PRIVATE
ArduinoCore
)
# Strip binary for upload
add_custom_target(avr_strip_hex ALL ${AVR_STRIP_COMMAND} ${PRODUCT_NAME}.elf DEPENDS ${PRODUCT_NAME})
# Transform binary into hex file, we ignore the eeprom segments in the step
add_custom_target(avr_create_hex ALL ${AVR_OBJCOPY_COMMAND} -O ihex -R .eeprom ${PRODUCT_NAME}.elf ${PRODUCT_NAME}.hex DEPENDS avr_strip_hex)
# Transform binary into hex file, this is the eeprom part (empty if you don't
# use eeprom static variables)
add_custom_target(eeprom ${AVR_OBJCOPY_COMMAND} -O ihex -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 ${PRODUCT_NAME}.elf ${PRODUCT_NAME}.eep DEPENDS avr_strip_hex)
add_custom_target(avr_calc_size_two ALL ${AVR_SIZE_COMMAND} -A --mcu=${MCU} ${PRODUCT_NAME}.elf DEPENDS avr_create_hex)
add_custom_target(avr_calc_size ALL ${AVR_SIZE_COMMAND} -C --mcu=${MCU} ${PRODUCT_NAME}.elf DEPENDS avr_calc_size_two)
# Upload the firmware with avrdude
add_custom_target(upload_to_arduino ${AVR_AVRDUDE_COMMAND} -v -V -C${AVR_AVRDUDE_CONFIG} -c${ARDUINO_PROGRAMMER_TYPE} -p${MCU} -P${ARDUINO_PROGRAMMER_COM_ID} -b${ARDUINO_PROGRAMMER_BAUD} -U flash:w:${PRODUCT_NAME}.hex DEPENDS avr_create_hex)
set_target_properties(upload_to_arduino PROPERTIES EXCLUDE_FROM_ALL TRUE)
# Clean extra files
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${PRODUCT_NAME}.hex;${PRODUCT_NAME}.eeprom;${PRODUCT_NAME}.lst")
add_subdirectory("../lib/arduino_libs/ArduinoCore" "${CMAKE_BINARY_DIR}/lib/arduino_libs/ArduinoCore")
It depends on another one for the arduino core library:
ArduinoCore/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(ArduinoCore VERSION 1.0 LANGUAGES CXX)
# Set the C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(THIS_LIBRARY_HOME "${ARDUINO_CORES_HOME}/arduino/")
file(GLOB SRC_FILES "${THIS_LIBRARY_HOME}/*.cpp" "${THIS_LIBRARY_HOME}/*.c")
# Add the executable
add_library(${PROJECT_NAME} ${SRC_FILES})
# Include directories
target_include_directories(${PROJECT_NAME} PUBLIC ${THIS_LIBRARY_HOME})
# include pin definitions
if(ARDUINO_BOARD STREQUAL "UNO")
set(PIN_HEADERS "${ARDUINO_AVR_DIRECTORY}/variants/standard/")
else()
message(FATAL_ERROR "Unsupported ARDUINO_BOARD value: ${ARDUINO_BOARD}")
endif()
target_include_directories(${PROJECT_NAME} INTERFACE ${PIN_HEADERS})
target_include_directories(${PROJECT_NAME} PRIVATE ${PIN_HEADERS})
unset(THIS_LIBRARY_HOME)
unset(SRC_FILES)
I think I am using wrong compile flags and that somehow causes arduino core size to explode when this function is called. Even if I delete all of my code and leave this simple test main.cpp
, the problem is there:
#include "Arduino.h"
void setup() {
// initialize serial:
Serial.begin(9600);
}
uint8_t bytes[10];
int i = 0;
void loop() {
if (Serial.available() >= 10) {
Serial.readBytes(&bytes[0], 10);
i = 10;
}
if(i >= 10) {
i = 0;
for(int iout = 0; iout < 10; ++iout) {
Serial.write(bytes[i]);
}
}
}
Output of the avr-size:
[3/5] avr-size -A --mcu=atmega328p connections_display.elf
connections_display.elf :
section size addr
.data 52 8388864
.text 15354 0
.bss 185 8388916
.comment 17 0
.note.gnu.avr.deviceinfo 64 0
Total 15672
[4/5] avr-size -C --mcu=atmega328p connections_display.elf
AVR Memory Usage
----------------
Device: atmega328p
Program: 15406 bytes (47.0% Full)
(.text + .data + .bootloader)
Data: 237 bytes (11.6% Full)
(.data + .bss + .noinit)
1 Answer 1
The problem was that this is not how to pass linker flags correctly. The -Wl
part of add_compile_options
was not passed to linker.
Instead, I had to expand the CMAKE_EXE_LINKER_FLAGS
:
set(CMAKE_EXE_LINKER_FLAGS
"-mmcu=${MCU} -Wl,--relax,--gc-sections,-Os,-g,--strip-discarded,--stats"
)
Now I got the same size as with Arduino IDE.
Explore related questions
See similar questions with these tags.