UWB NI框架嵌入式实现——Qorvo示例
在Qorvo提供的DW3000示例代码中,实现了与Apple的NI框架的互通的示例,本文中针对其示例程序进行简要的分析。测试中使用Qorvo提供的模块,该模块为nRF52833+DW3000的架构。
1. Qorvo相关库文件
Qorvo在提供示例时,仅提供了相关的库文件代码以及使用说明,因此,本文也只能在整体库文件的基础上进行介绍。
Qorvo库文件封装了NI框架相关的操作,提供了库访问的头文件:niq.h
。注意:根据Qorvo Licence文件,需要商用,需要获得相关授权。
库文件:libniq-m4-hfp-0.9.9.1.a
,版本:0.9.9.1
。
引用库相关框架,主要包括:Qorvo的NI框架库、DW3000相关驱动(libdwt_uwb_driver-hfp-6.0.0d.a
,版本:6.0.0
)、uwbstack_lib(主要是与FiRa相关内容),可以理解NI框架为在FiRa标准之上,根据苹果设备的特性进行了一层封装。
1.1 关于NIQ库
niq库文件主要的内容如下,头文件niq.h
。
其中,初始化niq库,调用niq_init
函数,该函数主要涉及了UWB的开始与结束,加密相关秘钥的初始化与去初始化,包括测距秘钥向量生成等函数指针。
//vector生成等(STS需要使用)
int niq_init(const void (*start_uwb)(void), const void (*stop_uwb)(void), const void (*crypto_init)(void), const void (*crypto_deinit)(void),const void (*crypto_range_vector_geneator)(uint8_t * const data, size_t data_len));/* 重启NI框架,每次UWB TWR会话停止均需要调用 */
void niq_reinit(void);
/* 取消初始化NI Qorvo 模块,前置调用设置的crypto_deinit函数 */
void niq_deinit(void);
/* 停止 NI UWB TWR会话 */
void niq_stop_uwb(void);//设置测距角色,0 - Controlee + Responder, 1 - Controller + Initiator
void niq_set_ranging_role(uint8_t role);
// 提供第三方配件配置数据,用于OOB握手——>对外输出配置数据。
void niq_populate_accessory_uwb_config_data(void * out_buffer, uint8_t * out_buffer_len);
// 配置UWB会话参数,调用start_uwb()
int niq_configure_and_start_uwb(uint8_t *payload, uint8_t length, void *arg);/// ----------------------------------------------------------------------
/// The following definitions exposed to the embedded application
/// ----------------------------------------------------------------------#define E_NIQ_INPVAL 1
#define E_NIQ_VERSIONNOTSUPPORTED 2#define NI_ACCESSORY_PROTOCOL_SPEC_MAJOR_VERSION 1
#define NI_ACCESSORY_PROTOCOL_SPEC_MINOR_VERSION 0#define MAX_UWB_CONFIG_SIZE (64)
#define ACCESSORY_CONFIGURATION_DATA_FIX_LEN (16)
关于NI框架中,外设相关的配置数据内容结构体(在iOS NI框架介绍中有简单介绍)如下:
/* 80字节 */
struct AccessoryConfigurationData {uint16_t majorVersion; // NI Accessory Protocol major versionuint16_t minorVersion; // NI Accessory Protocol minor versionuint8_t preferredUpdateRate;uint8_t rfu[10];uint8_t uwbConfigDataLength;uint8_t uwbConfigData[MAX_UWB_CONFIG_SIZE];
} __attribute__((packed));
另外,可以看到,在底层UWB设备的配置中,包含了FiRa标准中对于设备的详细定义要求,如会话ID、测距轮使用、多节点模式等等参数的定义。
/* UWB Device unicast configuration,具体参数含义需要结合芯片手册以及FiRa相关要求 */
struct fira_device_configure_s {uint8_t role;uint8_t enc_payload;uint32_t Session_ID;uint8_t Ranging_Round_Usage;uint8_t Multi_Node_Mode;uint8_t Rframe_Config;uint8_t ToF_Report;uint8_t AoA_Azimuth_Report;uint8_t AoA_Elevation_Report;uint8_t AoA_FOM_Report;uint8_t nonDeferred_Mode;uint8_t STS_Config;uint8_t Round_Hopping;uint8_t Block_Striding;uint32_t Block_Duration_ms;uint32_t Round_Duration_RSTU;uint32_t Slot_Duration_RSTU;uint8_t Channel_Number;uint8_t Preamble_Code;uint8_t PRF_Mode;uint8_t SP0_PHY_Set;uint8_t SP1_PHY_Set;uint8_t SP3_PHY_Set;uint32_t MAX_RR_Retry;uint8_t Constraint_Length_Conv_Code_HPRF;uint32_t UWB_Init_Time_ms;uint8_t Block_Timing_Stability;uint8_t Key_Rotation;uint8_t Key_Rotation_Rate;uint8_t MAC_FCS_TYPE;uint8_t MAC_ADDRESS_MODE;uint8_t SRC_ADDR[2];uint8_t Number_of_Controlee;uint8_t DST_ADDR[2];// 用于测距中STS生成的秘钥 uint8_t Vendor_ID[2];uint8_t Static_STS_IV[6];
};
1.2 UWBStack Lib
uwbstack_lib
库部分,主要提供了FiRa协议相关参数等,其中相关参数、相关数据结构类型定义如下:
#define FIRA_HELPER_H//主要为FiRa定义的相关会话参数
struct session_parameters {uint8_t device_type;uint8_t device_role;// 测距轮使用uint8_t ranging_round_usage;// ono-to-one, one-to-many, many-to-manyuint8_t multi_node_mode;uint16_t destination_short_address;uint32_t initiation_time_ms;/*** @slot_duration_rstu: 测距时隙周期,单位RSTU,FiRa中为1200 RSTU = 1ms*/uint32_t slot_duration_rstu;//每个round的时隙数uint32_t round_duration_slots;uint32_t block_duration_ms;// 是否使能多跳bool round_hopping;// 通道,5/9uint8_t channel_number;/*** @preamble_code_index: Uwb preamble code index.* BPRF (9-24), HPRF (25-32)*/uint8_t preamble_code_index;uint8_t rframe_config;uint8_t sfd_id;/*** @vupper64: vUpper64 for static STS (STATIC_STS_IV | VENDOR_ID).* 8 Bytes*/u8 vupper64[FIRA_VUPPER64_SIZE];uint8_t rx_antenna_selection;uint8_t rx_antenna_pair_azimuth;uint8_t rx_antenna_pair_elevation;uint8_t tx_antenna_selection;uint8_t rx_antenna_switch;uint8_t aoa_result_req;uint8_t report_tof;uint8_t report_aoa_azimuth;uint8_t report_aoa_elevation;uint8_t report_aoa_fom;u32 data_vendor_oui;
};struct controlee_parameters {/*** @address: Controlee short address.*/uint16_t address;
};
// 受控端参数,FIRA最大受控端数为16,参数主要是受控端的u16短地址
struct controlees_parameters {/*** @controlees: List of controlees.*/struct controlee_parameters controlees[FIRA_CONTROLEES_MAX];/*** @n_controlees: Number of controlees in the list.*/int n_controlees;
};enum aoa_measurements_index {FIRA_HELPER_AOA_AZIMUTH,FIRA_HELPER_AOA_ELEVATION,FIRA_HELPER_AOA_MAX
};
/* FiRa AoA 测量 */
struct aoa_measurements {uint8_t rx_antenna_pair; //天线对索引uint8_t aoa_fom; //本地AoA估计的质量int16_t aoa_2pi; //估计接收角度
};struct ranging_measurements {//...
};struct ranging_results {//...
};
FiRa库相关涉及函数原型如下定义:
// 设置调度器,Fira域,调用时UWB MAC必须停止
int fira_helper_set_scheduler(void);
// 初始化FiRa会话,用于创建和初始化fira会话
int fira_helper_init_session(uint32_t session_id);
// 启动FiRa会话,port_id用于通知
int fira_helper_start_session(uint32_t session_id, uint32_t port_id);
int fira_helper_stop_session(uint32_t session_id);
// 释放会话分配的内存,必须在会话已经停止的情况下调用。即在stop_session后调用
int fira_helper_deinit_session(uint32_t session_id);
// 设置FiRa会话参数
int fira_helper_set_session_parameters(uint32_t session_id, const struct session_parameters *session_params);
// 特定FiRa会话中添加受控端
int fira_helper_add_controlees(uint32_t session_id,const struct controlees_parameters *controlees);
int fira_helper_delete_controlees(uint32_t session_id, const struct controlees_parameters *controlees);
int fira_helper_parse_ranging_report(struct sk_buff *msg,struct ranging_results *results);
int fira_helper_send_data(uint32_t session_id,const struct data_parameters *data_params);
fira_region_params.h
为FiRa域相关参数,包括设备类型(Controller或Controlee),设备角色(发起者、应答者)、ROUND使用方式(OWR、SSTWR、DSTWR)、模式(单播、一对多、多对多)、结果报告(AT_RESPONDER,AT_INITIATOR)、RF帧的模式(SP0、SP1、SP2、SP3,Qorvo主要是0,1,3,未支持2)、PRF模式等。
1.3 底层驱动实现
在本示例中使用nRF52833作为主控芯片,一方面需要实现DW3000的底层访问相关驱动的移植。
HAL_DW3000.c
主要为针对Nordic平台的移植工作,包括中断处理等操作。- 注意:在代码中提到NRF芯片仅有1个IRQ用于所有的GPIO引脚,因此DW3000的(中断)irqN、(复位RST)rstIrqN均挂在
GPIOTE_IRQn
上,具体在中断函数中process_deca_irq
处理,根据IRQ引脚的状态判断是IRQ中断还是RST中断。
另外,由于NI框架在实现中,需要使用BLE来实现与苹果设备的数据交换,即利用BLE实现OOB,在本示例中使用nRF52833相关蓝牙服务实现。
2. MAC层数据服务相关实现简介
从IEEE 802.15.4协议中,MAC层数据传输服务提供了三种数据传输的原语:MCPS-DATA.request、MCPS-DATA.confirm、MCPS-DATA.indication。
在本示例的实现中,依然按照相关框架来进行实现。
#incluce <net/mac802154.h>struct ieee802154_hw {int extra_tx_headroom;u32 flags;struct device *parent;void *priv;struct wpan_phy *phy; //底层设备驱动
};//头文件主要提供内容,包括ieee802154_hw的分配与释放
struct ieee802154_hw *ieee802154_hw_alloc(void);
struct ieee802154_hw *ieee802154_hw_free(void);//struct dwchip_s在deca_interface.h中定义。
// IEEE 802.15.4 MCPS相关实现API接口
struct dwchip_s *dw3000_mcps_alloc(void);
int dw3000_mcps_register(struct dwchip_s *dw);
void dw3000_mcps_unregister(struct dwchip_s *dw);
void dw3000_mcps_free(struct dwchip_s *dw);
//芯片结构体,包括硬件抽象层(HAL)、驱动、MCPS已经接收结构体
struct dwchip_s
{ /*HAL*/struct dwt_spi_s *SPI; // firstvoid(*wakeup_device_with_io)(void);/*Driver*/struct dwt_driver_s *dwt_driver;struct dwt_callbacks_s callbacks;/* driver configuration */struct dwt_mcps_config_s *config;/* MCPS */struct mcps802154_llhw *llhw; struct mcps802154_ops *mcps_ops; //<net/mac802154.h>struct dw3000_calibration_data *calib_data;struct dwt_mcps_runtime_s *mcps_runtime;/* rx structure */struct dwt_mcps_rx_s *rx;/* GPIO used to switch off WIFI while transmitting, for example */int8_t coex_gpio_pin;int8_t coex_gpio_active_state;/** driver data*/void *priv; // last
};
当然,在当前Qorvo提供的示例代码中均对相关源码进行了封装,在后续的文章中,尽量从其实现的框架上来和大家一起来对其实现进行剖析。
/*** mac层相关操作回调接口,包括启动、停止,同步,ED检测,设置信道,*/
struct ieee802154_ops {struct module *owner;int (*start)(struct ieee802154_hw *hw);void (*stop)(struct ieee802154_hw *hw);int (*xmit_sync)(struct ieee802154_hw *hw, struct sk_buff *skb);int (*xmit_async)(struct ieee802154_hw *hw, struct sk_buff *skb);// 能量检测int (*ed)(struct ieee802154_hw *hw, u8 *level);// 通道设置int (*set_channel)(struct ieee802154_hw *hw, u8 page, u8 channel);int (*set_hw_addr_filt)(struct ieee802154_hw *hw,struct ieee802154_hw_addr_filt *filt,unsigned long changed);// 功率设置int (*set_txpower)(struct ieee802154_hw *hw, s32 mbm);int (*set_lbt)(struct ieee802154_hw *hw, bool on);// CCA模式,当前从相关注释来看并没有支持,cfg802154.h中struct wpan_phy_cca为空。int (*set_cca_mode)(struct ieee802154_hw *hw,const struct wpan_phy_cca *cca);int (*set_cca_ed_level)(struct ieee802154_hw *hw, s32 mbm);int (*set_csma_params)(struct ieee802154_hw *hw, u8 min_be, u8 max_be,u8 retries);int (*set_frame_retries)(struct ieee802154_hw *hw, s8 retries);int (*set_promiscuous_mode)(struct ieee802154_hw *hw, const bool on);void (*sw_scan_start)(struct ieee802154_hw *hw, __le64 addr);void (*sw_scan_complete)(struct ieee802154_hw *hw);
};
从ieee802154_ops
结构体来看,基本为标准IEEE 802154相关操作定义,在前面介绍的Linux相关UWB Stack实现中均会涉及。
相关术语
MAC,Medium Access Control,媒介访问控制,负责控制共享介质的访问方式和规则,保证多个节点间的通信能够有效地进行。
MCPS,MAC Common Part Sublayer,MAC公共部分子层,是整个MAC层的核心,提供数据传输服务。
MLME,MAC Layer Management Entity,为MAC层管理实体,提供管理服务。
相关文章:
UWB NI框架嵌入式实现——Qorvo示例
在Qorvo提供的DW3000示例代码中,实现了与Apple的NI框架的互通的示例,本文中针对其示例程序进行简要的分析。测试中使用Qorvo提供的模块,该模块为nRF52833DW3000的架构。 1. Qorvo相关库文件 Qorvo在提供示例时,仅提供了相关的库文…...
Linux OS源的问题记录
场景 安装了一台Linux虚拟机充当服务器,准备搭建一个elk环境,我使用命令安装docker的时候,报错提示 YumRepo Error: All mirror URLs are not using ftp, http[s] or file.Eg. Invalid release/repo/arch combination/ removing mirrorlist…...

数据库:Hive转Presto(五)
此篇将所有代码都补充完了,之前发现有的代码写错了,以这篇为准,以下为完整代码,如果发现我有什么考虑不周的地方,可以评论提建议,感谢。代码是想哪写哪,可能比较繁琐,还需要优化。 …...

SQL中for xml path 的用法
1. 用法 是一种将查询结果转换为 XML 格式的方法。它可以将查询结果中的每一行转换为一个 XML 元素,并且可以指定元素的名称和属性。 2. 应用示例 有一张学生选修课程的表,如下图所示 希望整合成下图所示效果 --建表 if object_id(StudentInfo,u) is…...

【TensorFlow2 之014】在 TF 2.0 中实现 LeNet-5
一、说明 在这篇文章中,我们将展示如何在 TensorFlow 中实现像 \(LeNet-5\) 这样的基础卷积神经网络。LeNet-5 架构由 Yann LeCun 于 1998 年发明,是第一个卷积神经网络。 数据黑客变种rs 深度学习 机器学习 TensorFlow 2020 年 2 月 29 日 | 0 …...

【2023】redis-stream配合spring的data-redis详细使用(包括广播和组接收)
目录 一、简介1、介绍2、对比 二、整合spring的data-redis实现1、使用依赖2、配置类2.1、配置RedisTemplate bean2.2、异常类 3、实体类3.1、User3.2、Book 4、发送消息4.1、RedisStreamUtil工具类4.2、通过延时队列线程池模拟发送消息4.3、通过http主动发送消息 5、dz…...

飞书应用机器人文件上传
背景: 接上一篇 flask_apscheduler实现定时推送飞书消息,当检查出的异常结果比较多的时候,群里会有很多推送消息,一条条检查工作量会比较大,且容易出现遗漏。 现在需要将定时任务执行的结果记录到文件,…...

高版本Mac系统如何打开低版本的Xcode
这里写目录标题 前言解决方案 前言 大家偶尔也碰见过更新Mac系统后经常发现低版本的Xcode用不了的情况吧.基本每年大版本更新之后都可以在各个开发群里碰见问这个问题的. 解决方案 打开访达->应用程序->选中打不开的那个版本的Xcode并且右键显示包内容->Contents-…...
测试H5需要注意的交互测试用例点
H5(HTML5)是一种用于构建网页的标准,可以实现丰富的交互和功能。测试H5交互通常涉及到验证网页在各种情况下的行为,包括用户输入、按钮点击、页面加载等等。以下是一些可能的H5交互测试用例: 页面加载: 验…...

1014蓝桥算法双周赛,学习算法技巧,助力蓝桥杯
家人们,我来免费给大家送福利了!!! 【1014蓝桥算法双周赛 】 背景 蓝桥杯全国软件和信息技术专业人才大赛是由工业和信息化部人才交流中心举办的全国性IT学科赛事。参赛高校超过1200余所,累计参赛人数超过40万人。该…...

C语言之通讯录的实现篇
目录 test.c 主菜单menu 创建通讯录con 初始化通讯录InitContact 增加个人信息AddContact 展示个人信息ShowContact 删除个人信息DelContact 查找个人信息SearchContact 修改个人信息ModifyContact test.c总代码 contact.h 头文件包含 PeoInfo_个人信息的设置声…...

如何降低海康、大华等网络摄像头调用的高延迟问题(二)
目录 1.RTSP介绍 2.解决办法1 3.解决办法2 1.RTSP介绍 RTSP(Real-time Streaming Protocol)是一种用于实时流媒体传输的网络协议。它被设计用于在服务器和客户端之间传输音频、视频以及其他流媒体数据。 RTSP协议允许客户端通过与服务器建立RTSP会话…...
centos清理日志和缓存
今天使用redmine修改密码,修改报错,再去试试创建用户,创建用户的页面直接报错显示不出来。然后看了一下服务器,发现服务器磁盘空间全部占满了。 CentOS系统也会在使用很长一段时间后出现硬盘空间开始不够的情况,而这并…...
排序算法的稳定性
什么是排序算法的稳定性? 排序算法的稳定性: 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i] r[j],且 r[i…...

kafka属性说明
kafka中关于一些字段说明 groupId :标识消费者分组id,如果多个消费者id相同,就表示这几个消费者是一组,当一组多个消费者消费同一个topic时,一组中只会有一个成功消费 代码如下 这时只会有一条消息被消费...
STM32F4使用ucosii时操作浮点数卡死的问题
STM32F4使用ucosii时操作浮点数卡死的问题_stm32 fpu float 程序跑不起来_shou撕代码的博客-CSDN博客...

python练习:赋值运算 => 输入身高,体重,求BMI = 体重(kg)/身高(m)的平方。
赋值运算 > 输入身高,体重,求BMI 体重(kg)/身高(m)的平方。 代码: height float(input(‘请输入您的身高(m):’)) weight float(input(‘请输入您的体重(kg):’))…...
PCL ICP精配准(点到点)
文章目录 一、简介二、实现过程三、实现效果参考资料一、简介 迭代最近点(ICP)算法作为是目前最常用的刚性点集配准方法,它有着简单、计算复杂度低等优点,该算法的具体计算过程如下: (1)在目标点云P中取点集 p i ∈ P p_i∈P p...
Redis数据缓存(Redis的缓存击穿和穿透的区别)
Redis是一个高性能的内存中数据存储系统,可以使用它作为数据缓存。使用Redis作为数据缓存可以提高应用程序的性能和可伸缩性,因为Redis运行在内存中,读写速度非常快。 Redis支持许多数据结构,如字符串、哈希表、列表、集合和有序…...

八大排序算法(含时间复杂度、空间复杂度、算法稳定性)
文章目录 八大排序算法(含时间复杂度、空间复杂度、算法稳定性)1、(直接)插入排序1.1、算法思想1.2、排序过程图解1.3、排序代码 2、希尔排序3、冒泡排序3.1、算法思想3.2、排序过程图解3.3、排序代码 4、(简单)选择排序4.1、算法…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...