RTX5. Управление памятью

CMSIS-RTOS API v2 предлагает два варианта управления памятью, которые может выбрать пользователь. Для хранения объектов можно использовать

  • Автоматическое динамическое распределение памяти (полностью переносимое), или
  • Ручное пользовательское распределение памяти (зависит от конкретной реализации).

Для того, чтобы повлиять на распределение памяти, все объекты RTOS, которые могут быть созданы по запросу, то есть объекты, имеющие функцию osXxxNew, принимают необязательный аргумент osXxxAttr_t attr при создании. Как правило, атрибуты объекта, как минимум, имеют элементы для назначения пользовательской памяти блока управления, то есть элементы cb_mem и cb_size. По умолчанию, т.е. Attr равен NULL или cb_mem равен NULL, используется автоматическое динамическое распределение памяти. Указатель на пользовательскую память в параметре cb_mem переключает на ручное пользовательское распределение. Для получения подробной информации о стратегиях выделения памяти, представленных в RTX5, смотрите раздел Выделение памяти

Автоматическое динамическое распределение памяти

Автоматическое распределение является значением по умолчанию и является жизнеспособным для многих вариантов использования. Более того, он полностью переносим между различными реализациями CMSIS-RTOS API v2. Общим недостатком динамического выделения памяти является возможность фрагментации и исчерпания памяти. Учитывая, что все необходимые объекты создаются один раз при инициализации системы и никогда не удаляются во время выполнения, этот класс сбоев во время выполнения можно предотвратить.

Фактическая используемая стратегия выделения зависит от реализации, то есть используется ли глобальная куча или предварительно выделенные пулы памяти.

Пример кода, мьютексы в этом примере создаются с использованием автоматического выделения памяти:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "cmsis_os2.h"                          // независимость от реализации
 
osMutexId_t mutex_id;
osMutexId_t mutex2_id;
 
const osMutexAttr_t Thread_Mutex_attr = {
  "myThreadMutex",                              // удобочитаемое имя мьютекса
  osMutexRecursive | osMutexPrioInherit,        // attr_bits
  NULL,                                         // память для блока управления (по умолчанию)
  0U                                            // размер для блока управления (по умолчанию)
};
 
void CreateMutex (void)  {
  mutex_id = osMutexNew(NULL);                // использовать значения по умолчанию для всех атрибутов
  mutex2_id = osMutexNew(&Thread_Mutex_attr); // использовать атрибуты из структуры Thread_Mutex_attr
  :
}

Ручное пользовательское распределение памяти

Можно получить точный контроль над распределением памяти, предоставляя пользовательскую память. Фактические требования к такой пользовательской памяти зависят от реализации. Таким образом, необходимо тщательно следить за размером и правилом выравнивания в используемой реализации, например, для RTX смотрите раздел  Статическая память.

Пример кода:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "rtx_os.h" // конкретная реализация
 
osMutexId_t mutex_id;
 
static uint32_t mutex_cb[osRtxMutexCbSize/4U]; // конкретная реализация
 
const osMutexAttr_t Thread_Mutex_attr = {
"myThreadMutex", // удобочитаемое имя мьютекса
osMutexRecursive | osMutexPrioInherit, // attr_bits
mutex_cb, // память для блока управления (определяется пользователем)
sizeof(mutex_cb) // размер для блока управления (определяется пользователем)
};
 
void CreateMutex (void) {
mutex_id = osMutexNew(&Thread_Mutex_attr); // использовать атрибуты из определенной структуры
:
}

В приведенном выше примере используется пользовательская память для блока управления мьютексом. В зависимости от фактической используемой реализации необходимо подключить определенный заголовочный файл, в данном случае rtx_os.h.

Оставить ответ