You are on page 1of 53

Chương 4.

2:
Quản lý tài nguyên và bộ nhớ
với FreeRTOS
2
Resource & Memory Management

Giới thiệu về các bộ nhớ của Arduino

Cấp phát bộ nhớ trong FreeRTOS

Quản lý bộ nhớ Heap trong FreeRTOS


3
Arduino Memory

 Arduino Memory Map:


 https://www.arduino.cc/en/Tutorial/Foundatio
ns/Memory
 avr-based Arduino boards :There are three
pools of memory in the microcontroller used
on
 Flash memory (program space), is where the
Arduino sketch is stored.
 SRAM (static random access memory) is
where the sketch creates and manipulates
variables when it runs.
 EEPROM is memory space that
programmers can use to store long-term
information.
 Flash memory and EEPROM memory are non-
volatile (the information persists after the
power is turned off). SRAM is volatile and will
be lost when the power is cycled.
4
Memory Architecture

 One essential part of a microcontroller is its memory


 Memory stores information temporarily or permanently in microcontrollers, and can be used for
several purposes.
 In this part, we will explore:
 Memory organization in microcontrollers, focusing on those present in Arduino® boards.
 Several ways to manage, measure, and optimize memory usage in Arduino-based systems.
5
Memory Architecture

 Memory blocks are essential parts of modern embedded systems, especially microcontroller-based
ones.
 Memory blocks are semiconductor devices that store and retrieve information or data; a
microcontroller central processing unit (CPU) uses and processes data stored in memory blocks to perform
specific tasks.
 As shown in the image below, memory blocks in microcontrollers are usually described as arrays.
 Memory arrays are divided into cells that can store data and be accessed using a unique identifier
representing its address or position relative to the memory array. Information in memory cells is stored
using binary digits (bits), usually organized in bytes (8-bits); it can also be retrieved later by the MCU or
other components of a microcontroller-based system.
 Memory in computing systems can be volatile or non-volatile.
 Volatile memory is a temporary memory, this means that data is stored while the system is running, but it
is lost forever when the system is turned off.
 Non-volatile memory is permanent memory; data is not lost even if the system is turned off.
6
Memory Architecture

 Memory Architectures: Von Neumann and Harvard


7
Memory Architecture

 Memory Architectures: Von Neumann


 Named after the mathematician, physicist,
and computer scientist John Von
Neumann, was first introduced in the mid
'40s. It is also known as the Princeton
architecture.
 This architecture stores program data and
instructions in the same memory unit.
Both are accessed by the CPU using the
same communications bus.
 Von Neumann's architecture is
fundamental since nearly all digital
computers design have been based on
this architecture.
8
Memory Architecture

 Memory Architectures: Harvard


 Named after the Harvard Mark I relay-
based computer, was first introduced in
the mid '40s.
 This architecture's main characteristic is
that it uses two separate memory units,
one for storing program instructions and
one for storing program data.
 Both memory units in the Harvard
architecture are accessed by the CPU
using different communication buses.
9
Memory Architecture

 Modern Architectures: Hybrids


 Modern computing systems use hybrid architectures models that maximize performance using the
best of both worlds, the von Neumann and the Harvard models.
 Microcontrollers are usually used in embedded applications.
 They must perform defined tasks reliably and efficiently, with low or constrained resources; this is
why the Harvard architecture model is mainly used in microcontrollers: microcontrollers have a
small program and data memory that needs to be accessed simultaneously.
 However, Harvard architecture is not always used in microcontrollers; some microcontroller families
use hybrid or Von Neumann architecture models.
10
Arduino® Boards Architectures

 Arduino® boards are mainly based on two families of microcontrollers: AVR® and ARM®.
 AVR® family microcontrollers are based on the Harvard architecture model
 ARM® family microcontrollers can be based on either von Neuman or Harvard architectures models.
 The following table summarizes Arduino boards microcontrollers architectures:
11
Arduino® Boards Architectures

 Arduino® boards are mainly based on two families of microcontrollers: AVR® and ARM®.
 AVR® family microcontrollers are based on the Harvard architecture model
 ARM® family microcontrollers can be based on either von Neuman or Harvard architectures models.
 The following table summarizes Arduino boards microcontrollers architectures:
12
Arduino® Boards Architectures

 Arduino® boards are mainly based on two families of microcontrollers: AVR® and ARM®.
 AVR® family microcontrollers are based on the Harvard architecture model
 ARM® family microcontrollers can be based on either von Neuman or Harvard architectures models.
 The following table summarizes Arduino boards microcontrollers architectures:
13
Memory Types

 All the different memory units inside a microcontroller can be divided into two main
types: RAM and ROM.
 RAM (from Random-Access Memory) in microcontroller-based systems is a volatile memory used to
store temporary data such as the system's firmware variables.
 ROM (from Read-Only Memory) in microcontroller-based systems is non-volatile memory used to
store permanent data such as the system's firmware.
 RAM and ROM in microcontroller-based systems are organized into three main categories:
 Flash
 RAM
 EEPROM
14
Memory Types

 Flash
 Flash memory in microcontroller-based systems is part of its ROM. The flash memory is where the
system's firmware is stored to be executed. For example, think of the famous Blink.ino sketch: when
we compile this sketch, we create a binary file that is later stored in the flash memory of an Arduino
board. The sketch is then executed when the board is powered on.
 RAM in microcontroller-based systems is where the system's temporary data or run-time
data is stored;
 for example, the variables created by functions of a program. RAM in microcontrollers usually
is SRAM; this is a type of RAM that uses a flip-flop to store one bit of data. There is also another type
of RAM that can be found in microcontrollers: DRAM.
 EEPROM: In microcontroller-based systems, Erasable Programmable Read-Only Memory, or
EEPROM, is also part of its ROM; actually, Flash memory is a type of EEPROM.
 The main difference between Flash memory and EEPROM is how they are managed; EEPROM can
be managed at the byte level (write or erased) while Flash can be managed at the block level.
15
Arduino® Boards Memory Allocation

 AVR memory map


 How their SRAM is organized into different
sections:
 Text: contains instructions loaded into the flash
memory
 Data: contains variables initialized in the sketch
 BSS: contains uninitialized data
 Stack: stores data of functions and interrupts
 Heap: stores variables created during run time
16
Memory Types

 In hybrid ARM architectures, a so called memory map is implemented, with a different


address map configuration of 32-bit, 36-bit, and 40-bit that depends on the requirement of
System On a Chip (SoC) address space with extra DRAM.
 The Memory Map grants interface with SoC design, while having most system control on a high level
coding. Memory access instructions can be used on high level code to manage interrupt modules
and built-in peripherals. All of this controlled by Memory Management Unit (MMU).
 The memory resource is handled by the MMU.
 The main role of the MMU is to enable the processor to run multiple tasks independently in its own
virtual memory space; the MMU then uses translation tables to establish a bridge between the virtual
and the physical memory addresses.
 Virtual Address is managed via software with memory instructions, and Physical address is the
memory system that is controlled depending on the Translation Table input given by the Virtual
Address.
17
Arduino® Boards Memory Allocation

 Memory organization in ARM-based


microcontrollers:
 The ARM-based microcontroller's memory is
organized into the following sections within the
address type mentioned previously:
 Virtual address:
 Kernel code and data
 Application code and data
 Physical address:
 ROM
 RAM
 Flash
 Peripherals
18
Memory Types

 Measuring Memory Usage in Arduino® Boards:


 Flash, SRAM, EEPROM
 Optimizing Memory Usage in Arduino-based Systems:
 https://docs.arduino.cc/learn/programming/memory-guide/
19
Resource & Memory Management

Giới thiệu về các bộ nhớ của Arduino

Cấp phát bộ nhớ trong FreeRTOS

Quản lý bộ nhớ Heap trong FreeRTOS


20
Memory Allocation in FreeRTOS

 Stack and Heap


 Malloc() and Free()
 FreeRTOS Dynamic/Static Memory Allocation
21
Memory Allocation in FreeRTOS

 RAM:
 TCB
 SCB
 QCB
 RAM space is used for Global data, arrays, static variables, …
22
Memory Allocation in FreeRTOS

 2 options:
 If you use dynamic creation method then they will be created in the heap memory of the RAM
 If you create them statically then they will be created in other part of the RAM except heap and stack space
23
Memory Allocation in FreeRTOS

 By default, the FreeRTOS heap is declared by kernel


 Setting configAPPLICATION_ALLOCATED_HEAP to 1 allows the
heap to instead be declared by the application
 configTOTAL_HEAP_SIZE
24
Memory Allocation in FreeRTOS

 By default,
25
Memory Allocation in FreeRTOS

 Malloc() and Free()


26
Memory Allocation in FreeRTOS

 FreeRTOS Dynamic/Static Memory Allocation:


 FreeRTOS versions prior to V9.0.0 allocate the memory used by the RTOS objects listed below from the
special FreeRTOS heap.
 FreeRTOS V9.0.0 and onwards gives the application writer the ability to instead provide the memory
themselves, allowing the following objects to optionally be created without any memory being allocated
dynamically:
 Tasks
 Software Timers
 Queues
 Event Groups
 Binary Semaphores
 Counting Semaphores
 Recursive Semaphores
 Mutexes
27
Memory Allocation in FreeRTOS

 FreeRTOS Dynamic/Static Memory Allocation:


 Whether it is preferable to use static or dynamic memory allocation is
dependent on the application, and the preference of the application
writer.
 Both methods have pros and cons, and both methods can be used within
the same RTOS application.
 The simple Win32 example located in the FreeRTOS/Source/WIN32-
MSVC-Static-Allocation-Only directory of the main FreeRTOS download
demonstrates how a FreeRTOS application can be created without
including any of the FreeRTOS heap implementations in a project.
28
Memory Allocation in FreeRTOS

 FreeRTOS Dynamic/Static Memory Allocation:


 Creating an RTOS Object Using Dynamically Allocated RAM
 Creating RTOS objects dynamically has the benefit of greater simplicity, and the potential to
minimise the application's maximum RAM usage:
 Fewer function parameters are required when an object is created.
 The memory allocation occurs automatically, within the RTOS API functions.
 The application writer does not need to concern themselves with allocating memory themselves.
 The RAM used by an RTOS object can be re-used if the object is deleted, potentially reducing the
application's maximum RAM footprint.
 RTOS API functions are provided to return information on heap usage, allowing the heap size to be
optimised.
 The memory allocation scheme used can be chosen to best suite the application, be that heap_1.c for
simplicity and determinism often necessary for safety critical applications, heap_4.c for fragmentation
protection, heap_5.c to split the heap across multiple RAM regions, or an allocation scheme provided
by the application writer themselves.
29
Memory Allocation in FreeRTOS

 FreeRTOS Dynamic/Static Memory Allocation:


 Creating an RTOS Object Using Dynamically Allocated RAM
 The following API functions, which are available if configSUPPORT_DYNAMIC_ALLOCATION is set
to 1 or left undefined, create RTOS objects using dynamically allocated RAM:
30
Memory Allocation in FreeRTOS

 FreeRTOS Dynamic/Static Memory Allocation:


 Creating an RTOS Object Using Statically Allocated RAM
 Creating RTOS objects using statically allocated RAM has the benefit of providing the
application writer with more control:
 RTOS objects can be placed at specific memory locations.
 The maximum RAM footprint can be determined at link time, rather than run time.
 The application writer does not need to concern themselves with graceful handling of memory
allocation failures.
 It allows the RTOS to be used in applications that simply don't allow any dynamic memory
allocation (although FreeRTOS includes allocation schemes that can overcome most
objections).
31
Memory Allocation in FreeRTOS

 FreeRTOS Dynamic/Static Memory Allocation:


 Creating an RTOS Object Using Statically Allocated
RAM
 The following API functions, which are available
if configSUPPORT_STATIC_ALLOCATION is set to 1, allow RTOS
objects to be created using memory provided by the application
writer.
 To provide memory the application writer simply needs to declare a
variable of the appropriate object type, then pass the address of the
variable into the RTOS API function.
 The StaticAllocation.c standard demo/test task is provided to
demonstrate how the functions are used:
32
Memory Allocation in FreeRTOS

 Resource Management:
 Using Mutex
 Using Couting Semaphore
 The count value indicates number of available resources
 To get a resource, a task must obtain (take) a semaphore
 When a task finishes with the resource, it 'gives' the semaphore back
Tham khảo thêm:
https://www.youtube.com/watch?v=AsZcF3pVlvY&list=PLaN_SFaG
u-90sD41MHD_6YOw_4CYQm5yx&index=7
33
Resource & Memory Management

Giới thiệu về các bộ nhớ của Arduino

Cấp phát bộ nhớ trong FreeRTOS

Quản lý bộ nhớ Heap trong FreeRTOS


34
Heap Memory Management in FreeRTOS

 FreeRTOS Memory Management


35
Heap Memory Management in FreeRTOS

 The RTOS kernel needs RAM each time a task, queue, mutex, software timer, semaphore or
event group is created.
 The RAM can be automatically dynamically allocated from the RTOS heap within the RTOS
API object creation functions, or it can be provided by the application writer.
 If RTOS objects are created dynamically then the standard C library malloc() and free()
functions can sometimes be used for the purpose, but:
 they are not always available on embedded systems,
 they take up valuable code space,
 they are not thread safe, and
 they are not deterministic (the amount of time taken to execute the function will differ from call to
call)…
 So more often than not an alternative memory allocation implementation is required.
36
Heap Memory Management in FreeRTOS

 One embedded/real time system can have very different RAM and timing requirements to
another => A single RAM allocation algorithm will only ever be appropriate for a subset of
applications.
 To get around this problem, FreeRTOS keeps the memory allocation API in its portable layer.
 The portable layer is outside of the source files that implement the core RTOS functionality, allowing
an application specific implementation appropriate for the real time system being developed to be
provided.
 When the RTOS kernel requires RAM, instead of calling malloc(), it instead calls pvPortMalloc().
When RAM is being freed, instead of calling free(), the RTOS kernel calls vPortFree().
37
Heap Memory Management in FreeRTOS

 FreeRTOS offers several heap management schemes that range in complexity and features.
It is also possible to provide your own heap implementation, and even to use two heap
implementations simultaneously.
 Using two heap implementations simultaneously permits task stacks and other RTOS objects
to be placed in fast internal RAM, and application data to be placed in slower external RAM.
 The FreeRTOS download includes five sample memory allocation implementations (Figure.)
 Other implementations can be added as needed. Exactly one of these source files should be
included in a project at a time [the heap defined by these portable layer functions will be used
by the RTOS kernel even if the application that is using the RTOS opts to use its own heap
implementation].
38
Heap Memory Management in FreeRTOS

 Five sample memory allocation


implementations:
 heap_1 - the very simplest, does not
permit memory to be freed.
 heap_2 - permits memory to be freed,
but does not coalescence adjacent free
blocks.
 heap_3 - simply wraps the standard
malloc() and free() for thread safety.
 heap_4 - coalescences adjacent free
blocks to avoid fragmentation. Includes
absolute address placement option.
 heap_5 - as per heap_4, with the ability
to span the heap across multiple non-
adjacent memory areas.
39
Heap Memory Management in FreeRTOS

 In FreeRTOS download:
40
Heap Memory Management in FreeRTOS

 Heap1.c
41
Heap Memory Management in FreeRTOS

 Heap1.c
 Does not permit memory to be freed once it has been allocated. Despite this, heap_1.c is appropriate
for a large number of embedded applications.
 This is because many small and deeply embedded applications create all the tasks, queues, semaphores, etc.
required when the system boots, and then use all of these objects for the lifetime of program (until the
application is switched off again, or is rebooted). Nothing ever gets deleted.
 The xPortGetFreeHeapSize() API function returns the total amount of heap space that remains
unallocated, allowing the configTOTAL_HEAP_SIZE setting to be optimised.
 The heap_1 implementation:
 Can be used if your application never deletes a task, queue, semaphore, mutex, etc. (which actually covers the
majority of applications in which FreeRTOS gets used).
 Is always deterministic (always takes the same amount of time to execute) and cannot result in memory
fragmentation.
 Is very simple and allocated memory from a statically allocated array, meaning it is often suitable for use in
applications that do not permit true dynamic memory allocation.
42
Heap Memory Management in FreeRTOS

 Heap2.c
43
Heap Memory Management in FreeRTOS

 Heap2.c
 heap_2 uses a best fit algorithm and, unlike scheme 1, allows previously allocated blocks to
be freed. It does not combine adjacent free blocks into a single large block.
 See heap_4.c for an implementation that does coalescence free blocks.
 The xPortGetFreeHeapSize() API function returns the total amount of heap space that
remains unallocated, (allowing the configTOTAL_HEAP_SIZE setting to be optimised), but
does not provided information on how the unallocated memory is fragmented into smaller
blocks.
 The pvPortCalloc() function has the same signature as the standard library calloc function.
 It allocates memory for an array of objects and initializes all bytes in the allocated storage to zero.
 If allocation succeeds, it returns a pointer to the lowest byte in the allocated memory block. On
failure, it returns a null pointer.
44
Heap Memory Management in FreeRTOS

 Heap2.c
 This implementation:
 Can be used even when the application repeatedly deletes tasks, queues, semaphores, mutexes, etc., with the caveat
below regarding memory fragmentation.
 Should not be used if the memory being allocated and freed is of a random size. For example:
 If an application dynamically creates and deletes tasks, and the size of the stack allocated to the tasks being created is
always the same, then heap2.c can be used in most cases. However, if the size of the stack allocated to the tasks being
created was not always the same, then the available free memory might become fragmented into many small blocks,
eventually resulting in allocation failures. (heap_4.c would be a better choise in this case)
 If an application dynamically creates and deletes queues, and the queue storage area is the same in each case (the
queue storage area is the queue item size multiplied by the length of the queue), then heap_2.c can be used in most
cases. However, if the queue storage area were not the same in each case, then the available free memory might become
fragmented into many small blocks, eventually resulting in allocation failures. (heap_4.c would be a better choise in this
case).
 The application called pvPortMalloc() and vPortFree() directly, rather than just indirectly through other FreeRTOS
API functions.
 Could possible result in memory fragmentation problems if your application queues, tasks, semaphores, mutexes, etc.
in an unpredictable order. This would be unlikely for nearly all applications but should be kept in mind.
 Is not deterministic - but is much more efficient that most standard C library malloc implementations.
45
Heap Memory Management in FreeRTOS

 Heap3.c
 This implements a simple wrapper for the standard C library malloc() and free() functions that
will, in most cases, be supplied with your chosen compiler.
 The wrapper simply makes the malloc() and free() functions thread safe.
 This implementation:
 Requires the linker to setup a heap, and the compiler library to provide malloc() and free()
implementations.
 Is not deterministic.
 Will probably considerably increase the RTOS kernel code size.
 Note that the configTOTAL_HEAP_SIZE setting in FreeRTOSConfig.h has no effect when
heap_3 is used.
46
Heap Memory Management in FreeRTOS

 Heap4.c
47
Heap Memory Management in FreeRTOS

 Heap4.c
 This scheme uses a first fit algorithm and, unlike scheme 2, it does combine adjacent free
memory blocks into a single large block (it does include a coalescence algorithm).
 The total amount of available heap space is set by configTOTAL_HEAP_SIZE - which is defined
in FreeRTOSConfig.h. The configAPPLICATION_ALLOCATED_HEAP FreeRTOSConfig.h
configuration constant is provided to allow the heap to be placed at a specific address in
memory.
 The xPortGetFreeHeapSize() API function returns the total amount of heap space that remains
unallocated when the function is called, and the xPortGetMinimumEverFreeHeapSize() API
function returns lowest amount of free heap space that has existed system the FreeRTOS
application booted. Neither function provides information on how the unallocated memory is
fragmented into smaller blocks.
 The vPortGetHeapStats() API function provides additional information
48
Heap Memory Management in FreeRTOS

 Heap4.c
 The pvPortCalloc() function has the same signature as the standard library calloc function.
 This implementation:
 Can be used even when the application repeatedly deletes tasks, queues, semaphores, mutexes, etc..
 Is much less likely than the heap_2 implementation to result in a heap space that is badly fragmented
into multiple small blocks - even when the memory being allocated and freed is of random size.
 Is not deterministic - but is much more efficient that most standard C library malloc implementations.
 heap_4.c is particularly useful for applications that want to use the portable layer memory
allocation schemes directly in the application code (rather than just indirectly by calling API
functions that themselves call pvPortMalloc() and vPortFree())
49
Heap Memory Management in FreeRTOS

 Heap5.c
 This scheme uses the same first fit and memory coalescence algorithms as heap_4, and
allows the heap to span multiple non adjacent (non-contiguous) memory regions.
 Heap_5 is initialised by calling vPortDefineHeapRegions(), and cannot be used until after
vPortDefineHeapRegions() has executed.
 Creating an RTOS object (task, queue, semaphore, etc.) will implicitly call pvPortMalloc() so it
is essential that, when using heap_5, vPortDefineHeapRegions() is called before the creation
of any such object.
 vPortDefineHeapRegions() takes a single parameter. The parameter is an array of HeapRegion_t
structures
50
Heap Memory Management in FreeRTOS

 Heap5.c
 The xPortGetFreeHeapSize() API function returns the total amount of heap space that
remains unallocated when the function is called,
 The xPortGetMinimumEverFreeHeapSize() API function returns lowest amount of free heap
space that has existed system the FreeRTOS application booted.
 Neither function provides information on how the unallocated memory is fragmented into
smaller blocks.
 The pvPortCalloc() function has the same signature as the standard library calloc function.
 The vPortGetHeapStats() API function provides additional information on the heap status.
51

Q&A
52
Câu hỏi ôn tập Chương 4

 Câu 1: Mô tả về cách thức phân bổ bộ nhớ RAM của HĐH FreeRTOS?


 Tham khảo: https://www.youtube.com/watch?v=bLQWB4H0TpE
 Câu 2: Cấp phát bộ nhớ là gì? Phân biệt cấp phát bộ nhớ động và cấp phát bộ nhớ tĩnh
trong FreeRTOS. Cho ví dụ minh họa
 Tham khảo: Understanding memory allocation, Static and dynamic allocation of
FreeRTOS primitives (P381-393, [1.1])
 Câu 3: Hãy chỉ ra các hàm API của FreeRTOS yêu cầu cấp phát bộ nhớ tĩnh/động
 Tham khảo: https://www.freertos.org/Static_Vs_Dynamic_Memory_Allocation.html
 Câu 4: Mô tả đặc điểm của 5 thư viện (triển khai cấp phát bộ nhớ mẫu) quản lý bộ nhớ
Heap của FreeRTOS
 Tham khảo: https://www.freertos.org/a00111.html
53
Bài tập thực hành TH9 – Memory Management

 TH9.1: FreeRTOS Memory Management Demo


 Tham khảo:
https://www.digikey.com/en/maker/projects/introduction-to-rtos-solution-to-part-4-
memory-management/6d4dfcaa1ff84f57a2098da8e6401d9c
https://www.youtube.com/watch?v=Qske3yZRW5I (Từ 6’00)
 TH9.2: Resoure Management – Arduino
 https://www.youtube.com/watch?v=3OPX7U3K4ug&t=43s
 TH9.3: Demo Heap5.c
 (File word kèm 4.2.Example_DemoHeap5c.docx)
 TH9.4: Implementing Malloc with FreeRTOS
 https://embeddedartistry.com/blog/2018/01/15/implementing-malloc-with-freertos/

You might also like