Hi again; in this post we’re going to be introducing the organization of memory with an embedded system, including both physical memory and compiled memory segments. Memory is a key component of embedded systems, and all computer systems for that matter. Unfortunately, memory is also one of our major limiting resources in embedded systems.
The fundamental building block of memory is a bit. And a bit can store one piece of Boolean information, either one or a zero. 8 bits make up a byte. And bytes are usually the minimum unit we can access in hardware. They’re usually the unit with which we scale the size of memory as well. A byte is actually really small compared to the sizes of memory in modern architectures. You usually have an enormous amount of bytes that make up your memory. Data centers are in the order of petabytes of memory. Your personal computers may see the need for terabytes of data storage. But embedded systems tend to only have smaller amounts of memory, around a couple hundred kilobytes to megabytes. For such small amounts of memory it is important that we utilize and organize memory efficiently in embedded systems.
- varying capacities
- power requirements
- the way data is stored the volatility
- how you access that information
Because of this, we usually design systems with a mixture of different memories. The memory system could be thought of as a pyramid. The top is the most expensive, lowest latency but it comes in very small capacity. The bottom of this pyramid represents technologies like disk or tape that are very inexpensive, have large capacity but have very high latency. Regardless of the type there are some key similarities among these different memories.
Depending on the manufacture or chipset, most micro controllers contains some internal amounts of memory. Chipset vendors usually design multiple chips in a sub family series all with varying amounts of memory. These memories do not typically list the peripheral or register memory but rather just the flash and RAM memory.
In the example above you can see the different size of Flash and SRAM memory, or the different CALE micro controllers. Flash ranges from 32k to 256k, and SRAM ranges from 4K to 32k. As you can see in this example, we typically have less SRAM memory than flash (SRAM < Flash). This is because flash memory contains our program code and SRAM contains our program data. Typically, our programs tend to be larger, and that space is not overwritten. Whereas program data is typically overwritten many times during the iteration of a program.
On a microcontroller, your memory size should not be chosen arbitrarily. Some amount of effort should go into sizing, or figuring out what your memory footprint will be before selecting a platform. This leads to our next discussion about memory, and that is the software to hardware translation. You may want to visualize memory as a runtime type of concept. But you should note that there is an important role that memory plays in the build and address allocation process. Our programs’ compilation process requires special information on the target architecture we need to compile for. We’ve provided a compile time flag to specify this. In addition, the build system needs a description of what memory regions are. These are provided to us via a linker file.
Memory is used to store all of our program code, program data, as well as the runtime state of our program. The linker file provides a segment, and sub segment code to memory mapping. This allows the build to translate a real, pitable program, to a program with assigned addresses. There were two main memories for this process, code and data. Code memory store information statically like flash which does not need power to retain information. In contrast, Data memory stores dynamically like RAM, but Ram requires power to retain information.
The flash and ram memories usually need some type of dedicated controller to configure, read, and write data. These controllers are usually built into the microcontroller, and they communicate with the cpu via a bus. If the internal memory is not enough, you can add external memory to your system, depending on how much hardware you can add to your board, that won’t cut into the interfaces your microcontroller supports. Below is an illustration of an external EEPROM connected the SPI. In this example EEPROM likely access an extra non-valuable code and data memory for the micro processor. However, SPI communication is needed to write or read any data from it.
In addition to code and data, we have Runtime Data not associated with the install program. This is referred to as register memory and it lives all over the microcontroller. Registers hold data that is used by the CPU and the peripherals to store runtime information or the state of a program. These internal registers are a mixture of peripheral, general purpose, and special purpose registers. However, usually there are very few CPU and peripheral registers. The CPU Registers themselves are a key component to how a microcontroller actually performs operations. These general purpose registers store the operands, a CPU instructions operate on. Special purpose registers dictate the state of a program, such as a current instruction or the program counter. (See the figure below)