nordic mesh 任务调度实现
nordic mesh 任务调度实现
nordic mesh的任务调度室基于定时器实现的,有两个链表结构维护任务。
需要注意的是,任务调度的部分接口只能在“bearer event”的中段级别被调用,因此调用的形式是通过设置"bearer event"事件来实现的。
结构及接口 @timer_scheduler.h
任务调度的结构定义如下:
typedef enum
{
TIMER_EVENT_STATE_UNUSED, /**< Not present in the scheduler */
TIMER_EVENT_STATE_ADDED, /**< Added for processing */
TIMER_EVENT_STATE_QUEUED, /**< Queued for firing */
TIMER_EVENT_STATE_RESCHEDULED, /**< Rescheduled, but not resorted */
TIMER_EVENT_STATE_ABORTED, /**< Aborted, but still in the list */
TIMER_EVENT_STATE_IGNORED, /**< Aborted, but added for processing */
TIMER_EVENT_STATE_IN_CALLBACK /**< Currently being called */
} timer_event_state_t;
/**
* Timer event structure for schedulable timers.
*/
typedef struct timer_event
{
volatile timer_event_state_t state; /**< Timer event state. */
timestamp_t timestamp; /**< 定时器激发时间 */
timer_sch_callback_t cb; /**< 定时器激发时的回调函数 */
uint32_t interval; /**< 周期事件的时间间隔,0时表示单次事件 */
void * p_context; /**< 调用回调函数cb时传入的参数 */
struct timer_event* p_next; /**< 指向下一个事件结构的指针,构成链表 */
} timer_event_t;
相关的几个接口如下:
/**
* Initializes the scheduler module.
* 在nrf_mesh_init()中被调用
*/
void timer_sch_init(void);
/**
* Schedules a timer event.
*
* @warning This function must be called from @ref BEARER_EVENT "bearer event" IRQ level or lower.
* 该函数必须在BEARER_EVENT的中断优先级上被调用
* @warning The structure parameters must not be changed after the structure has been added to the
* scheduler, as this may cause race conditions. If a change in timing is needed, please use the
* @ref timer_sch_reschedule() function. If any other changes are needed, abort the event, change the
* parameter, and schedule it again.
*
* @param[in] p_timer_evt A pointer to a statically allocated timer event, which will be used as
* context for the schedulable event.
*/
void timer_sch_schedule(timer_event_t* p_timer_evt);
/**
* Aborts a previously scheduled event.
*
* @warning This function must be called from @ref BEARER_EVENT "bearer event" IRQ level or lower.
* 该函数必须在BEARER_EVENT的中断优先级上被调用
* @param[in] p_timer_evt A pointer to a previously scheduled event.
*/
void timer_sch_abort(timer_event_t* p_timer_evt);
/**
* Reschedules a previously scheduled event.
*
* @warning This function must be called from @ref BEARER_EVENT "bearer event" IRQ level or lower.
* 该函数必须在BEARER_EVENT的中断优先级上被调用
* @param[in] p_timer_evt A pointer to a previously scheduled event.
* @param[in] new_timestamp When the event should time out, instead of the old time.
*/
void timer_sch_reschedule(timer_event_t* p_timer_evt, timestamp_t new_timestamp);
任务调度实现 @timer_scheduler.c
调度器中维护两个任务链表p_head
、p_add_head
,当有新的任务加入调度时,首先会加到p_add_head
链表中,此时新任务的状态会设置为"TIMER_EVENT_STATE_ADDED";之后在process_add_list()
函数遍历p_add_head
链表,将其中状态为"TIMER_EVENT_STATE_ADDED"的任务加入到第一个链表p_head
中。定时器激发时会遍历第一个链表,将其中满足运行时间的事件运行。
调度器结构的定义如下:
typedef struct
{
timer_event_t* p_head;
timer_event_t* p_add_head;
uint32_t dirty_events; /**< Events in the fire list that needs processing */
uint32_t event_count;
} scheduler_t;
/**
* Static globals
*/
static volatile scheduler_t m_scheduler; /**<调度器实体 */
static bearer_event_flag_t m_event_flag; /**<bearer event 事件 */
需要注意的是,部分定时器接口是在”bearer event“的中断优先级的被调用的。因此,定义了m_event_flag的全局变量,以产生bearer-event事件调用。
timer_sch_init()
调度器初始化函数的实现代码如下,在其中首先将调度器实体全部归零,然后注册了一个bearer-event事件。
void timer_sch_init(void)
{
// 调度器结构置零
memset((scheduler_t*) &m_scheduler, 0, sizeof(m_scheduler));
// 注册一个bearer-event事件
// 当调用函数 bearer_event_flag_set(m_event_flag) 时
// 会产生bearer-event中断,来调用flag_event_cb()回调函数
m_event_flag = bearer_event_flag_add(flag_event_cb);
}
bearer-event事件回调函数
static bool flag_event_cb(void)
{
/* 处理被污染的任务
* 被污染的任务要么直接移除
* 需要再次调度的,则加入到p_add_head链表中
*/
process_dirty_events();
/* add all the popped events back in, at their right places.
* 该函数遍历第二个链表,将其中的新加的任务添加到第一个链表中
* 第一个链表的任务是根据运行时间排序的,从头到尾运行时间越来越晚
* 即第一个链表的链表头是最先运行的节点
*/
process_add_list();
/* 激发定时器
* 遍历第一个链表,一次运行到达运行时间的任务
* p_head依次后移
*/
fire_timers(timer_now());
/*
* 设置定时器函数下次激发时间
*/
setup_timeout(timer_now());
return true;
}
timer_sch_schedule()函数实现如下:
// 任务加入调度时,首先是加入第二个任务链表中
void timer_sch_schedule(timer_event_t* p_timer_evt)
{
NRF_MESH_ASSERT(p_timer_evt != NULL);
NRF_MESH_ASSERT(p_timer_evt->cb != NULL);
uint32_t was_masked;
_DISABLE_IRQS(was_masked);
p_timer_evt->p_next = NULL;
add_to_add_list(p_timer_evt);
_ENABLE_IRQS(was_masked);
bearer_event_flag_set(m_event_flag);
}
timer_sch_abort()
终止某个任务
void timer_sch_abort(timer_event_t* p_timer_evt)
{
NRF_MESH_ASSERT(p_timer_evt != NULL);
uint32_t was_masked;
_DISABLE_IRQS(was_masked);
if (p_timer_evt->state == TIMER_EVENT_STATE_IN_CALLBACK)
{
p_timer_evt->state = TIMER_EVENT_STATE_UNUSED;
}
else if (p_timer_evt->state == TIMER_EVENT_STATE_ADDED)
{
p_timer_evt->state = TIMER_EVENT_STATE_IGNORED;
}
else if (p_timer_evt->state != TIMER_EVENT_STATE_UNUSED)
{
if (!is_dirty_state(p_timer_evt->state))
{
m_scheduler.dirty_events++;
}
p_timer_evt->state = TIMER_EVENT_STATE_ABORTED;
bearer_event_flag_set(m_event_flag);
}
_ENABLE_IRQS(was_masked);
}
timer_sch_reschedule()
再次调度
void timer_sch_reschedule(timer_event_t* p_timer_evt, timestamp_t new_timeout)
{
NRF_MESH_ASSERT(p_timer_evt != NULL);
uint32_t was_masked;
_DISABLE_IRQS(was_masked);
/* The events in the added queue will reinsert themselves in the processing. */
if (p_timer_evt->state == TIMER_EVENT_STATE_UNUSED ||
p_timer_evt->state == TIMER_EVENT_STATE_IN_CALLBACK)
{
add_to_add_list(p_timer_evt);
}
else if (p_timer_evt->state == TIMER_EVENT_STATE_ADDED ||
p_timer_evt->state == TIMER_EVENT_STATE_IGNORED)
{
p_timer_evt->state = TIMER_EVENT_STATE_ADDED;
}
else
{
/* Mark the rescheduled event as dirty, will be processed at the next opportunity. */
if (!is_dirty_state(p_timer_evt->state))
{
m_scheduler.dirty_events++;
}
p_timer_evt->state = TIMER_EVENT_STATE_RESCHEDULED;
}
p_timer_evt->timestamp = new_timeout;
bearer_event_flag_set(m_event_flag);
_ENABLE_IRQS(was_masked);
}
nordic mesh 任务调度实现的更多相关文章
- nordic mesh中的消息缓存实现
nordic mesh中的消息缓存实现 代码文件msg_cache.h.msg_cache.c. 接口定义 头文件中定义了四个接口,供mesh协议栈调用,四个接口如下所示,接口的实现代码在msg_ca ...
- NRF52833蓝牙5.1可用于105℃环境温度的Nordic蓝牙5.1 SoC能实现更广泛的并发多协议低功耗蓝牙、mesh和Thread应用
Nordic Semiconductor宣布推出nRF52833先进多协议系统级芯片(SoC),这是其广受欢迎且验证通过的nRF52系列的第五个新成员.nRF52833是一款功耗超低的低功耗蓝牙 (B ...
- nRF5 SDK for Mesh(六) BLE MESH 的 基础概念
Basic Bluetooth Mesh concepts The Bluetooth Mesh is a profile specification developed and published ...
- nRF5 SDK for Mesh(四) 源码编译
官方文档教程编译源码: http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk%2Fdita%2Fs ...
- nRF5 SDK for Mesh(一) 介绍和下载源码
一: 官网介绍地址:http://www.nordicsemi.com/Products/Bluetooth-low-energy/nRF5-SDK-for-Mesh Nordic offers a ...
- Nordic nRF5 SDK和softdevice介绍
SDK和Softdevice的区别是什么?怎么选择SDK和softdevice版本?芯片,SDK和softdevice有没有版本兼容问题?怎么理解SDK目录结构?SDK帮助文档在哪里?Softdevi ...
- 在mesh client示例中加入spi_slave接口(without IDE)
在mesh client示例中加入spi_slave接口(without IDE) 主要是理解cmake构建的过程,然后修改工程中的inlcude路径及c源文件. 1. 解压mesh_sdk unzi ...
- Nordic nRF52820超低功耗蓝牙5.2 SoC芯片-低端无线连接方案首选
nRF52820是功耗超低的低功耗蓝牙 (Bluetooth Low Energy /Bluetooth LE).蓝牙mesh.Thread.Zigbee和2.4 GHz专有低端无线连接解决方案.nR ...
- nordic 51822 sdk. timer 的使用
它的源代码和头文件分别为app_timer.c/app_timer.h.这是Nordic为我们提供的虚拟定时器,这个定时器不同于硬件上的TIMER,而是基于RTC1实现的一种虚拟定时器,其将定时功能作 ...
随机推荐
- Linux系统中的vi/vim指令【详解】
vi是Unix世界里极为普遍的全屏幕文本编辑器,vim是它的改进版本Vi IMproved的简称.几乎可以说任何一台Unix机器都会提供这套软件. 只要简单的在Shell下执行vi就可以进入 vi 的 ...
- 10.31课程.this指向
作用域: 浏览器给js的生存环境(栈). 作用域链: js中的关键字例如var.function...都可以提前声明,然后js由上到下逐级执行,有就使用,没有就在它的父级元素中查找.这就叫做作用域链. ...
- layer父界面调用子弹窗的方法和获取子弹窗的元素值总结
layer.open({ type: 2 ,title: false //不显示标题栏 ,closeBtn: false ,area: ['460px', '45%'] ,shade: 0.5 ,id ...
- 「PHP」工厂方法模式
引言 所属:创建型模式,常用设计模式之一 工厂模式分为:简单工厂模式.工厂方法模式.静态工厂模式.抽象工厂模式. 下面为工厂方法模式. 参考资料: <大话设计模式>程杰 模式概述 ...
- SHOPEX快递物流单号查询插件
本SHOPEX快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅急送快递.德邦物流.百世快递.汇通快递.中通快递.天天快递等知 ...
- Python安装及简介
Python简介 Python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言 ...
- 『Python题库 - 简答题』 Python中的基本概念 (121道)
## 『Python题库 - 简答题』 Python中的基本概念 1. Python和Java.PHP.C.C#.C++等其他语言的对比? 2. 简述解释型和编译型编程语言? 3. 代码中要修改不可变 ...
- python教程(二)·循环语句
计算机程序中常常需要重复执行某些语句,我们总不能将同一语句写上百遍吧?所以在python中,当然其它计算机语言也是,有一种语句可以重复执行相同的操作,这种语句就是 "循环语句",而 ...
- Tensorflow取消占用全部GPU
参考:https://www.cnblogs.com/jiu0821/p/9501665.html Tensorflow默认是会占用全部的GPU,而有时候你根本不需要那么占用那么多GPU资源,这时候就 ...
- 如何在同一个Excel里,对两个很相似的工作簿比对出不同之处
如何在同一个Excel里,对两个很相似的工作簿比对出不同之处