In embedded systems development, the management of memory is a crucial aspect that directly impacts both performance and memory usage. One common requirement in many applications is the use of constant data, such as lookup tables, which can be stored in non-volatile memory to optimize access speed and conserve SRAM. However, the way different platforms handle this process can vary. In this article, we will explore how to store constant data in ROM, specifically Flash memory, on two popular platforms: the Arduino UNO and the STM32F303K8 using Keil MDK. By understanding the nuances of both, developers can make more informed decisions when developing embedded applications.
The Arduino UNO, based on the ATmega328P microcontroller, is a popular platform for learning and prototyping. The board offers 32 KB of Flash memory, 2 KB of SRAM, and 1 KB of EEPROM. While Flash memory is non-volatile and used to store both code and constant data, there is a subtle difference in how constant variables are handled.
In Arduino, when you declare a variable as const
, it is by default stored in SRAM, not Flash memory. This is because the const
keyword only ensures that the data is read-only; it does not specify where the data is placed. However, for many embedded systems, placing lookup tables and constant data into Flash memory is essential for saving precious SRAM.
To explicitly store constant data such as a lookup table in Flash memory on the Arduino, the PROGMEM
macro must be used in conjunction with the const
keyword. The PROGMEM
modifier tells the compiler to place the variable into Flash memory rather than SRAM.
Here is an example of how to correctly store a lookup table in Flash memory on the Arduino UNO:
#include <avr/pgmspace.h> const uint8_t lookupTable[] PROGMEM = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; void setup() { Serial.begin(9600); // Accessing the lookup table for (int i = 0; i < 10; i++) { uint8_t value = pgm_read_byte_near(lookupTable + i); Serial.println(value); } } void loop() { // Main loop does nothing }
In this example, the PROGMEM
keyword ensures that the lookupTable
is stored in Flash memory. The pgm_read_byte_near()
function is then used to access the data in Flash memory, as direct access to PROGMEM
is not possible.
Without the PROGMEM
modifier, the data would be placed in SRAM, which is limited in size and could result in memory issues for larger arrays or more complex programs.
The STM32F303K8 is a more powerful microcontroller, part of the STM32 family from STMicroelectronics. It offers a rich set of features, including 64 KB of Flash memory, 8 KB of SRAM, and several advanced peripherals. When using the STM32 with Keil MDK, the process of storing constant data in non-volatile memory (Flash) is straightforward, thanks to the use of the const
keyword.
In contrast to the Arduino platform, STM32 uses Flash memory to store both code and constant data, and it is placed there automatically by the compiler when variables are declared as const
. However, just like on Arduino, the data is not always placed in the appropriate section of Flash unless the linker script is set up properly. By default, the const
keyword ensures that the variable is stored in read-only memory, and the linker generally places it in the Flash section.
Here’s an example of how you would store a lookup table in Flash memory on the STM32F303K8 using Keil MDK:
#include "stm32f3xx.h" const uint8_t lookupTable[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int main(void) { HAL_Init(); // Accessing the lookup table (using the array directly) for (int i = 0; i < 10; i++) { // Use the lookup table values uint8_t value = lookupTable[i]; // Do something with the value (e.g., output or processing) } while (1) { // Main loop does nothing } }
In this example, the const
keyword ensures that the lookupTable
is placed in Flash memory by default. The STM32F303K8’s linker will handle placing this constant data in the appropriate section of Flash memory for non-volatile storage.
While the const
keyword may not be as explicit as the PROGMEM
macro in Arduino, it still ensures that the data is stored in Flash memory on the STM32 platform. The STM32’s linker script and the memory layout will take care of putting the constant data into the correct section of Flash memory.
Use of PROGMEM
in Arduino: On the Arduino platform, the PROGMEM
macro is required to explicitly store constant data in Flash memory (ROM). This is crucial for optimizing SRAM usage, as Flash memory is much larger and non-volatile.
Use of const
in STM32: On STM32, using const
is typically enough to store data in Flash memory, as long as the linker script is properly configured. This simplifies the process compared to Arduino, where explicit use of PROGMEM
is necessary.
Memory Considerations: Both platforms benefit from storing constant data in Flash memory rather than SRAM. Arduino has limited SRAM, making this especially important for larger applications, while STM32 has more resources, though efficient memory usage is still critical for embedded applications.
Storing constant data in ROM (Flash memory) is a common requirement in embedded systems to conserve SRAM and optimize performance. On the Arduino platform, using the PROGMEM
macro is necessary to store data in Flash memory. On STM32, the const
qualifier is sufficient to achieve this, as the linker automatically places constant variables in Flash memory. Understanding these subtle differences helps developers efficiently manage memory resources and ensures that their applications can scale effectively, whether they are working with an Arduino UNO or a more complex STM32 microcontroller.