stm32duino / Arduino_Core_STM32

STM32 core support for Arduino
https://github.com/stm32duino/Arduino_Core_STM32/wiki
Other
2.86k stars 979 forks source link

Simple sketches using too much flash memory for STM32C0 #2250

Closed sfe-SparkFro closed 10 months ago

sfe-SparkFro commented 10 months ago

Describe the bug

I'm having issues compiling code for the STM32C0. This problem actually exists with most code I try to compile, but to limit the scope of this issue, I'll focus on the I2C scanner example, since it demonstrates the fundamental problems and it should be easy for others to reproduce. Attempting to compile this example for the STM32C011F4Ux gives several warnings and fails due to not enough flash memory (it states the FLASH region overflowed by ~7kB).

To Reproduce

  1. Open Arduino and select MCU
    • Use latest Arudino IDE version (2.2.1) with latest version of STM32 Arduino core installed (2.7.1)
    • Tools -> Board -> "Generic STM32C0 series"
    • Tools -> Board part number -> "Generic C011F4Ux"
  2. Open I2C scanner example
    • File -> Examples -> Examples for Generic STM32C0 series -> Wire -> i2c_scanner
  3. Click Verify
  4. Several warnings appear, and it fails due to the FLASH region overflowing by ~7kB

Expected behavior

The example should compile with no warnings and not overflow the FLASH region (ideally use much less so I still have room for my own code!)

Screenshots

Easier to just paste the Output after clicking the Verify button:

In file included from C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/STM32C0xx_HAL_Driver/Inc/stm32c0xx_hal_adc.h:31,
                 from C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/STM32C0xx/stm32c0xx_hal_conf_default.h:223,
                 from C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/STM32C0xx/stm32c0xx_hal_conf.h:13,
                 from C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/STM32C0xx_HAL_Driver/Inc/stm32c0xx_hal.h:30,
                 from C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/CMSIS/Device/ST/STM32C0xx/Include/stm32c0xx.h:197,
                 from C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\cores\arduino/stm32/stm32_def.h:26,
                 from C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\cores\arduino/stm32/clock.h:19,
                 from C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\cores\arduino/wiring_time.h:23,
                 from C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\cores\arduino/wiring.h:38,
                 from C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\cores\arduino/Arduino.h:36,
                 from C:\Users\Dryw\AppData\Local\Temp\arduino\sketches\9FF2223B70710C14E478C4C8C9407AE5\sketch\i2c_scanner.ino.cpp:1:
C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/STM32C0xx_HAL_Driver/Inc/stm32c0xx_ll_adc.h: In function 'void LL_ADC_SetAnalogWDMonitChannels(ADC_TypeDef*, uint32_t, uint32_t)':
C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/STM32C0xx_HAL_Driver/Inc/stm32c0xx_ll_adc.h:3677:27: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
 3677 |   register __IO uint32_t *preg;
      |                           ^~~~
C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/STM32C0xx_HAL_Driver/Inc/stm32c0xx_ll_adc.h: In function 'uint32_t LL_ADC_GetAnalogWDMonitChannels(ADC_TypeDef*, uint32_t)':
C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/STM32C0xx_HAL_Driver/Inc/stm32c0xx_ll_adc.h:3781:27: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
 3781 |   register __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->CFGR1, ((AWDy & ADC_AWD_CRX_REGOFFSET_MASK) >> ADC_AWD_CRX_REGOFFSET_POS)
      |                           ^~~~
C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/STM32C0xx_HAL_Driver/Inc/stm32c0xx_ll_adc.h:3784:21: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
 3784 |   register uint32_t AnalogWDMonitChannels = (READ_BIT(*preg, AWDy) & AWDy & ADC_AWD_CR_ALL_CHANNEL_MASK);
      |                     ^~~~~~~~~~~~~~~~~~~~~
C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/STM32C0xx_HAL_Driver/Inc/stm32c0xx_ll_adc.h: In function 'void LL_ADC_ConfigAnalogWDThresholds(ADC_TypeDef*, uint32_t, uint32_t, uint32_t)':
C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/STM32C0xx_HAL_Driver/Inc/stm32c0xx_ll_adc.h:3903:27: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
 3903 |   register __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->AWD1TR, (((AWDy & ADC_AWD_TRX_REGOFFSET_MASK)) >> (ADC_AWD_TRX_REGOFFSET_BITOFFSET_POS)) + ((ADC_AWD_CR3_REGOFFSET & AWDy) >> (ADC_AWD_CRX_REGOFFSET_BITOFFSET_POS + 1UL)));
      |                           ^~~~
C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/STM32C0xx_HAL_Driver/Inc/stm32c0xx_ll_adc.h: In function 'void LL_ADC_SetAnalogWDThresholds(ADC_TypeDef*, uint32_t, uint32_t, uint32_t)':
C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/STM32C0xx_HAL_Driver/Inc/stm32c0xx_ll_adc.h:3980:27: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
 3980 |   register __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->AWD1TR, (((AWDy & ADC_AWD_TRX_REGOFFSET_MASK)) >> (ADC_AWD_TRX_REGOFFSET_BITOFFSET_POS)) + ((ADC_AWD_CR3_REGOFFSET & AWDy) >> (ADC_AWD_CRX_REGOFFSET_BITOFFSET_POS + 1UL)));
      |                           ^~~~
C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/STM32C0xx_HAL_Driver/Inc/stm32c0xx_ll_adc.h: In function 'uint32_t LL_ADC_GetAnalogWDThresholds(ADC_TypeDef*, uint32_t, uint32_t)':
C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\system/Drivers/STM32C0xx_HAL_Driver/Inc/stm32c0xx_ll_adc.h:4022:33: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
 4022 |   register const __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->AWD1TR, (((AWDy & ADC_AWD_TRX_REGOFFSET_MASK)) >> (ADC_AWD_TRX_REGOFFSET_BITOFFSET_POS)) + ((ADC_AWD_CR3_REGOFFSET & AWDy) >> (ADC_AWD_CRX_REGOFFSET_BITOFFSET_POS + 1UL)));
      |                                 ^~~~
c:/users/dryw/appdata/local/arduino15/packages/stmicroelectronics/tools/xpack-arm-none-eabi-gcc/12.2.1-1.2/bin/../lib/gcc/arm-none-eabi/12.2.1/../../../../arm-none-eabi/bin/ld.exe: C:\Users\Dryw\AppData\Local\Temp\arduino\sketches\9FF2223B70710C14E478C4C8C9407AE5/i2c_scanner.ino.elf section `.text' will not fit in region `FLASH'
c:/users/dryw/appdata/local/arduino15/packages/stmicroelectronics/tools/xpack-arm-none-eabi-gcc/12.2.1-1.2/bin/../lib/gcc/arm-none-eabi/12.2.1/../../../../arm-none-eabi/bin/ld.exe: region `FLASH' overflowed by 7380 bytes
collect2.exe: error: ld returned 1 exit status

exit status 1

Compilation error: exit status 1

Desktop:

Board:

Additional context

I understand that this MCU only has 16kB of flash, but this example really should not use so much memory that it can't be flashed in the first place. For reference, compiling the I2C scanner example for the Arudino Uno (the kind of MCU the STM32C0 is advertised to replace) uses about 4kB of flash memory. Even the blink example uses over 12kB of flash by itself! Simply including Wire.h from the blink example causes the FLASH region to be overflowed by almost 1kB. Makes it basically impossible to do anything with I2C.

fpistm commented 10 months ago

Hi @sfe-SparkFro For mcu with smaller flash, you have to do some customization. https://github.com/stm32duino/Arduino_Core_STM32/wiki/HAL-configuration#example-of-blinkino-for-nucleo-l031k6-with-32768-bytes-of-flash-and-8192-bytes-of-ra

Warning have to be fix in the STM32Cube.

sfe-SparkFro commented 10 months ago

Thanks for the reply @fpistm!

Just to confirm, it should be as simple as creating a file called hal_conf_extra.h to the sketch directory, and adding #define HAL_*_MODULE_DISABLED for each module to disable, correct?

Doing this does have some minor effects, but not significant enough to get the I2C scanner example small enough. I tested the effect of adding each HAL_*_MODULE_DISABLED listed here and was only able to save 752 bytes. Here's my hal_conf_extra.h with comments describing the effect of each macro:

// Reduces flash size by 752 bytes
#define HAL_CRC_MODULE_DISABLED // 280 bytes
#define HAL_EXTI_MODULE_DISABLED // 472 bytes

// Changes warnings, does not chage flash size
#define HAL_ADC_MODULE_DISABLED

// No effect
#define HAL_I2S_MODULE_DISABLED
#define HAL_RTC_MODULE_DISABLED
#define HAL_SAI_MODULE_DISABLED
#define HAL_SPI_MODULE_DISABLED
#define HAL_DAC_MODULE_DISABLED
#define HAL_ICACHE_MODULE_DISABLED
#define HAL_SUBGHZ_MODULE_DISABLED
#define HAL_ETH_MODULE_DISABLED
#define HAL_OSPI_MODULE_DISABLED
#define HAL_QSPI_MODULE_DISABLED
#define HAL_SD_MODULE_DISABLED

// Can't disable these modules, required for i2c_scanner example
// #define HAL_I2C_MODULE_DISABLED
// #define HAL_TIM_MODULE_DISABLED

And here's the new Output with this hal_conf_extra.h:

C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\variants\STM32C0xx\C011D6Y_C011F(4-6)(P-U)_C031F(4-6)P\generic_clock.c: In function 'SystemClock_Config':
C:\Users\Dryw\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1\variants\STM32C0xx\C011D6Y_C011F(4-6)(P-U)_C031F(4-6)P\generic_clock.c:46:3: warning: implicit declaration of function 'LL_SetSystemCoreClock' [-Wimplicit-function-declaration]
   46 |   LL_SetSystemCoreClock(48000000);
      |   ^~~~~~~~~~~~~~~~~~~~~
c:/users/dryw/appdata/local/arduino15/packages/stmicroelectronics/tools/xpack-arm-none-eabi-gcc/12.2.1-1.2/bin/../lib/gcc/arm-none-eabi/12.2.1/../../../../arm-none-eabi/bin/ld.exe: C:\Users\Dryw\AppData\Local\Temp\arduino\sketches\13BD30998A11CD6BA9E390C223E9CA66/stm32c0_test.ino.elf section `.text' will not fit in region `FLASH'
c:/users/dryw/appdata/local/arduino15/packages/stmicroelectronics/tools/xpack-arm-none-eabi-gcc/12.2.1-1.2/bin/../lib/gcc/arm-none-eabi/12.2.1/../../../../arm-none-eabi/bin/ld.exe: region `FLASH' overflowed by 6628 bytes
collect2.exe: error: ld returned 1 exit status

exit status 1

Compilation error: exit status 1

The HAL configuration wiki also suggests disabling Serial. FWIW, doing this (Tools -> U(S)ART support -> Disabled) and removing all Serial code from the example does reduce the size enough to fit in the flash memory. But only barely (~14kB out of 16kB), and I actually need both Serial and Wire, so this is not a viable solution.

fpistm commented 10 months ago

Well, unfortunately, it will be hard to reduce enough the size of code to fit your needs. This core is generic to support all STM32 families and sometimes it could not fit in very small size of flash depending on the set of feature. One other way could be t disable the I2C and implement a I2C light driver using LL but can't do it.

Note that I've fixed the LL_SetSystemCoreClock warning thanks https://github.com/stm32duino/Arduino_Core_STM32/commit/75bda51e7c6d79415326ac43a199ee36200d93a1

sfe-SparkFro commented 10 months ago

Fair enough, I understand, and I appreciate your time! I'll see about using the LL drivers; my initial tests with them in the STM32CubeIDE have helped a lot in reducing the flash memory requirement. I do also have the opportunity to switch to the 32kB package (STM32C011F6Ux), so that will help too.

If possible, I would like to suggest adding a warning or something in the Notes column here (and to other devices with a small flash size) that out-of-the-box functionality will be limited in Arduino. IMO, not being able to use multiple Arduino drivers simultaneously (eg. Wire and Serial) is a pretty severe limitation of an Arduino core, and that could be stated more clearly.

Thanks again!

sfe-SparkFro commented 10 months ago

Updated issue title to hopefully make this more searchable.