System Memory Management

During normal operation, the system repeatedly allocates and releases memory blocks within RAM. Configuration settings determine whether these blocks are allocated from the general heap (user RAM) or from a dedicated memory area reserved exclusively for the operating system. Additionally, the system supports two primary allocation mechanisms: dynamic memory allocation and fixed-size memory block allocation.

Global and Internal Memory

During system configuration, it must be determined whether the system should utilize the entire RAM area or a restricted, dedicated region. This is controlled by the OS_INTERNAL_MEMORY_SIZE constant.

If the entire RAM area is used (OS_INTERNAL_MEMORY_SIZE set to 0), the system utilizes stMemAlloc and stMemFree to manage memory within the user area. This configuration is recommended only when it is certain that memory leaks will not occur in the user application, as such leaks could compromise system data integrity.

Alternatively, the system can utilize a private memory pool. The size of this pool is defined by OS_INTERNAL_MEMORY_SIZE. In this mode, a global buffer is created for exclusive use by the system to perform all internal allocation and release operations.

In both cases, memory management within the Standard Library must be enabled by setting ST_USE_MEMORY to 1. Note that OS_INTERNAL_MEMORY_SIZE is ignored if OS_USE_FIXMEM_POOLS (described below) is set to 1.

Fixed-Size Memory Pools

For real-time applications where determinism is critical, it is recommended to use the fixed-size memory block allocation algorithm instead of general-purpose dynamic allocation.

The system employs this deterministic algorithm when OS_USE_FIXMEM_POOLS is set to 1. The configuration allows for the creation of one to four distinct memory pools. The total size of each pool is defined by OS_FIX_POOL*_SIZE (where * represents the pool index from 0 to 3); setting this to zero disables the respective pool. The individual block size for each pool is defined by the OS_FIX_POOL*_ITEM_SIZE constant.

If only one memory pool is defined, all system allocations are drawn from that area. If multiple pools are defined, the system optimizes allocation by selecting the smallest available block size that satisfies the request. The system always attempts to allocate from the first pool; if the block size is insufficient, it proceeds to the next pool. Consequently, block sizes must be defined in ascending order across the pools. The recommended pool applications are as follows:

  • Memory Pool #0: Recommended block size of 20-32 bytes. This pool is typically used when an object is opened by a task. If this functionality is not required, the pool may be disabled. For details, see the system objects management section.
  • Memory Pool #1: Recommended block size of 128-256 bytes. These blocks are suitable for small objects such as events, counting semaphores, and timers.
  • Memory Pool #2: Recommended block size of 256-512 bytes, depending on configuration. This pool is intended for larger objects, such as task control blocks.
  • Memory Pool #3: This pool is dedicated to objects requiring significant buffers, such as shared memory, pointer queues, and streams. The block size should be large enough to accommodate both the object structure and its associated buffer (e.g., for a 1 KB buffer, the block should be approximately 128-512 bytes plus 1024 bytes).

While these settings are recommended, they may be customized to optimize memory footprint. For instance, if an application only utilizes events, mutexes, semaphores, and tasks, each pool can be tailored specifically to the size of those individual object types.

When this method is employed, fixed-size memory management in the Standard Library must be enabled by setting ST_USE_FIXMEM to 1.

SpaceShadow documentation