zephyr学习

zephyr内核对象学习

定时器

类似linux的定时器,
可以分别设置第一次到期时间和后续的周期触发时间,
可以注册到期回调和停止回调
还有一个计数状态,用于标记timer到期了多少次
在这里插入图片描述
duration:设定timer第一次到期的时间。

period: timer第一次到期后的触发时间间隔。

expiry:触发回调。

定时器的使用:

  1. 初始化定时器
void k_timer_init(struct k_timer *timer, k_timer_expiry_t expiry_fn, k_timer_stop_t stop_fn);
  1. 启动定时器
void k_timer_start(struct k_timer *timer, k_timeout_t duration, k_timeout_t period);
  1. 停止定时器
void k_timer_stop(struct k_timer *timer);
  1. 读取定时器状态
uint32_t k_timer_status_get(struct k_timer *timer);

读取定时器的状态,该状态表示自上次读取其状态以来定时器已到期的次数,每次读取后会重置状态为0。

  1. 等待定时器到期
uint32_t k_timer_status_sync(struct k_timer *timer);

调用这个函数会阻塞线程,直到定时器到期或者停止,调用这个函数会将定时器状态清零,另外不允许在中断处理函数中调用该函数,函数返回定时器的状态值。

  1. 获取定时器超时到期时的系统时间
k_ticks_t k_timer_expires_ticks(const struct k_timer *timer);

该函数返回定时器下一次到期时候的系统时间,以系统ticks为单位。如果定时器未运行,则返回当前系统时间。

  1. 获取定时器超时到期的剩余时间
k_ticks_t k_timer_remaining_ticks(const struct k_timer *timer)

计算运行的定时器下次过期前剩余的时间,如果定时器未运行,则返回0。

  1. 获取定时器超时到期前的剩余时间
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 i=0, i<100, 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。
  • 每次信号量释放时都会引发调度。
  • 如果多个线程都在等待信号量,新产生的信号量会被等待时间最长的最高优先级线程接收。

信号量的使用

  1. 初始化信号量
int k_sem_init(struct k_sem *sem, unsigned int initial_count, unsigned int limit);
  1. 获取信号量
int k_sem_take(struct k_sem *sem, k_timeout_t timeout);
  1. 释放信号量
void k_sem_give(struct k_sem *sem);

互斥量

互斥量本质应该和初始值和最大值为1的信号量相同;目的主要是为了提供对资源的独占访问(因为只有0和1,只有一个线程能拿到资源,所以就实现了独占访问)

  • 互斥量只能用于线程中,不能用于中断(会引起阻塞,所以不能用于中断)
  • 互斥量释放会引起调度(释放信号量也会引起调度)
  • 引起阻塞之后可能会导致优先级翻转(那理论上信号量也会引起优先级翻转)

互斥量的使用

  1. 初始化互斥量
int k_mutex_init(struct k_mutex *mutex);
  1. 互斥量上锁(相当于获取信号量)
int k_mutex_lock(struct k_mutex *mutex, k_timeout_t timeout);
  1. 互斥锁解锁(相当于释放信号量)
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, 还需要使用代码主动获取。

轮询的使用

  1. 初始化轮询实例
void k_poll_event_init(struct k_poll_event *event, uint32_t type, int mode, void *obj);

初始化的时候,一次只能添加一个内存对象,event是数组指针,type是指后面obj的类型(信号量或者FIFO或者轮询信号,不论是这三个的哪一种,在这之前都要调用对应的初始化接口进行初始化),mode一般是notify_only

  1. 轮询接口
int k_poll (struct k_poll_event *events, int num_events, k_timeout_t timeout)

在一次释放之后,如果k_poll需要再次捕获该信号,需要先调用复位信号的接口进行复位,否则将无法再次释放;

如果用的是poll_signal,可以用下面的接口进行操作:

  1. 轮询信号初始化
void k_poll_signal_init(struct k_poll_signal *sig);
  1. 轮询信号释放
int k_poll_signal_raise(struct k_poll_signal *sig, int result);
  1. 复位轮询信号
void k_poll_signal_reset(struct k_poll_signal *sig);
  1. 检查轮询信号
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命令和事件地方,L2CAP,ATT,SMP等核心协议也在这里

subsys/bluetooth/controller

蓝牙控制器实现。实现HCI的控制器端,链路层以及对无线电收发器的访问

include/bluetooth/

公共API头文件。这些是应用程序需要包含的头文件,以便使用蓝牙功能

drivers/bluetooth

HCI传输层驱动。每个HCI传输层都需要自己的驱动程序。(三线uart或者5线uart,usb,spi等)

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/420047.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【电机仿真】空间矢量脉宽调制(SVPWM)算法与实现

前言 文章【电机仿真】永磁同步电机模型中所提及了PMSM数学模型&#xff0c;模型算法是电机控制的理论基础&#xff0c;但在实际控制中&#xff0c;需要将这两部分具象化。实际电机所需要的总是三相电流或者电压&#xff0c;控制对象为逆变器中的开关器件&#xff0c;我们需要将…

C/C++ Zlib库调用Minzip来封装MyZip压缩类

文章目录 1、C/C Zlib库调用Minzip来封装MyZip压缩类1.1、类的功能实现1.1.1、ZIP压缩函数 Compress1.1.2、ZIP解压函数 UnCompress1.1.3、代码如下1.1.4、如何使用类 1、C/C Zlib库调用Minzip来封装MyZip压缩类 Zlib是一个开源的数据压缩库&#xff0c;提供了一种通用的数据压…

金仕达与 DolphinDB 建立深度合作,共筑 FICC 科技创新新篇章

从“关起门做交易”到“打开门做服务”&#xff0c;国内 FICC 业务正经历从自营到市场化服务的转变&#xff0c;借助数据分析、算法交易等技术的快速发展&#xff0c;交易团队能够更加主动地发现市场需求&#xff0c;为不同客群提供更好的做市业务&#xff0c;FICC 交易电子化已…

用于制作耳机壳的倒模专用UV树脂有什么特点?

制作耳机壳的UV树脂耳机壳UV胶具有以下特点&#xff1a; 快速固化&#xff1a;UV树脂可以在紫外线的照射下迅速固化&#xff0c;大大缩短了制作时间。高硬度与高耐磨性&#xff1a;UV树脂具有较高的硬度和耐磨性&#xff0c;能够提供良好的保护效果。透明度高&#xff1a;UV树…

靶机渗透之ConnectTheDots

对于vulnhub中的靶机&#xff0c;我们都需先下载镜像&#xff0c;然后导入VM&#xff0c;并将网络连接改为NAT模式。首先我们再来看一下靶机渗透的步骤&#xff1a;信息收集-漏洞分析-漏洞利用-提权。基本都是这个三个步骤&#xff0c;接下来开始我们今天的靶机渗透吧&#xff…

qt QRadioButton 及QButtonGroup 使用

QRadioButton 放在组合框QGroupBox中&#xff0c;再点击时&#xff0c;即使有多个QRadioButton按钮&#xff0c;同时选中的也就只有一个。 如下图所示&#xff0c; 对于多个QRadioButton&#xff0c;每个按钮都写一个槽函数是不太明智的选择&#xff0c;需要将QRadioButton放在…

续上一篇---Jetson Xavier NX 开发板板载摄像头教程

测试摄像头&#xff0c;打开 NX 的终端 写入命令&#xff1a;nvgstcapture-1.0 摄像头就会起来了&#xff0c;想关掉摄像头的话&#xff0c;直接在终端输入 q 再按回车&#xff1b;想捕获图片的话&#xff0c;在终端输入 j 再按回车&#xff0c;图片将保存当前目录下。 手册中…

html基础操练和进阶修炼宝典

文章目录 1.超链接标签2.跳锚点3.图片标签4.表格5.表格的方向属性6.子窗口7.音视频标签8.表单9.文件上传10.input属性 html修炼必经之路—各种类型标签详解加展示&#xff0c;关注点赞加收藏&#xff0c;防止迷路哦 1.超链接标签 <!DOCTYPE html> <html lang"en…

使用Python语言实现一个基于动态数组的序列队列

一、动态数组的实现 首先&#xff0c;我们需要创建一个DynamicArray类&#xff0c;该类将管理我们的动态数组。 动态数组能够动态地调整其大小&#xff0c;以容纳更多的元素。 目录 一、动态数组的实现 代码示例&#xff1a; 二、序列队列的实现 接下来&#xff0c;我…

Flutter Text 下划线

IntrinsicWidth(child: Column(mainAxisAlignment:MainAxisAlignment.center,children: [Text("工单名称",style: TextStyle(overflow: TextOverflow.fade,color: AppColors.baseColor,fontSize: 15.sp,// decorationStyle: TextDecorationStyle.dashed),),Container…

PCIE Retimer

1 Retimers retimer是一种PCIE的扩展设备&#xff0c;用于长距离高效地传输数据&#xff0c;起到一种中继器的作用。在EP和RC中间最多允许两级retimers级联&#xff0c;其可以分为纯模拟类&#xff0c;它是一种对物理层协议无关的芯片&#xff1b;另一种便是与物理层交互的芯片…

xsslabs第四关

测试 "onclick"alert(1) 这与第三关的代码是一样的&#xff0c;但是每一关考的点是不一样的所以我们看一下源代码 <!DOCTYPE html><!--STATUS OK--><html> <head> <meta http-equiv"content-type" content"text/html;ch…

奇安信发布《2024人工智能安全报告》,AI深度伪造欺诈激增30倍

2024年2月29日&#xff0c;奇安信集团对外发布《2024人工智能安全报告》&#xff08;以下简称《报告》&#xff09;。《报告》认为&#xff0c;人工智能技术的恶意使用将快速增长&#xff0c;在政治安全、网络安全、物理安全和军事安全等方面构成严重威胁。 《报告》揭示了基于…

生成式AI与仿真

仿真模型是物理对象、系统或过程的虚拟表示&#xff0c;可预测其在不同场景中的行为和性能。 如今&#xff0c;仿真模型广泛应用于各行各业&#xff0c;以优化流程、为决策提供信息并创建数字孪生。 几十年来&#xff0c;仿真模型一直被用来对复杂的系统和过程进行建模。 这些…

性能测试-CPU使用率过高问题

一、通过jstack排查 1.通过top命令找到cpu占用高的应用程序进程 top 2.通过top -Hp pid查看该应用中占用CPU高的线程 top -Hp 5649 下图中是线程id 3.通过printf "%x\n" [线程id] 将线程高的线程号转为十六进制。 4.通过jstack过滤该十六进制的关键信息。jstack [进程…

阿里云短信发送

阿里云短信 发送短信验证码是现在日常生活中很常见的事务&#xff0c;但相信很多人都只是接受过验证码&#xff0c;并不知道验证码的生成过程&#xff0c;也不知道如何自己创建一个验证码。会简单介绍如何通过阿里云来创建一个验证码短信。 一、首先打开阿里云官网 官网&…

Intel 芯片 Mac 如何重新安装系统

使用可引导安装器重新安装&#xff08;可用于安装非最新的 Mac OS&#xff0c;系统降级&#xff0c;需要清除所有数据&#xff0c;过程确保连接上网络&#xff0c;虽然这种方式不会下载 Mac OS&#xff0c;但是需要下载固件等信息&#xff09; 插入制作好的可引导安装器&#x…

MYSQL--JDBC*

一.介绍: 1.JDBC是一种用于执行SQL于语句的JAVA API,JDBC是一种使用JAVA访问数据库的执行规范标准,能够为不同的数据库提供统一的访问!由一组使用JAVA语言编写的接口以及类组成的 2.JDBC核心的类以及相关的接口主要有: DriverManager 注册驱动 Connection 使用…

【学习心得】Python调用JS的三种常用方法

在做JS逆向的时候&#xff0c;一种情况是直接用Python代码复现JS代码的功能&#xff0c;达成目的。但很多时候这种方法有明显的缺点&#xff0c;那就是一旦JS代码逻辑发生了更改&#xff0c;你就得重写Python的代码逻辑非常不便。于是第二种情况就出现了&#xff0c;我直接得到…

ccadmin - 可免费试用的 FreeSWITCH web管理后台

ccadmin - FreeSWITCH web管理后台 简介免费测试在线预览功能说明 简介 顶顶通呼叫中心中间件Web后台管理系统简称CCAdmin-Web&#xff0c;用于管理和配置顶顶通呼叫中心中间件。因为顶顶通呼叫中心中间件是基于FreeSWITCH开发的&#xff0c;所以CCAdmin本质上也是一个FreeSWI…