[TencentOS tiny source depth analysis] (4) - Message Queue

message queue

In a previous article [learning] TencentOS tiny source code analysis (3) - queue
we describe TencentOS tiny cohort achieved, but also points out TencentOS tiny queue is dependent on the message queue, then we take a look today the message queue.

In fact, a message queue is TencentOS tiny the base component , as the underlying queue.
So tos_config.hwill the following macro definitions:

#if (TOS_CFG_QUEUE_EN > 0u)
#define TOS_CFG_MSG_EN     1u
#else
#define TOS_CFG_MSG_EN     0u
#endif

System initialization messages pool

In system initialization ( tos_knl_init()time), the system will initialize the message pool, wherein the msgpool_init()function is used to initialize the message pool, the definition of the function is the tos_msg.c file, the function realized mainly through a forloop, the message pool k_msg_pool[TOS_CFG_MSG_POOL_SIZE]member variable is initialized, initializing the corresponding node list, and to mount it on the idle message list k_msg_freelist
initialization completion schematic :( assumed that only three message)

__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
    ···
}

Create a message queue

This function will be called in the queue creation, of course, he can own as a user API interface available to users, not just the kernel API interface.
The nature of this function is to initialize the list of messages in the message queue queue_head.
Initialization is complete schematic:

__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;
}

The destruction of a message queue

tos_msg_queue_destroy()Function for the destruction of a message queue when the message queue is not in use it can be destroyed, the destruction of nature is actually the content message queue control block is cleared, first determine what type of message queue control block is KNL_OBJ_TYPE_MSG_QUEUE, this function can only be destroyed type of queue control block. Then call the tos_msg_queue_flush()function to the list of messages in the message queue of All " 清空," "Empty" means that mounts to the message on the message queue released back into the pool (if the message queue of the message list there is a message, use the msgpool_free()function release message). And by tos_list_init()the message queue message list initialization function, knl_object_deinit()the function is to ensure that the message queue has been destroyed, then the message queue control block pend_objmember variable typeattribute is identified KNL_OBJ_TYPE_NONE.

But one thing to note, because RAM queue control block is allocated statically by the compiler, so even if the queue is destroyed, this memory is no way the release of ~

__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();
}

Getting a message from the message queue

tos_msg_queue_get()Function to get a message from the message queue, the message is acquired by the msg_addrparameter returned by the acquired message size msg_sizereturn parameters to the user, when the acquisition success is returned K_ERR_NONE, otherwise an error code corresponding.
This gets the message from the message queue function is no blocking, if the message is to succeed, or to fail to obtain, its implementation process as follows:
TOS_CFG_OBJECT_VERIFY_ENmacros enabled, you call the knl_object_verify()function to ensure that is to get from the message queue message, then TOS_LIST_FIRST_ENTRY_OR_NULLthere is no news to determine what is the message queue list of messages, if there is no return K_ERR_MSG_QUEUE_EMPTYmessage indicating that the queue is empty, anyway, will succeed, after a successful acquisition requires the use of msgpool_free()a function to release the message back to the message pool.

__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;
}

Writes a message to a message queue

When sending a message, TencentOS tinywill be removed from the message pool (idle message list) an idle message, the message list to mount message queue, by optselecting a message to mount the head or end of the list parameter, so the message queue writing support FIFOand LIFOthe way, msg_queueis to write a message to the message queue control block msg_addr, msg_sizeis written to the address and size of the message.

Very simple process of writing the message, directly msgpool_alloc()out a message from the message pool idle function, idle message if the system does not exist, the process directly returns an error code K_ERR_MSG_QUEUE_FULLmessage indicating the available system has been used up. If the message was successfully removed will be free to write messages to the message size of the recording address pool msg_addrand msg_sizemember variable, and by optselecting the position to mount the message list message (head or tail) parameter.

__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;
}

Experimental test code

#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

}

phenomenon

phenomenon

I like to focus on it!

I welcome public attention No.

Related code can reply "19" Get back in the public number.
For more information please concern "Things IoT development," the public number!

Guess you like

Origin www.cnblogs.com/iot-dev/p/11688931.html