网站设计套用模板,如何选取网站关键词,一般给公司做网站怎么收费,如何查看网站做没做百度推广zephyr内核对象学习
定时器
类似linux的定时器#xff0c; 可以分别设置第一次到期时间和后续的周期触发时间#xff0c; 可以注册到期回调和停止回调 还有一个计数状态#xff0c;用于标记timer到期了多少次 duration#xff1a;设定timer第一次到期的时间。
period: …zephyr内核对象学习
定时器
类似linux的定时器 可以分别设置第一次到期时间和后续的周期触发时间 可以注册到期回调和停止回调 还有一个计数状态用于标记timer到期了多少次 duration设定timer第一次到期的时间。
period: timer第一次到期后的触发时间间隔。
expiry触发回调。
定时器的使用
初始化定时器
void k_timer_init(struct k_timer *timer, k_timer_expiry_t expiry_fn, k_timer_stop_t stop_fn);启动定时器
void k_timer_start(struct k_timer *timer, k_timeout_t duration, k_timeout_t period);停止定时器
void k_timer_stop(struct k_timer *timer);读取定时器状态
uint32_t k_timer_status_get(struct k_timer *timer);读取定时器的状态该状态表示自上次读取其状态以来定时器已到期的次数每次读取后会重置状态为0。
等待定时器到期
uint32_t k_timer_status_sync(struct k_timer *timer);调用这个函数会阻塞线程直到定时器到期或者停止调用这个函数会将定时器状态清零另外不允许在中断处理函数中调用该函数函数返回定时器的状态值。
获取定时器超时到期时的系统时间
k_ticks_t k_timer_expires_ticks(const struct k_timer *timer);该函数返回定时器下一次到期时候的系统时间以系统ticks为单位。如果定时器未运行则返回当前系统时间。
获取定时器超时到期的剩余时间
k_ticks_t k_timer_remaining_ticks(const struct k_timer *timer)计算运行的定时器下次过期前剩余的时间如果定时器未运行则返回0。
获取定时器超时到期前的剩余时间
uint32_t k_timer_remaining_get(struct k_timer *timer);计算运行定时器下次到期前剩余的近似时间以毫秒(ms)为单位。如果定时器未运行则返回0。
另外还有一种定义和初始化定时器的方式 静态定义并初始化定时器
#define K_TIMER_DEFINE(name, expiry_fn, stop_fn)注意
因为timer的回调是在中断中执行所以在回调函数中不能做耗时操作。 timer不能保证精确的定时但其精度比k_sleep/k_usleep高测量执行时间时不建议使用k_timer建议读系统硬件时钟。
当timer触发回调后需要处理耗时操作时可配合k_work使用将耗时操作放在workqueue中执行
/* k_work回调函数用于处理耗时操作 */
void work_handler(struct k_work *work)
{while(int i0, i100, i){printk(do something \n);}
}/* 定义初始化一个k_work */
K_WORK_DEFINE(a_work, work_handler);/* timer到期回调函数 */
static void timer_handler_expiry(struct k_timer *dummy)
{counter;printk(counter %d \n, counter);/*发送k_work信号量*/k_work_submit(a_work);
}信号量
信号量是用于控制多个线程对一组资源的访问使用信号量在生产者和消费者之间同步
Zephyr的信号量在初始化时可以指定初始化计数值和最大计数值生产者释放(give)信号量时计数值1但不会超过最大值消费者获取(take)时计数值-1直到为0。每次信号量释放时都会引发调度。如果多个线程都在等待信号量新产生的信号量会被等待时间最长的最高优先级线程接收。
信号量的使用
初始化信号量
int k_sem_init(struct k_sem *sem, unsigned int initial_count, unsigned int limit);获取信号量
int k_sem_take(struct k_sem *sem, k_timeout_t timeout);释放信号量
void k_sem_give(struct k_sem *sem);互斥量
互斥量本质应该和初始值和最大值为1的信号量相同目的主要是为了提供对资源的独占访问因为只有0和1只有一个线程能拿到资源所以就实现了独占访问
互斥量只能用于线程中不能用于中断会引起阻塞所以不能用于中断互斥量释放会引起调度释放信号量也会引起调度引起阻塞之后可能会导致优先级翻转那理论上信号量也会引起优先级翻转
互斥量的使用
初始化互斥量
int k_mutex_init(struct k_mutex *mutex);互斥量上锁相当于获取信号量
int k_mutex_lock(struct k_mutex *mutex, k_timeout_t timeout);互斥锁解锁相当于释放信号量
void k_mutex_unlock(struct k_mutex *mutex);轮询未详细研究
轮询(poll)是一个比较特殊的内核对象polling API 允许一个线程等待一个或者多个条件满足。支持的条件类型只能是内核对象可以是Semaphore(信号量), FIFO(管道), poll signal(轮询)三种。 例如一个线程使用polling API同时等待多个semaphore只要其中一个 semaphore 触发时 polling API 就会得到通知。 poll 具有以下特性
当一个线程等待多个触发条件时只要有一个条件满足 k_poll 就会返回。当 Semaphore 或 FIFO 满足条件后, k_poll 只是接到通知返回线程并未获取到 semaphore 或FIFO, 还需要使用代码主动获取。
轮询的使用
初始化轮询实例
void k_poll_event_init(struct k_poll_event *event, uint32_t type, int mode, void *obj);初始化的时候一次只能添加一个内存对象event是数组指针type是指后面obj的类型信号量或者FIFO或者轮询信号不论是这三个的哪一种在这之前都要调用对应的初始化接口进行初始化mode一般是notify_only
轮询接口
int k_poll (struct k_poll_event *events, int num_events, k_timeout_t timeout)在一次释放之后如果k_poll需要再次捕获该信号需要先调用复位信号的接口进行复位否则将无法再次释放
如果用的是poll_signal可以用下面的接口进行操作
轮询信号初始化
void k_poll_signal_init(struct k_poll_signal *sig);轮询信号释放
int k_poll_signal_raise(struct k_poll_signal *sig, int result);复位轮询信号
void k_poll_signal_reset(struct k_poll_signal *sig);检查轮询信号
void k_poll_signal_check(struct k_poll_signal *sig, unsigned int *signaled, int *result);个人理解应该是在k_poll轮询多个对象其中包含poll_signal时用来确定是不是signal被捕获到了如果需要判断其他内核对象信号量或者FIFO则需要主动判断k_poll接口中的struct k_poll_event *events参数的state是sem有效还是fifo_data有效
zephyr蓝牙协议栈学习
简介
zephyr主要支持BLE对BR/EDR仅提供有限的支持 core5.3中BLE功能几乎全部支持包括LE audio和mesh BR/EDR仅支持部分GPA,L2CAP,RFCOMM,SDP,(不过看到zephyr代码里也有HF,A2DP,AVDTP等
zephyr可以仅被配置为controller或者host也可以配置为既有controller也有host zephyr仅做host时支持跟多个controller同时通信
源码树层次
subsys/bluetooth/host这里是host stack。处理HCI命令和事件地方L2CAPATTSMP等核心协议也在这里
subsys/bluetooth/controller蓝牙控制器实现。实现HCI的控制器端链路层以及对无线电收发器的访问
include/bluetooth/公共API头文件。这些是应用程序需要包含的头文件以便使用蓝牙功能
drivers/bluetoothHCI传输层驱动。每个HCI传输层都需要自己的驱动程序。(三线uart或者5线uartusbspi等
samples/bluetooth蓝牙实例代码。
test/bluetooth测试应用程序。这些应用程序用于验证蓝牙堆栈的功能。
doc/guides/bluetooth额外的文档比如PICS文档
HOST GAP通过定义BLE使用的四个不同角色来简化蓝牙LE访问 面向连接的角色
外围设备(例如智能传感器通常具有有限的用户界面)中央设备(通常是移动电话或PC)
无连接的角色
广播者(发送BLE广告例如智能信标)观察者(扫描BLE广告)
在面向连接的角色中中央设备隐式的启用观察者角色外围设备隐式的启用广播者角色
注册gatt service的方法
使用BT_GATT_SERVICE_DEFINE宏 实际管理单位应该是attr
/*** brief Statically define and register a service.** Helper macro to statically define and register a service.** param _name Service name.*/
#define BT_GATT_SERVICE_DEFINE(_name, ...) \const struct bt_gatt_attr attr_##_name[] { __VA_ARGS__ }; \const STRUCT_SECTION_ITERABLE(bt_gatt_service_static, _name) \BT_GATT_SERVICE(attr_##_name)/** brief GATT Attribute structure. */
struct bt_gatt_attr {/** Attribute UUID */const struct bt_uuid *uuid;bt_gatt_attr_read_func_t read;/** Attribute write callback */bt_gatt_attr_write_func_t write;/** Attribute user data */void *user_data;/** Attribute handle */uint16_t handle;/** brief Attribute permissions.** Will be 0 if returned from bt_gatt_discover().*/uint16_t perm;
};