vesperW · 1 天前

分享一款裸机状态下实现RTOS功能的组件

想要在裸机状态下,简单实现一些类似RTOS环境下的功能,其实网上也有很多组件包,今天 就来分享一款类似的组件:ToolKit.

1、介绍

ToolKit是一套应用于嵌入式系统的通用工具包,可灵活应用到有无RTOS的程序中,采用C语言面向对象的思路实现各个功能,尽可能最大化的复用代码,目前为止工具包包含:循环队列、软件定时器、事件集

  • Queue 循环队列
    1.支持动态、静态方式进行队列的创建与删除。
    2.可独立配置缓冲区大小。
    3.支持数据最新保持功能,当配置此模式并且缓冲区已满,若有新的数据存入,将会移除最早数据,并保持缓冲区已满。
  • Timer 软件定时器
    1.支持动态、静态方式进行定时器的创建与删除。
    2.支持循环单次模式。
    3.可配置有无超时回调函数。
    4.可配置定时器工作在周期间隔模式。
    5.使用双向链表,超时统一管理,不会因为增加定时器而增加超时判断代码。
  • Event 事件集
    1.支持动态、静态方式进行事件集的创建与删除。
    2.每个事件最大支持32个标志位。
    3.事件的触发可配置为“标志与”“标志或”

2、文件目录

toolkit
├── include                         // 包含文件目录
|   ├── toolkit.h                   // toolkit头文件
|   └── toolkit_cfg.h               // toolkit配置文件
├── src                             // toolkit源码目录
|   ├── tk_queue.c                  // 循环队列源码
|   ├── tk_timer.c                  // 软件定时器源码
|   └── tk_event.c                  // 事件集源码
├── samples                         // 例子
|   ├── tk_queue_samples.c          // 循环队列使用例程源码
|   ├── tk_timer_samples.c          // 软件定时器使用例程源码
|   └── tk_event_samples.c          // 事件集使用例程源码
└── README.md                       // 说明文档3 、函数定义

3 、函数定义

3.1 配置文件

image.png

3.2 Queue 循环队列API函数

以下为详细API说明及简要示例程序,综合demo可查看tk_queue_samples.c示例。
3.2.1 动态创建队列
注意:当配置TOOLKIT_USING_QUEUE后,才能使用此函数。此函数需要用到malloc
struct tk_queue *tk_queue_create(uint16_t queue_size, uint16_t max_queues, bool keep_fresh);

image.png

队列创建示例:

int main(int argc, char *argv[])
{
    /* 动态方式创建一个循环队"queue",缓冲区大小50字节,不保持最新 */
    struct tk_queue *queue = tk_queue_create(50, 1, false);
    if( queue == NULL){
        printf("队列创建失败!\n");
    }
    /* ... */
    /* You can add your code under here. */
    return 0;
}
3.2.2 动态删除队列
注意:当配置TOOLKIT_USING_QUEUE后,才能使用此函数。此函数需要用到free。必须为动态方式创建的队列对象。
bool tk_queue_delete(struct tk_queue *queue);

image.png

3.2.3 静态初始化队列
bool tk_queue_init(struct tk_queue *queue, void *queuepool, uint16_t pool_size, uint16_t queue_size, bool keep_fresh);

image.png

队列创建示例:

int main(int argc, char *argv[])
{
    /* 定义一个循环队列 */
    structtk_queuequeue;
    /* 定义循环队列缓冲区 */
    uint8_t queue_pool[100];
    /* 静态方式创建一个循环队列"queue",缓存区为queue_pool,大小为queue_pool的大小,模式为保持最新 */
    if( tk_queue_init(&queue, queue_pool, sizeof(queue_pool), 
                      sizeof(queue_pool[0]), true) == false){
        printf("队列创建失败!\n");
    }
    /* ... */
    /* You can add your code under here. */
}
3.2.4 静态脱离队列
注意: 会使缓存区脱离与队列的关联。必须为静态方式创建的队列对象。
bool tk_queue_detach(struct tk_queue *queue);

image.png

3.2.5 清空队列
bool tk_queue_clean(struct tk_queue *queue);

image.png

3.2.6 判断队列是否为空
bool tk_queue_empty(struct tk_queue *queue);

image.png

3.2.7 判断队列是否已满
bool tk_queue_full(struct tk_queue *queue);

image.png

3.2.8 从队列中读取一个元素(不从队列中删除)
bool tk_queue_peep(struct tk_queue *queue, void *pval);

image.png

3.2.9 移除一个元素
bool tk_queue_remove(struct tk_queue *queue);

image.png

3.2.10 向队列压入(入队)1个元素数据
bool tk_queue_push(struct tk_queue *queue, void *val);

image.png

3.2.11 从队列弹出(出队)1个元素数据
bool tk_queue_pop(struct tk_queue *queue, void *pval);

image.png

3.2.12 查询队列当前数据长度
uint16_t tk_queue_curr_len(struct tk_queue *queue);

image.png

3.2.13 向队列压入(入队)多个元素数据
uint16_t tk_queue_push_multi(struct tk_queue *queue, void *pval, uint16_t len);

image.png

3.2.14 从队列弹出(出队)多个元素数据
uint16_t tk_queue_pop_multi(struct tk_queue *queue, void *pval, uint16_t len);

image.png

3.3 Timer 软件定时器API函数
以下为详细API说明及简要示例程序,综合demo可查看tk_timer_samples.c示例。
3.3.1 软件定时器功能初始化
注意:此函数在使用定时器功能最初调用,目的是创建定时器列表头结点,和配置tick获取回调函数。
bool tk_timer_func_init(uint32_t (*get_tick_func)(void));

image.png

3.3.2 动态创建定时器
注意:当配置TOOLKIT_USING_TIMER后,才能使用此函数。此函数需要用到malloc
struct tk_timer *tk_timer_create(void(*timeout_callback)(struct tk_timer *timer));

image.png

定时器创建示例:

/* 定义获取系统tick回调函数 */
uint32_tget_sys_tick(void)
{
    return tick;
}

/* 定时器超时回调函数 */
voidtimer_timeout_callback(struct tk_timer *timer)
{
    printf("timeout_callback: timer timeout:%ld\n", get_sys_tick());
}

intmain(int argc, char *argv[])
{
    /* 初始化软件定时器功能,并配置tick获取回调函数*/
    tk_timer_func_init(get_sys_tick);
    
    /* 定义定时器指针 */
    tk_timer_t timer = NULL;
    /* 动态方式创建timer,并配置定时器超时回调函数 */
    timer = tk_timer_create((tk_timer_timeout_callback *)timer_timeout_callback);
    if (timer == NULL)
    {
        printf("定时器创建失败!\n");
        return0;
    }
    /* ... */
    /* You can add your code under here. */
    return0;
}
3.3.3 动态删除定时器
当配置TOOLKIT_USING_TIMER后,才能使用此函数。此函数需要用到free。必须为动态方式创建的定时器对象。
bool tk_timer_delete(struct tk_timer *timer);

image.png

3.3.4 静态初始化定时器
bool tk_timer_init(struct tk_timer *timer, void (*timeout_callback)(struct tk_timer *timer));

image.png

队列创建示例:

/* 定义获取系统tick回调函数 */
uint32_tget_sys_tick(void)
{
    return tick;
}

/* 定时器超时回调函数 */
voidtimer_timeout_callback(struct tk_timer *timer)
{
    printf("timeout_callback: timer timeout:%ld\n", get_sys_tick());
}

intmain(int argc, char *argv[])
{
    /* 定义定时器timer */
    structtk_timertimer;
    bool result = tk_timer_init( &timer,(tk_timer_timeout_callback *)timer_timeout_callback);
    if (result == NULL)
    {
        printf("定时器创建失败!\n");
        return0;
    }
    /* ... */
    /* You can add your code under here. */
    return0;
}
3.3.5 静态脱离定时器
注意: 会将timer从定时器链表中移除。必须为静态方式创建的定时器对象。
bool tk_timer_detach(struct tk_timer *timer);

image.png

3.3.6 定时器启动
bool tk_timer_start(struct tk_timer *timer, tk_timer_mode mode, uint32_t delay_tick);

image.png

3.3.7 定时器停止
bool tk_timer_stop(struct tk_timer *timer);

image.png

3.3.8 定时器继续
bool tk_timer_continue(struct tk_timer *timer);

image.png

3.3.9 定时器重启
注意:重启时长为最后一次启动定时器时配置的时长。
bool tk_timer_restart(struct tk_timer *timer);

image.png

3.3.10 获取定时器模式
tk_timer_mode tk_timer_get_mode(struct tk_timer *timer);

image.png

3.3.11 获取定时器状态
tk_timer_state tk_timer_get_state(struct tk_timer *timer);

image.png

3.3.12 定时器处理
bool tk_timer_loop_handler(void);

image.png

注意:tk_timer_loop_handler函数要不断的循环调用。
3.3.13 超时回调函数

函数原型

typedef void (*timeout_callback)(struct tk_timer *timer);
说明:超时回调函数可定义多个,即一个定时器对应一个回调函数,也可多个定时器对应一个回调函数。

一对一

/* 定义两个回调函数,对应定时器timer1和timer2 */
void timer1_timeout_callback(struct tk_timer *timer){
    printf("定时器1超时!\n");
}
void timer2_timeout_callback(struct tk_timer *timer){
    printf("定时器2超时!\n");
}
/* 创建两个定时器,配置单独超时回调函数 */
timer1 = tk_timer_create((timeout_callback *)timer1_timeout_callback);
timer2 = tk_timer_create((timeout_callback *)timer2_timeout_callback);

多对一

/* 定时器timer1和timer2共用一个回调函数,在回调函数做区分 */
void timer_timeout_callback(struct tk_timer *timer){
    if (timer == timer1)
        printf("定时器1超时!\n");
    else if (timer == timer2)
        printf("定时器2超时!\n");
}
/* 创建两个定时器,使用相同的超时回调函数 */
timer1 = tk_timer_create((timeout_callback *)timer_timeout_callback);
timer2 = tk_timer_create((timeout_callback *)timer_timeout_callback);
3.4 Event 事件集API函数
以下为详细API说明及简要示例程序,综合demo可查看tk_event_samples.c示例。
3.4.1 动态创建一个事件
注意:当配置TOOLKIT_USING_EVENT后,才能使用此函数。此函数需要用到malloc
struct tk_event *tk_event_create(void);

image.png

3.4.2 动态删除一个事件
当配置TOOLKIT_USING_TIMER后,才能使用此函数。此函数需要用到free。必须为动态方式创建的事件对象。
bool tk_event_delete(struct tk_event *event);

image.png

3.4.3 静态初始化一个事件
bool tk_event_init(struct tk_event *event);

image.png

3.4.4 发送事件标志
bool tk_event_send(struct tk_event *event, uint32_t event_set);

image.png

3.4.5 接收事件
bool tk_event_recv(struct tk_event *event, uint32_t event_set, uint8_t option, uint32_t *recved);

image.png

END

作者:Cproape
来源:strongerHuang

推荐阅读

欢迎大家点赞留言,更多Arm技术文章动态请关注极术社区嵌入式客栈专栏欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。

推荐阅读
关注数
2928
内容数
373
分享一些在嵌入式应用开发方面的浅见,广交朋友
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息