第12篇 zephyr 数据传递之STACK

目录

摘要

1 概念

2 实现

2.1 定义一个stack

2.2 入栈

2.3 出栈

3 参考链接


本学笔记基于zephyr 工程版本 2.2.99,主机环境为ubuntu18.04,开发平台 nrf52840dk_nrf52840

摘要

stack是一个内核对象,它实现了后进先出队列( last in, first out),允许线程和ISR添加或移除有限个整数值。

1 概念

任意个数的stack可以被定义,引用Stack时,使用的是Stack定义的内存地址,同样只要你的内存允许,就可以随便定义。

Stack有下面关键属性:

一个整数值的queue,用于存储加入Stack并且还没有被移除的数据项。queue是通过stack_data_t类型值得一个数组来实现的,并且必须是字对齐。stack_data_t类型和cpu的word大小是一致的,一般是4个字节或者8个字节。

maximum quantity 加入队列数组的数值的最大个数。

stack使用之前必须被初始化,初始化会将queue设置为空。

一个数据值可以被ISR或者线程添加到stack,如果有等待线程存在,这个值会直接的传给线程,而不是先加入queue再取出然后再给等待的线程。其他情况这个值会被添加到LIFO类型的queue。当stack中的队列达到最大值,如果再继续向stack中添加数据项,内核是不去检测的。将导致一个未定义的行为。类似于栈溢出了。

一个数据向可以被线程移除(取出),如果线程从一个没有数据项的stack中取数据,那么线程会进入等待,直到有数据项可以从stack中读出。多个线程可以同时的访问一个空的stack,当有数据项添加到stack中,优先级最高,等待时间最长的线程将先获得数据项。

内核也允许在isr中去取出stack中的数据项,但是stack为控制,isr不要尝试去等待。

2 实现

2.1 定义一个stack

使用struct k_stack类型去定义stack变量,k_stack_init()或者k_stack_alloc_init()去初始化这个stack。使用这个k_stack_alloc_init()函数初始化的时候,一个缓冲区不用被提供,缓冲区可以的从线程内存池中分配。

下面代码,定义并初始化一个可以保存10个数据的空stack:

#define MAX_ITEMS 10

stack_data_t my_stack_array[MAX_ITEMS];
struct k_stack my_stack;

k_stack_init(&my_stack, my_stack_array, MAX_ITEMS);

或者可以在编译时调用K_STACK_DEFINE实现上面同样的功能:

K_STACK_DEFINE(my_stack, MAX_ITEMS);

2.2 入栈

可以调用k_stack_push()函数,添加一个数据项到stack。

下面的示例展示,定义一个数据结构内存池,并且将他们的地址加入到stack中:

/* define array of data structures */
struct my_buffer_type {
    int field1;
    ...
    };
struct my_buffer_type my_buffers[MAX_ITEMS];

/* save address of each data structure in a stack */
for (int i = 0; i < MAX_ITEMS; i++) {
    k_stack_push(&my_stack, (stack_data_t)&my_buffers[i]);
}

2.3 出栈

可以调用k_stack_pop()函数,将数据项从stack中取出:

下面的示例展示了,一个线程动态的分配一个没有使用的数据结构,当这个数据结构不在被需要,这个线程应该将这个数据结构的地址重新入栈:

struct my_buffer_type *new_buffer;

k_stack_pop(&buffer_stack, (stack_data_t *)&new_buffer, K_FOREVER);
new_buffer->field1 = ...

3 参考链接

https://docs.zephyrproject.org/latest/reference/kernel/data_passing/stacks.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章