UWB NI框架嵌入式实现——Qorvo示例

这篇具有很好参考价值的文章主要介绍了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 version
    uint16_t            minorVersion; // NI Accessory Protocol minor version
    uint8_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-many
	uint8_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/9
	uint8_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; // first
    void(*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层管理实体,提供管理服务。

Linux内核 IEEE 802.15.4规范相关实现,头文件定义:mac802154.h。文章来源地址https://www.toymoban.com/news/detail-725087.html

到了这里,关于UWB NI框架嵌入式实现——Qorvo示例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【嵌入式总复习】Linux管道详解——管道通信、无名管道、有名管道、具体应用示例

    进程间的通信方式有五种,分别为:管道,信号量,共享内存,消息队列和套接字 把一个程序的输出直接连接在另外一个程序的输入。 管道分为有名管道和无名管道两种,它们的区别是: 无名管道只能在父子进程之间进行通信。 有名管道又称为命名管道,可以在任意两个进程之间进行

    2024年02月08日
    浏览(58)
  • 嵌入式驱动开发之框架及调试技巧累积

    知识储备。 在linux系统中,App无法操作硬件的,不具备相应的权限。在mmu(内存管理单元)作了划分的,应用层只能操作属于它的mmu部分。操作硬件只能是通过驱动程序。应用程序与驱动程序之间有严格的界限。驱动程序在内核中。 如App使用open函数打开设备时,会先设置某个寄

    2024年02月06日
    浏览(39)
  • 嵌入式系统专业术语以及AHL-STM32L431运行示例程序

    目录 一、嵌入式术语 1.1 与硬件相关的术语 1.2 与通信相关的术语 1.3 与功能模块相关的术语 二、运行示例程序,并得出结论 1.1 与硬件相关的术语 封装(Package,PKG)   封装是指将集成电路芯片封装在外部包装中以保护芯片并便于连接到电路板上。不同类型的封装可以影响芯

    2024年04月09日
    浏览(41)
  • 分享一款嵌入式开源按键框架代码工程MultiButton

    MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块。 Github地址:https://github.com/0x1abin/MultiButton 这个项目非常精简,只有两个文件: (1)可无限扩展按键; (2)按键事件的回调异步处理方式可以简化程序结构,去除冗余的按键处理硬编码,让按键业务逻辑更清晰。 通

    2024年04月15日
    浏览(64)
  • 痞子衡嵌入式:使用恩智浦GUI Guider快速创建全新LCD屏示例工程的步骤

    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是 使用恩智浦GUI Guider快速创建全新LCD屏示例工程的步骤 。 在痞子衡旧文 《在i.MXRT1170上快速点亮一款全新LCD屏的方法与步骤》 里,痞子衡介绍了在官方 SDK 裸机驱动 elcdif 示例工程基础上做修改以支持一

    2024年03月13日
    浏览(47)
  • Azure RTOS & 嵌入式无线网络框架简化物联网应用开发

    一、Azure RTOS概述 Azure RTOS 是一个实时操作系统 (RTOS),适用于由微控制器 (MCU) 提供支持的物联网 (IoT) 和边缘设备, Azure RTOS 旨在支持高度受限设备(电池供电,并且闪存容量不到 64 KB)。简而言之,这就是一套完整的针对于物联网应用开发的带有多线程功能,中间件和桌面

    2024年02月08日
    浏览(62)
  • 嵌入式_一种非常简单实用的基于GD32的裸机程序框架

    搜索了一下关于GD或ST裸机程序的问题,网上有非常多也非常的例子,但是针对裸机开发的程序框架却比较少,这里简单整理了一下在项目中使用过的一种比较小巧便携的裸机程序框架(确切点说算不上框架,只能说一种写法)。 之前常见的裸机程序框架就是流水账框架,比

    2024年02月13日
    浏览(44)
  • 【嵌入式Linux内核驱动】SPI子系统 | 硬件原理 | 应用编程 | 内核驱动 | 总体框架

    1.1 SPI通信协议 SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线 四根通信线:SCK(Serial Clock)、MOSI(Master Output Slave Input)、MISO(Master Input Slave Output)、SS(Slave Select) 同步,全双工 支持总线挂载多设备(一主多从) 1.2 硬件连接 多NSS独立片选方式 菊花

    2024年02月16日
    浏览(64)
  • 【速成】蓝桥杯嵌入式省一教程:(五)用按键和屏幕实现嵌入式交互系统

    一个完整的嵌入式系统,包括任务执行部分和人机交互部分。在前四节中,我们已经讲解了LED、LCD和按键,用这三者就能够实现一个人机交互系统,也即搭建整个嵌入式系统的框架。在后续,只要将各个功能加入到这个交互系统中,即可完成整个嵌入式系统的设计。因此,尽

    2024年02月09日
    浏览(61)
  • 速通蓝桥杯嵌入式省一教程:(五)用按键和屏幕实现嵌入式交互系统

    一个完整的嵌入式系统,包括任务执行部分和人机交互部分。在前四节中,我们已经讲解了LED、LCD和按键,用这三者就能够实现一个人机交互系统,也即搭建整个嵌入式系统的框架。在后续,只要将各个功能加入到这个交互系统中,即可完成整个嵌入式系统的设计。因此,尽

    2024年02月12日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包