Memory segments API has been introduced with µC/LIB v1.38. They offer the possibility to create segments of memory at different locations and to allocate buffers from them.
Three different functions are available to allocate memory from a memory segment:
Function | Description | Use case |
---|---|---|
Mem_SegAlloc() | General-purpose allocation function. It will provide a buffer aligned on a CPU word boundary and with no guaranteed padding. | General purpose buffers and control data accessed only by the CPU. |
Mem_SegAllocExt() | Same as Mem_SegAlloc() , except that this function allows specifying an alignment. It will also provide the amount of bytes required to prevent overflow when the memory segment's size limit is exceeded. | General purpose buffers and control data accessed only by the CPU but that require specific alignment (for example, task stacks). |
Mem_SegAllocHW() | Allocates a buffer using specified alignment. This function will also add padding at the end of the buffer according to the padding_align argument specified at the creation of the memory segment. This is useful on systems that use cache memory as it allows to have nothing else than the buffer mapped over all its associated cache lines. | Data buffers that can be copied via a DMA engine. |
Example usage of memory segments
Listing - Memory Segment Usage Example gives an example usage of memory segments. In this example, we attempt to create a memory segment and to allocate three buffers of 20 bytes from it using the three different segment allocation functions available. Following the listing is an explanation of the differences between these three buffers.
#define CACHE_LINE_LEN 32u static CPU_INT08U MemSegData[4096u]; static MEM_SEG MemorySegment; static void Mem_SegExample (void) { CPU_INT08U *p_general_purpose_buf; CPU_INT08U *p_general_purpose_buf_with_align; CPU_INT08U *p_hardware_buffer; LIB_ERR err_lib; /* ------------ CREATION OF MEMORY SEGMENT ------------ */ (1) Mem_SegCreate( "Name", /* Name of mem seg (for debugging purposes). */ &MemorySegment, /* Pointer to memory segment structure. */ (CPU_ADDR)MemSegData, /* Base address of memory segment data. */ 4096u, /* Length, in byte, of the memory segment. */ CACHE_LINE_LEN, /* Padding alignment value. */ &err_lib); if (err_lib != LIB_MEM_ERR_NONE) { /* Validate memory segment creation is successful. */ /* Handle error case. */ return; } /* ------- ALLOCATION OF GENERAL PURPOSE BUFFER ------- */ (2) p_general_purpose_buf = Mem_SegAlloc("General purpose buffer", &MemorySegment, 20u, /* Requested buffer length. */ &err_lib); if (err_lib != LIB_MEM_ERR_NONE) { /* Validate memory segment allocation is successful. */ /* Handle error case. */ return; } /* --- ALLOCATION OF ALIGNED GENERAL PURPOSE BUFFER --- */ (3) p_general_purpose_buf_with_align = Mem_SegAllocExt("General purpose buffer aligned", &MemorySegment, 20u, 8u, /* Request 8 bytes boundary alignment. */ DEF_NULL, &err_lib); if (err_lib != LIB_MEM_ERR_NONE) { /* Validate memory segment allocation is successful. */ /* Handle error case. */ return; } /* ---------- ALLOCATION OF HARDWARE BUFFER ----------- */ (4) p_hardware_buffer = Mem_SegAllocHW("Buffer read/written via DMA engine", &MemorySegment, 20u, 1024u, /* DMA engine required alignment. */ DEF_NULL, &err_lib); if (err_lib != LIB_MEM_ERR_NONE) { /* Validate memory segment allocation is successful. */ /* Handle error case. */ return; } /* ... */ }
(1) Creation of the memory segment. The memory segment will be created on a statically allocated buffer of 4096 bytes. The base address of the memory segment data can also point to a controller dedicated memory.
(2) Allocation of a general-purpose buffer. p_general_purpose_buf
is intended to be used as a control buffer and is only read/written by the CPU. This buffer will automatically be aligned on CPU word boundary.
(3) Allocation of a general-purpose buffer with specified alignment. p_general_purpose_buf_with_align
will be allocated from the memory segment but will be aligned on an 8-bytes boundary.
(4) Allocation of an hardware buffer (a buffer that can be read/written from a DMA engine). p_hardware_buffer
will be allocated from the memory segment and will be aligned on a 1024 bytes boundary. The difference with
is that this buffer will have a real length of 32 bytes as it will be padded using the padding alignment specified at the time of the memory segment creation at (1). The p_general_purpose_buf_with_align
padding_align
argument was set to a cache line length. This buffer is guaranteed to not share its memory cache line with other buffer hence preventing cache incoherence.