очередь сообщений
в предыдущем посте[TencentOS крошечное обучение] Анализ исходного кода (3) — очередьМы описали реализацию очереди TencentOS tiny, а также указали, что очередь TencentOS tiny зависит от очереди сообщений, поэтому давайте сегодня рассмотрим реализацию очереди сообщений.
На самом деле очередь сообщений — одна из самых крошечных в TencentOS.основные компоненты, как нижний слой очереди. так вtos_config.h
будут использовать следующие определения макросов:
#if (TOS_CFG_QUEUE_EN > 0u)
#define TOS_CFG_MSG_EN 1u
#else
#define TOS_CFG_MSG_EN 0u
#endif
Инициализация пула системных сообщений
Во время инициализации системы (tos_knl_init()
), система инициализирует пул сообщений, среди которыхmsgpool_init()
Функция используется для инициализации пула сообщений, и определение этой функции находится в tosВ файле msg.c реализация функции в основном осуществляется черезfor
цикл, пул сообщений `kmsgpool[TOSCFGMSGPOOLSIZE]的成员变量进行初始化,初始化对应的列表节点,并且将它挂载到空闲消息列表上
kСхематическая диаграмма завершения инициализации msg_freelist`: (при условии, что сообщений всего 3)
__KERNEL__ void msgpool_init(void)
{
uint32_t i;
for (i = 0; i < TOS_CFG_MSG_POOL_SIZE; ++i) {
tos_list_init(&k_msg_pool[i].list);
tos_list_add(&k_msg_pool[i].list, &k_msg_freelist);
}
}
__API__ k_err_t tos_knl_init(void)
{
···
#if (TOS_CFG_MSG_EN) > 0
msgpool_init();
#endif
···
}
создание очереди сообщений
Эта функция будет вызываться при создании очереди.Конечно, она также может быть предоставлена пользователям как пользовательский интерфейс API, а не только интерфейс API ядра. Суть этой функции заключается в инициализации списка сообщений в очереди сообщенийqueue_head
. Принципиальная схема завершения инициализации:
__API__ k_err_t tos_msg_queue_create(k_msg_queue_t *msg_queue)
{
TOS_PTR_SANITY_CHECK(msg_queue);
#if TOS_CFG_OBJECT_VERIFY_EN > 0u
knl_object_init(&msg_queue->knl_obj, KNL_OBJ_TYPE_MSG_QUEUE);
#endif
tos_list_init(&msg_queue->queue_head);
return K_ERR_NONE;
}
уничтожение очереди сообщений
tos_msg_queue_destroy()
Функция используется для уничтожения очереди сообщений.Когда очередь сообщений не используется, ее можно уничтожить.Суть уничтожения заключается в очистке содержимого блока управления очередью сообщений.Во-первых, определить тип управления очередью сообщений блокировать.KNL_OBJ_TYPE_MSG_QUEUE
, эта функция может уничтожить только управляющий блок типа очереди. тогда позвониtos_msg_queue_flush()
Функция поставит в очередь все сообщения в списке сообщений "清空
", "Пустой" означает освобождение сообщения, смонтированного в очереди, обратно в пул сообщений (если в списке сообщений очереди сообщений есть сообщения, используйтеmsgpool_free()
сообщение об отключении функции). и черезtos_list_init()
Функция инициализирует список сообщений очереди сообщений,knl_object_deinit()
Функция состоит в том, чтобы гарантировать, что очередь сообщений была уничтожена, в это время блок управления очередью сообщенийpend_obj
переменная-членtype
имущество, идентифицированное какKNL_OBJ_TYPE_NONE
.
Но есть одно замечание, потому что оперативная память блока управления очередью статически выделяется компилятором, поэтому даже если очередь уничтожена, эта память не может быть освобождена~
__API__ k_err_t tos_msg_queue_destroy(k_msg_queue_t *msg_queue)
{
TOS_PTR_SANITY_CHECK(msg_queue);
#if TOS_CFG_OBJECT_VERIFY_EN > 0u
if (!knl_object_verify(&msg_queue->knl_obj, KNL_OBJ_TYPE_MSG_QUEUE)) {
return K_ERR_OBJ_INVALID;
}
#endif
tos_msg_queue_flush(msg_queue);
tos_list_init(&msg_queue->queue_head);
#if TOS_CFG_OBJECT_VERIFY_EN > 0u
knl_object_deinit(&msg_queue->knl_obj);
#endif
return K_ERR_NONE;
}
__API__ void tos_msg_queue_flush(k_msg_queue_t *msg_queue)
{
TOS_CPU_CPSR_ALLOC();
k_list_t *curr, *next;
TOS_CPU_INT_DISABLE();
TOS_LIST_FOR_EACH_SAFE(curr, next, &msg_queue->queue_head) {
msgpool_free(TOS_LIST_ENTRY(curr, k_msg_t, list));
}
TOS_CPU_INT_ENABLE();
}
Получить сообщение из очереди сообщений
tos_msg_queue_get()
Функция используется для получения сообщений из очереди сообщений, а полученные сообщения проходят черезmsg_addr
Параметр возвращается, а размер сообщения получается черезmsg_size
Параметр возвращается пользователю и возвращается при успешном захвате.K_ERR_NONE
, в противном случае вернуть соответствующий код ошибки. Эта функция получения сообщений из очереди сообщений не будет блокироваться.Если есть сообщение, получение будет успешным, в противном случае получение будет неудачным.Ее процесс реализации выглядит следующим образом:TOS_CFG_OBJECT_VERIFY_EN
Когда определение макроса включено, вызовитеknl_object_verify()
Функция гарантирует, что сообщение получено из очереди сообщений, а затем передано черезTOS_LIST_FIRST_ENTRY_OR_NULL
Определить, есть ли сообщение в списке сообщений очереди сообщений, и вернуться, если оно не существуетK_ERR_MSG_QUEUE_EMPTY
Указывает, что очередь сообщений пуста, и оно все равно будет успешно получено, и его нужно использовать после получения успеха.msgpool_free()
Функция выпускает сообщение обратно в пул сообщений.
__API__ k_err_t tos_msg_queue_get(k_msg_queue_t *msg_queue, void **msg_addr, size_t *msg_size)
{
TOS_CPU_CPSR_ALLOC();
k_msg_t *msg;
#if TOS_CFG_OBJECT_VERIFY_EN > 0u
if (!knl_object_verify(&msg_queue->knl_obj, KNL_OBJ_TYPE_MSG_QUEUE)) {
return K_ERR_OBJ_INVALID;
}
#endif
TOS_CPU_INT_DISABLE();
msg = TOS_LIST_FIRST_ENTRY_OR_NULL(&msg_queue->queue_head, k_msg_t, list);
if (!msg) {
TOS_CPU_INT_ENABLE();
return K_ERR_MSG_QUEUE_EMPTY;
}
*msg_addr = msg->msg_addr;
*msg_size = msg->msg_size;
msgpool_free(msg);
TOS_CPU_INT_ENABLE();
return K_ERR_NONE;
}
Написать сообщение в очередь сообщений
При отправке сообщения,TencentOS tiny
Бездействующее сообщение будет взято из пула сообщений (списка бездействующих сообщений) и подключено к списку сообщений очереди сообщений.opt
Выбор параметра монтируется в конец или начало списка сообщений, поэтому поддерживается запись в очередь сообщений.FIFO
иLIFO
способ,msg_queue
блок управления очередью сообщений, в который должно быть записано сообщение,msg_addr
,msg_size
Это адрес и размер сообщения, которое будет написано.
Процесс написания сообщения очень прост, напрямую черезmsgpool_alloc()
Функция берет сообщение о простое из пула сообщений и, если в системе нет сообщения о простое, возвращает код ошибки напрямую.K_ERR_MSG_QUEUE_FULL
Указывает, что сообщения, доступные системе, исчерпаны. Если бесплатное сообщение получено успешно, адрес и размер записываемого сообщения будут записаны в пул сообщений.msg_addr
иmsg_size
переменные-члены, а затем передатьopt
Параметр выбирает положение (в начале или в конце) для монтирования сообщения в список сообщений.
__API__ k_err_t tos_msg_queue_put(k_msg_queue_t *msg_queue, void *msg_addr, size_t msg_size, k_opt_t opt)
{
TOS_CPU_CPSR_ALLOC();
k_msg_t *msg;
#if TOS_CFG_OBJECT_VERIFY_EN > 0u
if (!knl_object_verify(&msg_queue->knl_obj, KNL_OBJ_TYPE_MSG_QUEUE)) {
return K_ERR_OBJ_INVALID;
}
#endif
TOS_CPU_INT_DISABLE();
msg = msgpool_alloc();
if (!msg) {
TOS_CPU_INT_ENABLE();
return K_ERR_MSG_QUEUE_FULL;
}
msg->msg_addr = msg_addr;
msg->msg_size = msg_size;
if (opt & TOS_OPT_MSG_PUT_LIFO) {
tos_list_add(&msg->list, &msg_queue->queue_head);
} else {
tos_list_add_tail(&msg->list, &msg_queue->queue_head);
}
TOS_CPU_INT_ENABLE();
return K_ERR_NONE;
}
экспериментальный тестовый код
#include "stm32f10x.h"
#include "bsp_usart.h"
#include "tos.h"
k_msg_queue_t test_msg_queue_00;
k_task_t task1;
k_task_t task2;
k_stack_t task_stack1[1024];
k_stack_t task_stack2[1024];
void test_task1(void *Parameter)
{
k_err_t err;
int i = 0;
int msg_received;
size_t msg_size = 0;
while(1)
{
printf("queue pend\r\n");
for (i = 0; i < 3; ++i)
{
err = tos_msg_queue_get(&test_msg_queue_00, (void **)&msg_received, &msg_size);
if (err == K_ERR_NONE)
printf("msg queue get is %d \r\n",msg_received);
if (err == K_ERR_PEND_DESTROY)
{
printf("queue is destroy\r\n");
tos_task_delay(TOS_TIME_FOREVER - 1);
}
}
tos_task_delay(1000);
}
}
void test_task2(void *Parameter)
{
k_err_t err;
int i = 0;
uint32_t msgs[3] = { 1, 2, 3 };
printf("task2 running\r\n");
while(1)
{
for (i = 0; i < 3; ++i)
{
err = tos_msg_queue_put(&test_msg_queue_00, (void *)(msgs[i]), sizeof(uint32_t), TOS_OPT_MSG_PUT_FIFO);
if (err != K_ERR_NONE)
printf("msg queue put fail! code : %d \r\n",err);
}
tos_task_delay(1000);
}
}
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
k_err_t err;
/*初始化USART 配置模式为 115200 8-N-1,中断接收*/
USART_Config();
printf("Welcome to TencentOS tiny\r\n");
tos_knl_init(); // TOS Tiny kernel initialize
tos_robin_config(TOS_ROBIN_STATE_ENABLED, (k_timeslice_t)500u);
printf("create test_queue_00\r\n");
err = tos_msg_queue_create(&test_msg_queue_00);
if(err != K_ERR_NONE)
printf("TencentOS Create test_msg_queue_00 fail! code : %d \r\n",err);
printf("create task1\r\n");
err = tos_task_create(&task1,
"task1",
test_task1,
NULL,
3,
task_stack1,
1024,
20);
if(err != K_ERR_NONE)
printf("TencentOS Create task1 fail! code : %d \r\n",err);
printf("create task2\r\n");
err = tos_task_create(&task2,
"task2",
test_task2,
NULL,
4,
task_stack2,
1024,
20);
if(err != K_ERR_NONE)
printf("TencentOS Create task2 fail! code : %d \r\n",err);
tos_knl_start(); // Start TOS Tiny
}
Феномен
Следуй за мной, если хочешь!
Соответствующие коды можно получить, ответив на «19» на фоне официального аккаунта. Добро пожаловать в публичный аккаунт «Развития Интернета вещей IoT»