ARM Cortex-M4 Zero-Initialized Data Allocation in Minimal Keil Project

When compiling an empty main function for the STM32F103C8 microcontroller using Keil ARM, the program size report indicates a surprisingly large Zero-Initialized (ZI) data section. Specifically, the output shows:

  • Code: 648 bytes
  • RO-data: 252 bytes
  • RW-data: 0 bytes
  • ZI-data: 1632 bytes

The ZI-data section, which represents uninitialized global and static variables, is unexpectedly large for an empty main function. This section is allocated in RAM but does not contribute to the binary size since it is zero-initialized at runtime. The presence of such a large ZI-data section suggests that the linker script and startup code are reserving significant memory for system-level data structures, even in a minimal project.

The startup file (startup_stm32f10x_md.s) and the system initialization file (system_stm32f10x.c) are essential components provided by Keil and CMSIS. These files include critical initialization routines such as setting up the stack, heap, and clock configuration. The RTE_Device.h file is part of the Run-Time Environment (RTE) configuration, which defines device-specific settings and peripheral configurations. These files are necessary for the proper functioning of the microcontroller, even in a minimal project.

Linker Script Configuration and C Library Overhead

The large ZI-data section can be attributed to several factors, primarily related to the linker script configuration and the overhead introduced by the C library. The linker script defines memory regions and assigns sections to these regions. In a typical STM32 project, the linker script reserves memory for the stack, heap, and other system-level data structures. The stack size, in particular, can significantly impact the ZI-data section. The default stack size in Keil projects is often set to a conservative value to ensure sufficient space for function calls and local variables.

The C library initialization code, which is included by default in Keil projects, also contributes to the ZI-data section. This code sets up the runtime environment, including initializing the heap for dynamic memory allocation. The heap size is another factor that can increase the ZI-data section. Even in a minimal project, the C library initialization code reserves memory for the heap, which is reflected in the ZI-data section.

The system_stm32f10x.c file contains the SystemInit function, which is called from the startup file before the main function. This function configures the microcontroller’s clock system, including the HCLK (AHB clock). The SystemInit function is essential for setting up the clock tree and ensuring that the microcontroller operates at the desired frequency. The RTE_Device.h file, on the other hand, defines device-specific settings such as peripheral clock enables and pin configurations. These settings are necessary for the proper initialization of the microcontroller’s peripherals.

Optimizing ZI-Data Allocation and Customizing System Initialization

To reduce the ZI-data section, the first step is to review and adjust the linker script settings. The stack and heap sizes can be modified to better fit the application’s requirements. In Keil, the stack and heap sizes can be adjusted in the startup file or through the project settings. Reducing the stack and heap sizes can significantly decrease the ZI-data section, but care must be taken to ensure that the application has sufficient memory for its operations.

Using microlib, a minimal implementation of the C library, can also help reduce the ZI-data section. Microlib is designed for embedded systems with limited resources and provides a smaller footprint compared to the standard C library. To enable microlib in Keil, navigate to the project options, select the "Target" tab, and check the "Use MicroLIB" option. This will replace the standard C library with microlib, reducing the overhead associated with the C library initialization code.

For applications that require custom clock configurations, the SystemInit function can be modified or replaced. The SystemInit function is defined in the system_stm32f10x.c file and is responsible for configuring the clock tree. To customize the clock configuration, the SystemInit function can be modified to set the desired HCLK frequency. Alternatively, the SystemInit function can be replaced with a custom initialization function that configures the clock system according to the application’s requirements. This custom function should be called from the startup file instead of the default SystemInit function.

The RTE_Device.h file can also be customized to optimize the device-specific settings. This file is generated by the Run-Time Environment (RTE) configuration tool and defines the peripheral configurations for the microcontroller. By customizing the RTE_Device.h file, unnecessary peripheral configurations can be removed, reducing the memory footprint of the application. However, care must be taken to ensure that the required peripherals are properly configured for the application.

In summary, the large ZI-data section in a minimal STM32F103C8 project is primarily due to the default linker script settings and the overhead introduced by the C library initialization code. By adjusting the stack and heap sizes, using microlib, and customizing the SystemInit function and RTE_Device.h file, the ZI-data section can be optimized to better fit the application’s requirements. These optimizations can help reduce the memory footprint of the application, making it more suitable for resource-constrained embedded systems.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *