5。用户指南

5.1。BLE框架

图24描述所使用的通用架构方案。

. . / _images / 046. png

图24BLE框架体系结构

使用自顶向下方法,累积BLE框架的层功能可以确定为以下:

  1. 保佑服务框架提供了保佑服务,应用程序可以使用“开箱即用”,使用简单的初始化函数和各种祝福服务回调事件(如一个警戒级别属性的变化)。BLE服务框架的功能是基于对话框的顶部BLE API库。BLE服务API头文件可以找到<代码class="docutils literal notranslate">< sdk_root_directory > / sdk /接口/祝福/服务/包括。BLE服务回调应用程序执行的任务,使用BLE服务框架。

  2. 对话框BLE API是一组函数,可以用来启动保佑操作或应对保佑事件。API的头文件路径下可以找到<代码class="docutils literal notranslate">< sdk_root_directory > / sdk /接口/祝福/ api /包括。API函数可以用来发送消息(命令或回复事件)BLE经理,通过直接调用BLE经理命令处理程序或应用程序之间使用队列任务和BLE管理器的任务。BLE API被称为应用程序的上下文中。

  3. 祝福祝福manager提供了接口功能的芯片。应用程序的任务是基于保佑功能使用对话框的保佑与祝福管理器API接口。之间的祝福manager是一个任务,应用程序和BLE适配器。它使用保佑适配器接口与保佑堆栈。BLE管理器使用一个通用的传输层(GTL)接口与祝福适配器通信通过一个命令和事件队列。BLE管理器是一个独立的系统任务。

  4. BLE适配器是系统任务,提供的接口BLE堆栈。它运行BLE栈内部调度程序,接收的命令或回复来自BLE的事件管理器,并通过保佑事件保佑经理。保佑核心功能实现的保佑适配器的任务。

  5. BLE堆栈的软件栈实现BLE主机和低能量(LE)控制器(链路层)。BLE主机包括逻辑链路控制和适应协议(L2CAP),安全管理协议(SMP)、属性(ATT)协议,通用属性剖面(关贸总协定)和通用访问配置文件(GAP)。BLE堆栈API头文件,DA1469x,可以找到<代码class="docutils literal notranslate">< sdk_root_directory > / sdk /接口/祝福/栈/ da14690 /包括。保佑栈软件是运行在保佑适配器的任务上下文。

5.1.1。开发BLE应用程序亚博国际官网平台网址

的一个主要目标SmartSnippets™DA1469x SDK是简化BLE应用程序的开发,实现快速投放市场的时间。亚博国际官网平台网址的SmartSnippets™DA1469x SDK将应用程序逻辑与祝福堆栈实现和提供了一个干净的和强大的API与祝福交互功能的设备。的保佑API提供了一个简单的方法来配置保佑设备,开始空中作战和关贸总协定的设置属性数据库服务器。BLE服务API提供预定义的蓝牙特别兴趣小组概况与只有几回调函数的定义。

接近记者(<代码class="docutils literal notranslate">pxp_reporter)应用程序是祝福的最典型的应用程序包含在SmartSnippets™DA1469x SDK亚博国际官网平台网址。它是一个完整的开发和固体BLE的例子应用程序在SmartSnippets™DA1469x SDK。它使用对话框BLE API和保佑服务框架实现的功能保佑概要文件。

然而,它可能不是最简单的例子或最好的起点熟悉从头BLE的开发应用程序。相反,有祝福项目专门为特定的祝福作为起点创建应用程序如灯塔(亚博国际官网平台网址<代码class="docutils literal notranslate">ble_adv_demo)或特定的角色如通用外围(<代码class="docutils literal notranslate">ble_peripheral)或中心(<代码class="docutils literal notranslate">ble_central)设备。

本节的目标是介绍各种选项和例子中存在SmartSnippets™DA1469x SDK,可以用作许多应用程序构建块。亚博国际官网平台网址经过短暂的介绍API可以找到头文件,每一个部分描述了它们实现的功能以及指导他们如何不同于对方。这些信息是至关重要的从头开发BLE应用程序时。

5.1.2中。BLE API头文件

5.1.2.1。对话框BLE API

所有演示和服务API中可以找到(Ref_04)

在大多数项目这些API位于头文件是象征性地与文件

< sdk_root_directory > / sdk /祝福/ api /包括

跨几个API函数声明头文件根据它们的功能:

  • 通用的API (ble_common.h):功能用于操作,而不是特定于特定的祝福设备软件组件。例如:

表15 API函数的常见BLE设备软件组件

函数

描述

ble_register_app ()

BLE框架注册应用程序,以便它可以接收BLE事件通知。

ble_enable ()

让祝福模块。

ble_reset ()

重置BLE模块。

ble_central_start ()

BLE中央启动设备。这实际上是一个helper函数,因为它使用API调用ble_enable()和ble_gap_role_set ()。

ble_peripheral_start ()

开始祝福外围设备。这也是一个helper函数,使用ble_enable()和ble_gap_role_set ()。

ble_get_event ()

保佑事件从保佑事件队列。

ble_has_event ()

检查是否有一个事件等待幸运的事件队列。

ble_handle_event_default ()

用于定义处理的事件不是由添加的服务或应用程序定义处理程序。

  • 差距和L2CAP api (ble_gap.h / ble_l2cap.h):涵盖了范围广泛的操作,如

    • 设备参数配置:设备的作用、MTU大小、设备名称暴露在服务属性的差距,等等。

    • 空中作战:广告、扫描连接,连接请求作出反应,启动或响应连接参数更新,等等。

    • 安全操作:启动和响应配对或焊接程序,设置安全级别,unpair等等。

表16 差距,L2CAP API函数

函数

描述

BLE设备配置

ble_gap_role_get ()

目前角色设置的差距。

ble_gap_role_set ()

设置设备差距角色(中央,外围,观察者,广播)。

ble_gap_mtu_size_get ()

获取当前MTU大小设置。

ble_gap_mtu_size_set ()

设置MTU大小用于MTU交易所交易。

ble_gap_channel_map_get ()

获取当前设置通道的地图设备(设备必须配置为中心)。

ble_gap_channel_map_set ()

设置设备的通道映射(设备必须配置为中心)。

ble_gap_address_get ()

获取当前使用的BD地址设备。

ble_gap_address_set ()

设备的设置BD地址。

ble_gap_device_name_get ()

得到各自的属性中使用的设备名称服务的差距。

ble_gap_device_name_set ()

设置设备名称中使用各自的属性差距服务。

ble_gap_appearance_get ()

得到各自的属性中使用的外观差异服务。

ble_gap_appearance_set ()

设置中使用的外观的各自属性差距服务。

ble_gap_per_pref_conn_params_get ()

得到外围优先连接参数用于各自的属性差距服务。

ble_gap_per_pref_conn_params_set ()

设置首选外围连接参数用于各自的属性差距服务。

ble_gap_get_io_cap ()

I / O设备的能力。

ble_gap_set_io_cap ()

设置设备的I / O功能(结合同行的I / O功能,这将决定配对算法将使用)。

ble_gap_data_length_set ()

设置数据长度用于传输新连接。

广告

ble_gap_adv_start ()

广告开始。

ble_gap_adv_stop ()

停止广告。

ble_gap_adv_data_set ()

设置广告使用数据和扫描响应数据。

ble_gap_adv_ad_struct_set ()

广告数据集和扫描响应数据<代码class="docutils literal notranslate">::gap_adv_ad_struct_t类型

ble_gap_adv_data_get ()

获取当前使用的广告数据和扫描响应数据。

ble_gap_adv_intv_get ()

获取当前设置广告间隔。

ble_gap_adv_intv_set ()

设置广告间隔(ble_gap_adv_start之前完成())。

ble_gap_adv_chnl_map_get ()

获取当前广告通道映射设置。

ble_gap_adv_chnl_map_set ()

设置广告通道映射(ble_gap_adv_start之前完成())。

ble_gap_adv_mode_get ()

可发现性模式用于广告。

ble_gap_adv_mode_set ()

设置用于广告的可发现性模式(ble_gap_adv_start之前完成())。

ble_gap_adv_filt_policy_get ()

得到过滤政策用于广告。

ble_gap_adv_filt_policy_set ()

设置过滤政策用于广告。

ble_gap_adv_direct_address_get ()

得到对方地址用于定向广告。

ble_gap_adv_direct_address_set ()

设置对等地址用于指导广告(ble_gap_adv_start之前完成())。

扫描

ble_gap_scan_start ()

开始扫描设备。

ble_gap_scan_stop ()

停止扫描设备。

连接管理

ble_gap_scan_params_get ()

得到的扫描参数用于未来的连接。

ble_gap_scan_params_set ()

设置扫描参数用于未来的连接。

ble_gap_connect ()

发起一个直接连接到一个设备。

ble_gap_connect_ce ()

发起一个直接连接与一个应用程序定义的最小和最大连接事件的长度

ble_gap_connect_cancel ()

取消一个发起连接过程。

ble_gap_disconnect ()

发起一个断开过程建立了联系。

ble_gap_peer_version_get ()

得到同行的版本建立连接。

ble_gap_peer_features_get ()

得到对等的功能建立连接。

ble_gap_conn_rssi_get ()

得到的RSSI连接。

ble_gap_conn_param_update ()

发起一个连接参数更新或更新请求过程(根据角色组和同行的支持功能)。

ble_gap_conn_param_update_reply ()

回复一个连接参数更新请求。

ble_gap_data_length_set ()

设置用于传输的数据长度指定连接。

ble_gap_phy_get ()

发射机和接收机PHY(缺省首选或指定的连接)。

ble_gap_phy_set ()

设置PHY用于RX和TX(缺省或对于一个给定的连接)。

安全

ble_gap_pair ()

开始配对。

ble_gap_pair_reply ()

回应一个配对请求。

ble_gap_passkey_reply ()

回应请求万能钥匙。

ble_gap_numeric_reply ()

回复数字比较请求(仅LE安全连接)。

ble_gap_get_sec_level ()

得到链接安全性水平。

ble_gap_set_sec_level ()

安全级别设置链接。

ble_gap_unpair ()

Unpair设备(从祝福也会删除相关的债券数据存储)。

ble_gap_address_resolve ()

解决BD地址存储在BLE存储使用的讨厌。

辅助函数

ble_gap_get_connected ()

获得连接设备的列表。

ble_gap_get_bonded ()

得到的保税设备列表。

ble_gap_get_devices ()

返回列表的设备基于过滤器。

ble_gap_get_device_by_addr ()

设备对象,考虑到设备地址。

ble_gap_get_device_by_conn_idx ()

设备对象,考虑到连接索引。

ble_gap_is_bonded ()

获得债券的设备状态(通过连接索引)。

ble_gap_is_addr_bonded ()

获得债券的设备(地址)。

专家功能

ble_gap_skip_latency ()

暂时忽略连接延迟。

  • 关贸总协定服务器API (ble_gatts.h):设置属性数据库,设置属性值,通知/指示特征值,启动MTU交往,响应读写请求等。

表17 关贸总协定服务器API

函数

描述

ble_gatts_add_service ()

添加一个新的关贸总协定ATT数据库服务。后续调用ble_gatts_add_include (), ble_gatts_add_characteristic()和ble_gatts_add_descriptor()将属性添加到服务,这叫补充道。

ble_gatts_add_include ()

添加一个服务包括服务声明添加ble_gatts_add_service ()。

ble_gatts_add_characteristic ()

添加一个特征声明服务添加ble_gatts_add_service ()。

ble_gatts_add_descriptor ()

添加一个描述符声明服务添加ble_gatts_add_service ()。

ble_gatts_register_service ()

增加攻击力数据库之前所有属性添加到服务。

ble_gatts_enable_service ()

在数据库启用服务。

ble_gatts_disable_service ()

禁用服务数据库。

ble_gatts_get_characteristic_prop ()

读取当前特征的属性和权限。

ble_gatts_set_characteristic_prop ()

设置特征的属性和权限。

ble_gatts_get_value ()

获取属性值。

ble_gatts_set_value ()

设置属性值。

ble_gatts_read_cfm ()

确认一个属性读取请求的响应。

ble_gatts_write_cfm ()

确认一个属性写请求的响应。

ble_gatts_prepare_write_cfm ()

确认一个属性准备写请求的响应。

ble_gatts_send_event ()

发送一个特征值通知或指示。

ble_gatts_service_changed_ind ()

发送指示服务的变化特点。

ble_gatts_get_num_attr ()

计算服务所需的属性。

  • 关贸总协定客户机API (ble_gattc.h):设备配置为使用的关贸总协定客户发现服务,特点,对等设备等,读或写它的属性,启动MTU交流,确认迹象的接待等。

表18 关贸总协定客户机API

函数

描述

ble_gattc_browse ()

浏览远程关贸总协定服务器上的服务。

ble_gattc_browse_range ()

浏览服务远程关贸总协定服务器在给定的范围内。

ble_gattc_discover_svc ()

远程关贸总协定服务器上发现服务。

ble_gattc_discover_include ()

发现包括远程关贸总协定服务器上的服务。

ble_gattc_discover_char ()

发现远程关贸总协定服务器上的特点。

ble_gattc_discover_desc ()

发现服务器上远程关贸总协定描述符。

ble_gattc_read ()

读一个特征值或特征描述符从远程关贸总协定服务器,根据属性处理。

ble_gattc_write ()

写一个特征值或特征描述符到远程关贸总协定服务器,根据属性处理。

ble_gattc_write_no_resp ()

属性写入远程关贸总协定服务器没有响应。

ble_gattc_write_prepare ()

准备长/可靠写远程关贸总协定服务器。

ble_gattc_write_execute ()

长/可靠写远程关贸总协定服务器执行。

ble_gattc_indication_cfm ()

发送确认收到指示。

ble_gattc_get_mtu ()

得到当前TX MTU同行。

ble_gattc_exchange_mtu ()

MTU交换。

请注意

几个缺口配置函数之前,必须被称为属性创建数据库,因为修改设备的配置可以明确创建的属性数据库。这是指出Doxygen头的配置功能可以有这种效果。

5.1.2.2。对话框BLE服务API

BLE服务API的头文件<代码class="docutils literal notranslate">< sdk_root_directory > / sdk /接口/祝福/服务/包括。在大多数项目API相关头文件是象征性的<代码class="docutils literal notranslate">< sdk_root_directory > / sdk /祝福/服务/包括

提供服务API,回调函数原型和定义都包含在每个服务的头文件。服务的实现如下:

表19 头文件的祝福服务

头文件

描述

bas.h

电池服务

bcs.h

身体成分服务

ble_service.h

服务处理程序API

bms.h

债券管理服务

cts.h

当前时间服务

dis.h

设备信息服务

dlg_debug.h

对话框调试服务

dlg_suota.h

对话框SUOTA服务

hids.h

人机界面设备服务

hrs.h

心率服务

ias.h

立即提醒服务

lls.h

链接损失服务

scps.h

扫描参数服务

sps.h

串行端口服务

svc_defines.h

常见的所有服务的定义

svc_types.h

常见的共同特征

tps.h

Tx电力服务

uds.h

用户数据服务

wss.h

重量范围服务

所有服务都定义一个初始化函数。这个函数被调用时参数变化对不同服务。

最常见的参数是一个指针指向一个或多个回调函数,应该呼吁一个特定于服务的事件。例如,原型的初始化函数立即提醒服务(ias.h)如下:

代码23 初始化代码立即提醒服务
ble_service_t*ias_init(ias_alert_level_cb_talert_level_cb)

函数<代码class="docutils literal notranslate">ias_init ()只有一个参数。是一个指针将被调用的回调函数,当一个对等设备修改立即警戒级别的价值特征。这个回调函数是用户应用程序代码的一部分,应提供所需的应用程序处理改变立即警戒级别。

所有初始化函数的返回值是创建服务的处理用于参考服务的应用程序。了解服务与祝福交互框架是有用的知道这个处理代表什么。句柄是一种指向一个通用的结构(<代码class="docutils literal notranslate">ble_service_t),它定义了服务应如何与框架。在每个服务有一个内部服务定义(<代码class="docutils literal notranslate">XXX_service_t)所示图25。这包含通用服务结构+一组处理,每个服务实现的关贸总协定的特点一个。这<代码class="docutils literal notranslate">XXX_service_t结构是由<代码class="docutils literal notranslate">XXX_init ()的服务。的<代码class="docutils literal notranslate">start_h和<代码class="docutils literal notranslate">end_h处理将包含开始和结束处理该服务的属性在整个关贸总协定表关贸总协定服务器提供的。所以,当关贸总协定客户机从服务器请求一个服务发现这些代表了开始和结束处理,客户端将使用访问服务<代码class="docutils literal notranslate">XXX

. . / _images / 058. png

图25服务处理的结构

一组可选的回调允许每个服务指定如果它想做一些具体处理某些事件受到祝福的框架。如果服务时要通知另一个祝福设备连接到这个设备就可以定义自己的<代码class="docutils literal notranslate">handle_connected_evt ()功能和它插入<代码class="docutils literal notranslate">connected_evt回调。每个服务宣布<代码class="docutils literal notranslate">handle_connected_evt ()函数为静态<代码class="docutils literal notranslate">xxx.c按照惯例,SmartSnippets™SDK都共享相同的函数名在每个服务。

为每个服务初始化,因此添加到祝福服务框架<代码class="docutils literal notranslate">ble_service_add ()、通用服务结构添加到结构支持的服务中所示图26

. . / _images / 059. png

图26结构支持的服务

现在主要的内部服务结构解释,更容易遵循服务初始化定义如何服务如何运作。

在祝福服务框架,主要的事件处理程序<代码class="docutils literal notranslate">ble_service_handle_event (),如下所示。

代码24 处理保佑事件使用保佑服务框架
boolble_service_handle_event(常量ble_evt_hdr_t*evt){开关(evt- >evt_code){情况下BLE_EVT_GAP_CONNECTED:connected_evt((常量ble_evt_gap_connected_t*)evt);返回;/ /使它“处理”,因此应用程序可以处理情况下BLE_EVT_GAP_DISCONNECTED:disconnected_evt((常量ble_evt_gap_disconnected_t*)evt);返回;/ /使它“处理”,因此应用程序可以处理情况下BLE_EVT_GATTS_READ_REQ:返回read_req((常量ble_evt_gatts_read_req_t*)evt);情况下BLE_EVT_GATTS_WRITE_REQ:返回write_req((常量ble_evt_gatts_write_req_t*)evt);情况下BLE_EVT_GATTS_PREPARE_WRITE_REQ:返回prepare_write_req((常量ble_evt_gatts_prepare_write_req_t*)evt);情况下BLE_EVT_GATTS_EVENT_SENT:返回event_sent((常量ble_evt_gatts_event_sent_t*)evt);}返回;}

这些sub-handlers里面<代码class="docutils literal notranslate">ble_service_handle_event ()搜索整个添加服务找到一个定义了这个事件的行为。有两种类型的事件的处理方式不同。

5.1.2.3。面向连接的事件

连接和断开事件可能感兴趣的所有注册服务,所以可以通知所有服务。清理关闭以同样的方式处理。

例如连接事件将调用BLE服务的静态定义的<代码class="docutils literal notranslate">connected_evt ()函数(<代码class="docutils literal notranslate">sdk /接口/祝福/服务/ src / ble_service.c)。这将通过注册的所有服务BLE服务框架来检查服务,注册在服务初始化连接事件。对于每一次这样的服务<代码class="docutils literal notranslate">connected_evt就会调用回调。

5.1.2.4。面向属性的事件

这些事件处理与一个给定的属性。每个属性与一个独特的服务每一个处理程序的第一步是确定哪些服务属性属于。例如写请求在一个特定的属性将调用BLE服务的静态定义的<代码class="docutils literal notranslate">write_req ()函数(<代码class="docutils literal notranslate">sdk /接口/祝福/服务/ src / ble_service.c)如下所示。这将首先确定哪些服务属性的拥有<代码class="docutils literal notranslate">find_service_by_handle ()。如果它有一个write_req定义回调执行回调。

代码25 写请求的示例代码
静态boolwrite_req(常量ble_evt_gatts_write_req_t*evt){ble_service_t*svc=find_service_by_handle(evt- >处理);如果(!svc){返回;}如果(svc- >write_req){svc- >write_req(svc,evt);}返回真正的;}

这个流的一个例子是写没有响应过程,可以应用于立即警戒级别的特征直接提醒服务。关贸总协定客户机请求写入时,它将触发特征<代码class="docutils literal notranslate">write_req ()sub-handler下<代码class="docutils literal notranslate">ble_service_handle_event ()

的<代码class="docutils literal notranslate">write_req ()sub-handler将使用<代码class="docutils literal notranslate">find_service_by_handle ()是否添加服务注册的特点。它将匹配与立即提醒服务(IAS)和随着IAS注册IAS写请求处理程序<代码class="docutils literal notranslate">handle_write_req ()将被称为(<代码class="docutils literal notranslate">sdk /接口/祝福/服务/ src / ias.c)。

代码26 例子的代码处理写入请求并匹配相应的实例
静态无效handle_write_req(ble_service_t*svc,常量ble_evt_gatts_write_req_t*evt){ia_service_t*ias=(ia_service_t*)svc;att_error_t犯错=ATT_ERROR_OK;如果(evt- >长度= =1){uint8_t水平;/ **这是只写的特点所以我们不需要存储值*任何地方,可以在这里处理并答复。* /水平=get_u8(evt- >价值);如果(水平>2){犯错=ATT_ERROR_APPLICATION_ERROR;}其他的如果(ias- >cb){ias- >cb(evt- >conn_idx,水平);}}ble_gatts_write_cfm(evt- >conn_idx,evt- >处理,犯错);}

通过调用<代码class="docutils literal notranslate">ias - > cb ()函数,实际上这个处理程序调用应用程序时提供的回调函数作为一个参数传递<代码class="docutils literal notranslate">ias_init ()被称为应用程序。最后,它发送一个确认写入更新值的属性数据库维护BLE堆栈。

这只是一个例子的方式祝福服务框架将保佑事件保佑服务事件。不同的事件在不同的服务可以有不同程度的复杂性,但是大多数时候这种复杂性是包含在bie服务API。目的是应用程序只需要调用服务的初始化函数和定义适当的回调函数来处理所有服务的事件。

此外,一些服务定义额外的特定于服务的API调用。例如,心率服务实现定义了一个API来触发通知心率的测量特点,使用功能<代码class="docutils literal notranslate">hrs_notify_measurement ()和<代码class="docutils literal notranslate">hrs_notify_measurement_all ()(首先是用来通知特性指定对等,而第二个是用来通知所有订阅同行)的特点。还有些服务定义一些内部辅助函数用于操纵特征值,和一些服务需要属性初始值作为参数的初始化函数。

的保佑服务API添加另一层一般保佑API。一起祝福适配器,保佑,保佑API库和保佑服务框架导致保佑框架。

BLE服务API提供了一个现成的解决方案来实现应用程序使用许多常见的采用BLE服务。底层BLE API和关贸总协定服务器API可用于创建其他采用服务或者甚至使用BLE服务作为模板定制服务。

以下部分将概述一个通用的应用程序,然后将详细描述的几个例子BLE项目包含在SmartSnippets™DA1469x SDK:

表20 BLE项目包含在SmartSnippets™DA1469x SDK

BLE项目

一般的描述

ble_adv

最简单的祝福项目中可用SmartSnippets™DA1469x SDK,它不使用BLE服务框架,只暴露和关贸总协定服务的差距。

ble_peripheral

一个项目,可以用作开发BLE外围应用程序的模板。亚博国际官网平台网址服务的项目包括一些祝福服务框架下实现的。

ble_suota_client

这个应用程序是一个SUOTA 1.2客户端实现,允许更新SUOTA-enabled设备空气,使用一个简单的串行控制台界面。

5.1.2.5。配置项目

在每个项目BLE框架通过一组定制和BSP配置配置文件设置和宏定义用于该项目。这些文件中发现的<代码class="docutils literal notranslate">配置每个项目的目录。

对于ble_adv项目的这些文件<代码class="docutils literal notranslate">配置/ custom_config_qspi.h和<代码class="docutils literal notranslate">配置/ custom_config_ram.h(分别QSPI和RAM构建配置)。

任何定义在这些文件会覆盖默认的SDK值被发现在以下文件:

sdk / bsp / config / bsp_defaults.h

sdk /接口/幸福/ config / ble_config.h

sdk / free_rtos / include / FreeRTOSconfig.h

5.1.2.6。BLE应用程序结构

所有的祝福应用项目SmartSnippets™DA1469x SDK也有类似的结构。这涉及到几个FreeRTOS任务在不同的优先级,以确保整个系统的实时要求。

BLE应用程序中实现FreeRTOS任务创建的<代码class="docutils literal notranslate">system_init ()函数。<代码class="docutils literal notranslate">system_init ()在启动和运行在最高优先级还负责启动保佑经理和保佑适配器的任务。

应用程序任务有以下流程:

  1. 设备初始化和配置:启动BLE,设定装置的作用、设备名称、外观和其他设备参数。

  2. 属性创建数据库(关贸总协定服务器设备):创建服务和属性使用BLE服务框架。这个必须完成后(1)防止删除属性数据库。

  3. 空气操作配置和初始化:保佑外围设备通常广告目的和保佑中央设备扫描和/或目的试图连接到另一个设备。

  4. 无限的<代码class="docutils literal notranslate">(,)循环,这是应用程序的事件处理循环。应用程序被设置为所需的,现在是等待祝福事件响应,如连接或写请求。

    • BLE适配器(<代码class="docutils literal notranslate">ad_ble_task)必须有一个更高的优先级比应用程序任务(s),因为它祝福主机运行关键任务堆栈调度器和它处理时间。

    • 大部分的祝福阻止应用程序使用Fr亚博国际官网平台网址eeRTOS任务通知机制。<代码class="docutils literal notranslate">ble_adv_demo是最简单的应用程序,是唯一的项目,不使用这种机制。相反,它只是块BLE经理的事件队列。

    • 除了BLE-related大多数项目也使用其他系统模块功能,如软件定时器或传感器。在这种情况下,应用程序通常定义了回调函数触发这些系统事件或中断。这些回调函数应该使用任务通知开启应用程序可以处理应用程序中的事件或中断任务的上下文(在它<代码class="docutils literal notranslate">(,)循环)。

警告

调用一个祝福的API函数在一个回调函数触发计时器到期将执行BLE API函数在计时器的任务上下文。回调函数中调用其他函数也可以对实时性能的影响或损坏小栈使用计时器任务。

5.1.3。BLE安全

蓝牙规范定义了设备验证和链路加密的安全选项。处理这些方面的安全无缝的BLE框架。API在表21能够设置安全,启动配对,做一个安全请求或设置加密使用以前交换密钥。最细节的处理程序由BLE内部框架和应用程序将只通知如果需要干预或过程完成时。这些选项将详细描述部分5.1.3。25.1.3。5

安全密钥的生成和存储和其他键信息也由BLE框架。持久性存储还可以用于启用存储的安全性键和键flash中的数据信息。BLE框架可以检索信息权力周期之后,用它来恢复与先前保税设备连接。这是描述的5.1.4

5.1.3.1。乐安全

LE安全连接配对和默认启用的SDK支持使用部分中描述的API5.1.3。2勒将使用安全连接配对,如果连接同伴支持应用程序的功能不需要特别请求它。如果组合设备的功能导致数值比较配对算法(引入和使用安全连接配对),数字比较请求的应用程序将被通知在配对的接待<代码class="docutils literal notranslate">BLE_EVT_GAP_NUMERIC_REQUEST事件,应当使用<代码class="docutils literal notranslate">ble_gap_numeric_reply ()函数。

如果应用程序只需要使用LE遗留配对和禁用安全连接支持SDK,它应该定义<代码class="docutils literal notranslate">dg_configBLE_SECURE_CONNECTIONS宏0在应用程序配置文件。

5.1.3.2。功能

表21总结了应用程序所使用的API函数,可以设置安全特性。

表21 BLE安全API函数

API调用

描述

ble_gap_pair ()

发起一个配对连接对等或焊接过程。取决于连接设备是主人或奴隶,这个调用将会分别在配对或安全要求。

ble_gap_pair_reply ()

回复收到了<代码class="docutils literal notranslate">BLE_EVT_GAP_PAIR_REQ事件。这个事件只会收到一个外围设备当中央同行已经发起了一个配对的过程,所以这个函数应该只被称为外围应用程序后,只有一个<代码class="docutils literal notranslate">BLE_EVT_GAP_PAIR_REQ事件已经收到。

ble_gap_passkey_reply ()

回复收到了<代码class="docutils literal notranslate">BLE_EVT_GAP_PASSKEY_REQUEST事件。这个事件将会收到如果设备的输入/输出功能的结合导致了万能钥匙进入配对算法。应用程序应该使用这个函数提交的总钥匙进行配对过程。

ble_gap_numeric_reply ()

回复收到了<代码class="docutils literal notranslate">BLE_EVT_GAP_NUMERIC_REQUEST事件。这个事件将会收到如果设备的输入/输出功能的结合导致数值比较配对算法。应用程序应该使用这个函数接受或拒绝的数字键进行配对过程。这应该是只如果启用了LE安全连接使用。

ble_gap_set_sec_level ()

设置一个连接的安全级别。如果设备已经保税,现有的长期关键(LTK)将被用于设置加密。如果设备不是保税,配对或安全请求将被触发(取决于设备的主人或奴隶在连接)与债券标志设置为false。

ble_gap_get_sec_level ()

得到当前建立在一个连接的安全级别。

ble_gap_unpair ()

Unpair之前或保税设备配对。这也将删除键和键数据信息安全目前存在于BLE存储。

5.1.3.3。事件

表22描述了BLE事件与安全相关应用程序可能收到的和适当的API函数来回应他们。

表22 BLE安全API事件

事件

论点

描述

BLE_EVT_GAP_PAIR_REQ

ble_evt_gap_pair_req_t

配对请求接收到连接对等。成员<代码class="docutils literal notranslate"><债券>表明如果同行要求债券(即长期安全密钥的交换)。应用程序应该使用<代码class="docutils literal notranslate">ble_gap_pair_reply ()这个请求做出回应。

BLE_EVT_GAP_PAIR_COMPLETED

ble_evt_gap_pair_completed_t

之前要求配对过程已经完成。成员<代码class="docutils literal notranslate"><状态>表示这个过程的完成状态,而成员<代码class="docutils literal notranslate"><债券>和<代码class="docutils literal notranslate">< MITM >表明如果债券与同行建立了MITM(中间人)保护上启用了连接链接。

BLE_EVT_GAP_SECURITY_REQUEST

ble_evt_gap_security_request_t

安全收到的请求连接周边同行。成员<代码class="docutils literal notranslate"><债券>和<代码class="docutils literal notranslate">< MITM >表明如果一个债券和MITM保护要求的同行。应用程序可以使用<代码class="docutils literal notranslate">ble_gap_pair ()与同行进行配对。

BLE_EVT_GAP_PASSKEY_NOTIFY

ble_evt_gap_passkey_notify_t

生成一个万能钥匙在配对过程。这个事件将会收到如果应用程序显示功能。成员<代码class="docutils literal notranslate">《万能钥匙》包含万能钥匙,应该显示输入的用户和同行的配对过程继续。

BLE_EVT_GAP_PASSKEY_REQUEST

ble_evt_gap_passkey_request_t

万能钥匙被要求在一个配对过程。这个事件将会收到如果应用程序的键盘功能。应用程序应该使用<代码class="docutils literal notranslate">ble_gap_passkey_reply ()响应这个请求使用用户输入的万能钥匙。

BLE_EVT_GAP_NUMERIC_REQUEST

ble_evt_gap_numeric_request_t

数字比较期间要求配对过程。这个事件将会收到如果应用程序键盘或者是/否和显示功能。应用程序应该使用<代码class="docutils literal notranslate">ble_gap_numeric_reply ()响应这个请求使用输入用户输入的接受或拒绝。

BLE_EVT_GAP_SEC_LEVEL_CHANGED

ble_evt_gap_sec_level_changed_t

建立的安全级别改变了链接。成员<代码class="docutils literal notranslate"><上>包含的安全级别。这将是后收到配对或加密过程已经成功完成。

BLE_EVT_GAP_SET_SEC_LEVEL_FAILED

ble_evt_gap_set_sec_level_failed_t

设置安全级别上建立链接使用<代码class="docutils literal notranslate">ble_gap_set_sec_level ()已经失败了。成员<代码class="docutils literal notranslate"><状态>指出失败的原因。这将是收到一个启动加密过程后成功。这可能表明,应再次请求配对连接对等(例如,对方可能已经失去了以前交换安全密钥)。

5.1.3.4。宏

表23包含宏BLE安全相关的配置。

表23 BLE安全API宏

默认的

描述

dg_configBLE_SECURE_CONNECTIONS

1

设置为1使用LE安全连接配对如果同伴支持特性或0总是使用LE遗留配对。

dg_configBLE_PAIR_INIT_KEY_DIST

GAP_KDIST_ENCKEY | GAP_KDIST_IDKEY | GAP_KDIST_SIGNKEY

设置安全密钥请求分发的配对发起者在配对功能交换过程。

dg_configBLE_PAIR_RESP_KEY_DIST

GAP_KDIST_ENCKEY | GAP_KDIST_IDKEY | GAP_KDIST_SIGNKEY

设置安全密钥请求分发的配对响应者在配对功能交换过程。

5.1.3.5。消息序列图(msc)

5.1.3.5.1。中央
. . / _images / 047. png

图27中央配对只是工作

. . / _images / 048. png

图28中央结合只是工作

. . / _images / 049. png

图29中央结合万能钥匙条目(中央显示)

. . / _images / 050. png

图30中央结合万能钥匙条目(外围显示)

. . / _images / 051. png

图31中央结合数值比较(仅安全连接)

5.1.3.5.2。外围
. . / _images / 052. png

图32外围配对只是工作

. . / _images / 053. png

图33外围键只是工作

. . / _images / 054. png

图34外围键密钥条目(外围显示)

. . / _images / 055. png

图35外围键密钥条目(中央显示)

. . / _images / 056. png

图36外围键数字比较(仅安全连接)

5.1.4。BLE存储

BLE存储相关信息的模块,实现了存储功能连接和保税同行,像安全密钥,CCC描述符的配置和应用程序定义的值。BLE存储可以保持连接的列表和保税设备在RAM和持久性存储(例如,在flash)。默认情况下,设备管理在RAM中只和持久性存储必须显式地启用应用程序的配置通过定义宏<代码class="docutils literal notranslate">CONFIG_BLE_STORAGE。然后使用非易失性存储器存储设备数据(NVMS)通用分区(见部分4所示。2详情)。

两种数据存储:

  • 设备配对数据(交换密钥和相关信息)。

  • 应用程序定义的数据使用BLE存储器管理API(只设置了“持久”标志的值存储在flash,例如CCC描述符值)。

持久性存储可以启用应用程序通过添加以下条目在应用程序的自定义配置文件:

代码27 让祝福持久存储
/ /启用BLE持久存储#定义CONFIG_BLE_STORAGE/ /使Flash和NVMS适配器类型(BLE持久性存储要求的)#定义dg_configFLASH_ADAPTER 1#定义dg_configNVMS_ADAPTER 1#定义dg_configNVMS_VES 1

保税设备的最大数量可以设置使用<代码class="docutils literal notranslate">defaultBLE_MAX_BONDED宏(默认定义为8)。如果应用程序试图债券比允许更多的设备,将返回一个错误。这个错误应该由应用程序来处理。它可以unpair当前保税设备(使用之一<代码class="docutils literal notranslate">ble_gap_unpair ()没有结合API函数)或执行配对。

技术细节的BLE存储实现可以在下面找到readme文件:

< sdk_root_directory > / sdk /祝福/ readme.md /接口

5.1.6。LE数据包长度的扩展

蓝牙核心版本4.0和4.1的最大数据包数据单元(PDU)大小27个八位字节。蓝牙核心版本4.2引入了一个重要的增强,即数据包长度的扩展,它允许的PDU大小27和251个八位字节之间。这意味着,例如,L2CAP层可以填满247个八位字节更高一层的数据包在每个L2CAP PDU 21个八位位组相比,与先前的蓝牙核心版本。这显著增加(10倍以上)数量的每个包的八位字节的用户发送的数据允许设备传输数据比之前的版本快2.5倍。这将是伟大的好处可能需要传输大量数据的应用程序,如无线(OTA)固亚博国际官网平台网址件更新或下载大量数据从传感器日志。

为默认的PDU大小扩展建立连接,数据长度必须执行更新过程。根据该控制过程<代码class="docutils literal notranslate">LL_LENGTH_REQ和<代码class="docutils literal notranslate">LL_LENGTH_RSPpdu必须交换的连接设备,以便每个通知的对等设备的能力。每个设备使用这些PDU报告其最大接收数据通道和最大传输数据通道PDU载荷长度和PDU。这个更新过程后,PDU大小为每个连接的数据路径的方向由交换两个控制器的最小值。

DA1469x支持数据长度的扩展功能,所以接收和传输数据的值是默认设置为最大允许长度,也就是251个八位字节。DA1469x控制器配置为一个祝福的中央设备何时启动数据长度更新在一个新的连接对等设备的控制器是否支持这一功能。BLE管理器将使用定义的值<代码class="docutils literal notranslate">dg_configBLE_DATA_LENGTH_RX_MAX和<代码class="docutils literal notranslate">dg_configBLE_DATA_LENGTH_TX_MAX宏的初始数据长度更新谈判。

5.1.6.1。功能

表27 LE数据长度函数——ble_gap.h

函数

描述

ble_gap_data_length_set ()

设置最大传输数据长度和时间为一个现有的连接或未来的首选传输数据长度连接(即传输数据长度用于未来的数据长度更新谈判)。连接数据长度的变化将是暗示使用<代码class="docutils literal notranslate">BLE_EVT_GAP_DATA_LENGTH_CHANGED事件。

5.1.6.2。宏

表28 LE数据长度定义

默认的

描述

dg_configBLE_DATA_LENGTH_RX_MAX

251年

设置最大接收数据通道PDU载荷长度。除非<代码class="docutils literal notranslate">ble_gap_data_length_set ()使用应用程序,这将定义接收数据的长度在LE数据长度更新谈判做的设备。

dg_configBLE_DATA_LENGTH_TX_MAX

251年

设置最大传输数据通道PDU载荷长度。除非<代码class="docutils literal notranslate">ble_gap_data_length_set ()使用应用程序,这将定义传输数据的长度在LE数据长度更新谈判做的设备。

5.1.6.3。事件

表29 LE数据长度事件——获取使用ble_get_event ()——ble_gap.h

事件

论点

描述

BLE_EVT_GAP_DATA_LENGTH_CHANGED

ble_evt_gap_data_length_changed_t

数据长度改变为指定的连接。成员<代码class="docutils literal notranslate">< rx_length >,<代码class="docutils literal notranslate">< rx_time >,<代码class="docutils literal notranslate">< tx_length >和<代码class="docutils literal notranslate">< tx_time >指定的值获得勒数据长度更新后谈判(每个方向的数据长度通常设置的最小值连接设备)报告的。

BLE_EVT_GAP_DATA_LENGTH_SET_FAILED

ble_evt_gap_data_length_set_failed_t

数据长度设置操作失败。成员<代码class="docutils literal notranslate"><状态>表示一组操作失败的原因。

5.1.7。2 m体育

蓝牙4.2核心版本只支持1的强制性的比特率每秒(Mb / s),也被称为勒1 m体育。蓝牙核心版本5.0,它是实现对话框DA1469x产品家族,还支持可选的比特率的2 Mb / s,也被称为勒2 m体育。该功能实现的LE控制器和使用中所描述的API可以对它进行配置5.1.7.15.1.7.2,尽管额外的配置不是强制性的;LE控制器将处理PHY更新程序无缝并会通知应用程序的任何变化在PHY配置无论哪一方发起PHY更新过程。

5.1.7.1。功能

表30 勒- ble_gap.h 2 m函数

函数

描述

ble_gap_phy_get ()

发射机和接收机PHY偏好设置为未来所有现有的连接或连接。PHY配置的变化对于一个给定的连接将信号使用<代码class="docutils literal notranslate">BLE_EVT_GAP_PHY_CHANGED事件。

ble_gap_phy_set ()

设置发射机和接收机PHY偏好为未来所有现有的连接或连接。完成体育组操作将信号使用<代码class="docutils literal notranslate">BLE_EVT_GAP_PHY_SET_COMPLETED事件和可能的变化PHY配置对于一个给定的连接将使用信号<代码class="docutils literal notranslate">BLE_EVT_GAP_PHY_CHANGED事件。

5.1.7.2。事件

表31 勒2 m事件——获取使用ble_get_event ()——ble_gap.h

事件

论点

描述

BLE_EVT_GAP_PHY_CHANGED

ble_evt_gap_phy_changed_t

PHY配置更改为指定的连接。成员<代码class="docutils literal notranslate">< tx_phy >和<代码class="docutils literal notranslate">< rx_phy >指定当前配置的发射机和接收PHY分别。这个事件之后才收到改变一个或两个发射机和接收机PHY配置。

BLE_EVT_GAP_PHY_SET_COMPLETED

ble_evt_gap_phy_set_completed_t

体育组操作已完成。这将是收到后ble_gap_phy_set()调用。成员<代码class="docutils literal notranslate"><状态>表示一组操作的状态。

5.1.8。NVPARAM字段

表32显示了非易失性内存参数中可以找到<代码class="docutils literal notranslate">< sdk_root_directory > / sdk /中间件/适配器/ include / platform_nvparam.h

表32 NVPARAM字段

标签

抵消

长度

NVPARAM_BLE_PLATFORM_BD_ADDRESS

0 x01

6字节数组

NVPARAM_BLE_PLATFORM_LPCLK_DRIFT

0 x07

16位值

NVPARAM_BLE_PLATFORM_EXT_WAKEUP_TIME

0 x0d

16位值

NVPARAM_BLE_PLATFORM_OSC_WAKEUP_TIME

0 x0e

16位值

NVPARAM_BLE_PLATFORM_RM_WAKEUP_TIME

0 x0f

16位值

NVPARAM_BLE_PLATFORM_SLEEP_ENABLE

0 x11

1个字节

NVPARAM_BLE_PLATFORM_EXT_WAKEUP_ENABLE

0 x12

1个字节

NVPARAM_BLE_PLATFORM_BLE_CA_TIMER_DUR

0 x40

16位值

NVPARAM_BLE_PLATFORM_BLE_CRA_TIMER_DUR

0 x41

1个字节

NVPARAM_BLE_PLATFORM_BLE_CA_MIN_RSSI

1个字节

NVPARAM_BLE_PLATFORM_BLE_CA_NB_PKT

0 x43

16位值

NVPARAM_BLE_PLATFORM_BLE_CA_NB_BAD_PKT

0 x44

16位值

NVPARAM_BLE_PLATFORM_IRK

0 x80

16字节数组

5.1.9。祝福任务优先考虑

BLE软件SDK包含三个模块:

  1. BLE经理祝福:提供的接口芯片的功能。应用程序任务使用保佑API接口与保佑经理。之间的祝福manager是一个任务,应用程序和BLE适配器。它使用保佑适配器接口与保佑堆栈。

  2. BLE适配器任务:系统提供接口BLE堆栈。它运行BLE栈内部调度程序,接收的命令或回复来自BLE的事件管理器,并通过保佑堆栈事件保佑经理。保佑核心功能实现的保佑适配器的任务。

  3. BLE堆栈:实现链路层的软件堆栈和BLE主机栈,特别是逻辑链路控制和适应协议(L2CAP),安全管理协议(SMP)、属性(ATT)协议,通用属性剖面(关贸总协定)和通用访问配置文件(GAP)。

请注意

保佑栈软件是运行在保佑适配器的任务上下文实例化和初始化堆栈。

默认两BLE系统任务优先级高于SDK应用程序的任务。

请注意

应用程序开发人员应该确保保佑适配器和保佑经理任务总是有一个优先级高于应用程序任务。

保佑适配器运行保佑堆栈调度器,分派BLE堆栈的不同层之间的所有消息并调用适当的处理程序。例如,当应用程序使用API<代码class="docutils literal notranslate">ble_gatts_send_event ()发送关贸总协定通知,这将导致之间的消息传播祝福经理,保佑适配器和几个保佑堆栈的内部层,直到达到传输缓冲区,最终,空气。

5.1.10。祝福任务时间要求

在DA1469x LE控制器运行独立于应用程序。然而,祝福系统任务(保佑适配器,保佑经理)仍然需要定期运行,确保BLE数据及时传输和处理。当应用程序不做任何祝福API调用,没有数据交换与同行,祝福适配器通常会阻塞,直到它需要检索信息或者发送一个命令BLE主机。

在某些场景中祝福管理器和BLE适配器将与信息交流而不通知应用程序。例如,在与同行使用私有地址,祝福管理器将使用已知的设备让试图解决它。在这种情况下,保佑经理和保佑适配器将有更多的运行时段。

还有其他情况下当BLE框架需要回复从应用程序时,例如,一对请求收到对等或写请求。再一次,在这些情况下,保佑适配器和保佑经理将不得不多次运行之间的一段两个连接事件。

5.1.11。属性操作

作为属性协议严格当一个属性请求如收到一个读或写请求,有幸获得堆栈的关贸总协定层将切换到一个繁忙状态只要请求未完成/处理。对于写请求或读请求的一个属性值所提供的应用程序,那么应用程序必须确认这些操作使用<代码class="docutils literal notranslate">ble_gatts_read_cfm ()或<代码class="docutils literal notranslate">ble_gatts_write_cfm ()(分别在收到<代码class="docutils literal notranslate">BLE_EVT_GATTS_READ_REQ或<代码class="docutils literal notranslate">BLE_EVT_GATTS_WRITE_REQ)。在这种情况下,其他关贸总协定操作,如通知发送,将排队,直到此请求确认。

5.1.12。BLE应用实例

5.1.12.1。广告的应用

最简单的祝福项目SmartSnippets™DA1469x SDK<代码class="docutils literal notranslate">ble_adv演示是在文件夹中找到<代码class="docutils literal notranslate">< sdk_root_directory > /项目/ dk_apps /演示/ ble_adv。应用程序启动外围设备,设置设备名称和广告数据和广告开始。代码28是一个从c

代码28 设置BLE设备
/ /开始祝福模块作为外围设备ble_peripheral_start();/ /设置设备名称ble_gap_device_name_set(”对话框中副词演示”,ATT_PERM_READ);/ /设置广告数据ble_gap_adv_data_set(运算符(adv_data),adv_data,0,);/ /开始广告ble_gap_adv_start(GAP_CONN_MODE_UNDIRECTED);

没有祝福服务添加,只是差距,关贸总协定服务公开。无限循环,实现了一生行为的应用程序使用<代码class="docutils literal notranslate">ble_get_event(真正的)阻止无限期BLE经理的事件队列。一旦事件发布,使用一个任务的疏导和处理它<代码class="docutils literal notranslate">开关的情况。代码29位于c

代码29 事件处理的例子
(,){ble_evt_hdr_t*hdr;每个循环* / / *通知监督sys_watchdog_notify(wdog_id);/ *暂停监督而阻塞ble_get_event () * /sys_watchdog_suspend(wdog_id);/ **等待幸运的事件——这任务块*无限期直到收到东西。* /hdr=ble_get_event(真正的);/ *简历监督* /sys_watchdog_notify_and_resume(wdog_id);如果(!hdr){继续;}开关(hdr- >evt_code){情况下BLE_EVT_GAP_CONNECTED:handle_evt_gap_connected((ble_evt_gap_connected_t*)hdr);打破;情况下BLE_EVT_GAP_DISCONNECTED:handle_evt_gap_disconnected((ble_evt_gap_disconnected_t*)hdr);打破;情况下BLE_EVT_GAP_PAIR_REQ:{ble_evt_gap_pair_req_t*evt=(ble_evt_gap_pair_req_t*)hdr;ble_gap_pair_reply(evt- >conn_idx,真正的,evt- >债券);打破;}默认的:ble_handle_event_default(hdr);打破;}/ /自由事件缓冲区OS_FREE(hdr);}

祝福不使用服务框架以来,唯一的事件由应用程序来处理这三个事件的处理<代码class="docutils literal notranslate">开关案例:连接,断开和一对请求。这是有意义的对于这个应用程序作为其惟一的目的是启动一个接入广告,重新启动它的一双断开和应对来自设备的请求需要配对/焊接连接。

运行这个项目将导致广告BLE外围设备暴露的差距和关贸总协定服务。差距服务属性可以使用任何标准阅读BLE中央设备。

的<代码class="docutils literal notranslate">ble_peripheral项目是一个好的起点开发BLE外围应用程序。亚博国际官网平台网址它是在文件夹中找到<代码class="docutils literal notranslate">< sdk_root_directory > /项目/ dk_apps /功能/ ble_peripheral。与其他示例项目,它没有实现一个特定的配置文件,而是通过关贸总协定公开几个祝福服务服务器。

应用程序的初始化是类似于其他项目,实现BLE外围应用程序。亚博国际官网平台网址它使用保佑服务框架实例化多个保佑服务:

  • 电池服务(多个实例)

  • 当前时间服务

  • 设备信息服务

  • 扫描参数服务

  • 对话框调试服务

  • 自定义用户服务

除了蓝牙SIG-adopted服务,<代码class="docutils literal notranslate">ble_peripheral项目实例化两个更多的服务,对话框调试服务和一个定制的用户服务。

调试服务的对话框可用于与服务交互的应用程序公开使用控制点特点写命令和接收通知。详细描述的方法与调试服务中所示的对话框readme.md文件在项目文件夹中。

自定义用户服务没有定义任何特定的功能除了服务使用128位的uuid,特性和描述符。这个定制服务,被称为<代码class="docutils literal notranslate">myservice在项目的源代码,是实现一个自定义服务的一个例子使用BLE API调用来创建其属性数据库。没有具体的功能是定义这些属性之一是读或写。如何创建和使用自定义服务的更多细节将在部分5.1.15

属性创建数据库后,设备将广告目的,它将等待连接事件。

的<代码class="docutils literal notranslate">ble_peripheral项目使用BLE服务框架来处理服务事件,应用程序还定义了处理程序连接,广告完成和一对请求事件。的<代码class="docutils literal notranslate">ble_peripheral站在项目的完整性之间的某个地方<代码class="docutils literal notranslate">ble_adv演示应用程序,实现一个完整的祝福像<代码class="docutils literal notranslate">pxp_reporter

项目将公开的服务可以使用配置文件<代码class="docutils literal notranslate">配置/ ble_peripheral_config.h

5.1.13。BLE概要文件项目

除了前面部分所描述的项目,有几个应用程序项目实现BLE概要文件。这些项目是更为复杂和BLE应用程序的提供一个完整的实现。亚博国际官网平台网址因此他们提供一个好的参考如何把祝福的功能与几个操作系统机制,GPIO处理和接口与外部传感器。

实现配置文件位于下<代码class="docutils literal notranslate">< sdk_root_directory > /项目/ dk_apps / ble_profiles和下面列出:

  • 苹果媒体服务(<代码class="docutils literal notranslate">自动对盘及成交系统)——客户角色

  • 藏在关贸总协定概要(<代码class="docutils literal notranslate">HOGP)- - -设备作用(<代码class="docutils literal notranslate">hogp_device)

  • 藏在关贸总协定概要(<代码class="docutils literal notranslate">HOGP)——主机角色(<代码class="docutils literal notranslate">hogp_host)

  • 心率概要传感器的作用(<代码class="docutils literal notranslate">hrp_sensor)

  • 心率概要收集器的作用(<代码class="docutils literal notranslate">hrp_collector)

  • 距离剖面——记者角色(<代码class="docutils literal notranslate">pxp_reporter)坐落在<代码class="docutils literal notranslate">< sdk_root_directory > /项目/ dk_apps /演示

  • 体重秤概要体重秤的作用(<代码class="docutils literal notranslate">wsp_weightscale)

  • 苹果通知中心服务(<代码class="docutils literal notranslate">小区)-通知使用者(<代码class="docutils literal notranslate">数控)的作用(<代码class="docutils literal notranslate">小区)

  • 血压概要(<代码class="docutils literal notranslate">BLP)-血压传感器的作用(<代码class="docutils literal notranslate">blp_sensor)

  • 债券管理服务(<代码class="docutils literal notranslate">百时美施贵宝)

  • 骑自行车的速度和节奏收集器(<代码class="docutils literal notranslate">CSCP)

  • 健康温度计概要温度计的作用(<代码class="docutils literal notranslate">htp_thermometer)

5.1.14。使用采用BLE服务

表33总结了API的头文件BLE服务实现的SmartSnippets™DA1469x SDK。这些文件可以在找到<代码class="docutils literal notranslate">< sdk_root_directory > / sdk /接口/祝福/服务/包括。开发人员可以使用这些api将这些服务添加到另一个项目。

表33 BLE服务API的头文件

文件名称

描述

ble_service.h

BLE服务框架API:

  • 添加服务框架

  • 处理事件使用BLE服务框架

  • 提升权限

  • 得到服务的属性

  • 添加包含服务

bas.h

电池服务——BAS

bcs.h

身体成分服务- bc

bms.h

债券管理服务——BMS

cts.h

当前时间服务- CTS

dis.h

设备信息服务——说

dlg_debug.h

对话框调试服务

dlg_suota.h

对话框SUOTA服务

hids.h

人机界面设备服务——藏

hrs.h

服务——小时心率

ias.h

服务——IAS立即警觉

lls.h

链接服务——接拍的损失

scps.h

服务——scp扫描参数

sps.h

串行端口服务- SPS

tps.h

Tx - TPS电力服务

uds.h

用户数据服务——UDS

wss.h

体重服务——WSS

5.1.15。添加一个自定义服务

下面的代码段概述创建一个新的定制服务所需的初始化<代码class="docutils literal notranslate">XXX。它需要的文件<代码class="docutils literal notranslate">xxx.c和<代码class="docutils literal notranslate">xxx.h要创建。这些基础是一个很好的例子<代码class="docutils literal notranslate">dlg_mls服务多连杆演示。这提供了一个只编写特色服务。

每个服务需要一个包含通用结构<代码class="docutils literal notranslate">ble_service_t结构和任何回调函数和特征处理所需的服务。在下面的例子中为服务<代码class="docutils literal notranslate">XXX有一个回调函数和一个定义的特征。

代码30 结构定义为XXX的服务
类型定义结构体{ble_service_tsvc;/ /核心BLE服务结构xxx_cb_tcb;/ /回调应用提供的xxx/ /服务处理一个事件uint16_txxx_char1_val_h;/ /声明为每个特征处理/ /可以读或写}xxx_service_t;

初始化函数的要求<代码class="docutils literal notranslate">xxx_init ()如下例所示。关键信息的评论解释每一行在做什么。

代码31 为XXX服务初始化函数
xxx_service_t*xxx_init(callback1){/ /分配和初始化xxx_service_t结构/ /定义任何回调函数所需的服务,只有在这种情况下写xxx- >svcwrite_req=< 服务请求处理程序>/ /创建主服务UUID 16或128位的值uuid=ble_uuid_from_string()uuid=ble_uuid_create16()/ /添加主服务X属性num_attrs=Xble_gatts_add_service(&uuid,GATT_SERVICE_PRIMARY,num_attrs)/ /创建特征1在关贸总协定为这个服务,并为其分配处理表ble_gatts_add_characteristic(&uuid,关贸总协定财产,丙氨酸权限,大小,0,,&xxx- >xxx_char1_h)/ /设置start_h和传入null终止可变长度列中的所有特征处理服务ble_gatts_register_service(&xxx- >svcstart_h,&xxx- >xxx_char1_h,0);/ /计算服务端处理基于服务的属性xxx- >svcend_h=xxx- >svcstart_h+num_attrs;/ /传入回调函数添加到服务结构xxx- >xxx_cb1=callback1;/ /添加新创建的服务ble框架ble_service_add(&xxx- >svc);/ /并返回处理服务的应用程序返回&xxx- >svc}

5.1.16。扩展BLE功能

保佑API可以用来开发保佑的对话框应用程序。亚博国际官网平台网址API的头文件都位于文件夹<代码class="docutils literal notranslate">< sdk_root_directory > / sdk /接口/祝福/ api /包括。他们记录(Ref_04)并进行了总结表34

表34 头文件对话框BLE API

文件名称

描述

ble_att.h

属性协议API:主要定义。

ble_attribdb.h

助手来管理复杂的属性数据库。

ble_bufops.h

助手将得到祝福缓冲区的数据。

ble_common.h

通用的API:功能用于操作不是特定于特定BLE主机软件组件

ble_gap.h

差距API:

  • 设备参数配置:设备的作用、MTU大小、设备名称暴露在服务属性的差距,等等。

  • 空气操作:广告、扫描、连接,连接请求作出反应,启动或响应连接参数更新,等等。

  • 安全操作:启动和响应配对或焊接过程,设置安全级别,unpair等等。

ble_gatt.h

关贸总协定的共同定义的API

ble_gattc.h

关贸总协定客户机API:

  • 发现服务、特征等的对等设备

  • 读或写一个对等设备的属性

  • 启动MTU交流

  • 确认接收的迹象

ble_gattc_util.h

关贸总协定的客户端工具

ble_gatts.h

关贸总协定服务器API:

  • 设置属性数据库

  • 设置属性值

  • 通知/指示特征值

  • 启动MTU交流

  • 响应读写请求

ble_l2cap

BLE L2CAP API。

ble_storage.h

BLE持久存储API。

ble_uuid.h

BLE UUID声明和辅助函数。

5.2。软件升级的空气(SUOTA)

5.2.1。介绍

的SmartSnippets™DA1469x SDK允许用户更新无线设备的软件,利用软件升级的空气(SUOTA)过程。

当一个更新过程开始从一个Android和iOS设备,一个新的固件图像首先转移到闪存设备,然后重新启动以完成更新。最后的验证和激活新形象由ROM引导加载程序在执行下一个重启。更多信息参见章5.3。1

SUOTA关贸总协定服务器上运行DA1469x设备和关贸总协定Android和iOS设备上的客户端运行SUOTA应用程序。

5.2.2。SUOTA服务描述

本节简要描述SUOTA服务,负责执行软件升级/祝福。给出一个详细的服务特征描述表35

表35 SUOTA服务特征

特点抽搐

SUOTA版本

(SUOTA_VERS离子定义)

访问

大小

描述

MEM_DEV

从版本v1.3

4

使用这个特性关贸总协定客户机可以发送命令到SUOTA服务。一些最常用的命令如下:

  • SPOTAR_IMG_SPI_FLASH (0 * 13): SUOTA做准备。图像将被存储到闪存。

  • SPOTAR_REBOOT (0 xfd):重新启动设备。

  • 以SPOTAR_IMG_END (0 xfe):客户端发送整个图像。SUOTA服务允许执行CRC计算和其他理智测试来验证图像转移成功。

GPIO地图

4

用于指定GPIO外部闪存设备的地图。目前不适用。

MEM_INFO

4

直到现在商店收到的字节总数。

PATCH_LEN

从版本v1.3

2

指定的字节数,当收到,将触发通知回关贸总协定客户机。这意味着用于流量控制。关贸总协定的确切值设置在SUOTA客户机。生成的通知从“状态”的特点

PATCH_DATA

从版本v1.3

WRITE_NO_RE SP

确切的大小规定PATCH_DATA CHAR_SIZE

这是SUOTA图像数据发送端点。指定的确切大小”PATCH_DATA CHAR_SIZE”特点,并可以使用不同的值(23 - 509)根据吞吐量的需求

状态

从版本v1.3

通知

1

这个特点是用来通知关贸总协定客户SUOTA的状态的过程。状态通知被发送到显示错误条件(例如错误的命令,或CRC)或允许SUOTA过程中流量控制。

L2CAP_PSM

从版本v1.3

2

这是一个可选的特性,如果存在,表明SUOTA服务支持SUOTA在关贸总协定和SUOTA L2CAP CoC。的值表示动态L2CAP信道SUOTA服务侦听连接。没有这个特征表明,只有在关贸总协定SUOTA支持。

版本

从版本v1.3

1

表明SUOTA服务的版本。从“SUOTA_VERSION”中检索值的定义。

MTU

从版本v1.3

2

商店MTU的当前值,也就是23(默认),或一个更大的价值,如果MTU交换发生。这个值可以使用由关贸总协定客户机检索MTU大小(如果这样的API不是可用的)与最优率和写“PATCH_DATA”特征。

PATCH_DATA CHAR_SIZE

从版本v1.3

2

指定的大小“PATCH_DATA”特征。

CCC

1

客户特点配置允许关贸总协定客户启用通知从“状态”源。

一旦发现SUOTA服务在远程设备和关贸总协定客户机启用通知通过编写CCC的特点,可以开始通过发行SUOTA过程<代码class="docutils literal notranslate">SPOTAR_IMG_SPI_FLASH命令。写命令执行成功的前提是:

  • 不超过一台设备正在连接到SUOTA启用设备

  • 应用程序驻留在SUOTA启用设备允许升级

  • 有足够的内存分配的内部工作缓冲区

如果违反任何上述限制,然后命令失败,错误通知发送回客户机关贸总协定(状态<代码class="docutils literal notranslate">SUOTA_SRV_EXIT)。命令执行成功后服务能够接收数据在关贸总协定或L2CAP CoC层(如果<代码class="docutils literal notranslate">L2CAP_PSM特点是可用的)。

关贸总协定客户机可以使用的价值特征<代码class="docutils literal notranslate">MTU执行ATT写命令的特点<代码class="docutils literal notranslate">PATCH_DATA与最佳大小如果关贸总协定客户端(手机)没有API来找到最优包的大小。也有可能为关贸总协定客户机检索的大小<代码class="docutils literal notranslate">PATCH_DATA通过阅读特点<代码class="docutils literal notranslate">PATCH_DATA_CHAR_SIZE的特点。

在这之后,关贸总协定客户机应该指定的值<代码class="docutils literal notranslate">patch_len变量通过编写<代码class="docutils literal notranslate">PATCH_LEN的特点。<代码class="docutils literal notranslate">PATCH_LEN指定的字节数,一旦收到,会触发一个通知回关贸总协定客户机。这种流控制可以用来避免洪水SUOTA启用设备与太多的图像数据。值越大,更好的吞吐量,因为通知会生成较少,因此错过了连接事件的数量(流已经停止等待通知)却降低了。

例如,如果<代码class="docutils literal notranslate">patch_len设置为500字节时,通知将被发送到关贸总协定客户机时字节范围1 - 500,501 - 1000,1001 - 1500等。蓝牙低能量后规范,最大可以写入的字节数<代码class="docutils literal notranslate">PATCH_DATA特性与单个ATT写命令的最小的MTU - 3和的大小<代码class="docutils literal notranslate">PATCH_DATA的特点。

当整个图片已发送,关贸总协定客户机应该问题<代码class="docutils literal notranslate">SPOTAR_IMG_END命令来显示这个SUOTA服务。服务将会执行一些健康检查来验证图像转移发生没有错误,然后将生成适当的状态通知(<代码class="docutils literal notranslate">SUOTA_CMP_OK成功,<代码class="docutils literal notranslate">SUOTA_APP_ERROR或<代码class="docutils literal notranslate">SUOTA_CRC_ERR错误)。

最后,关贸总协定客户机可能问题<代码class="docutils literal notranslate">SPOTAR_REBOOT命令强制重启设备。这一步是可选的,但强烈推荐。

请注意

的<代码class="docutils literal notranslate">PATCH_DATA,<代码class="docutils literal notranslate">PATCH_DATA_CHAR_SIZE和<代码class="docutils literal notranslate">PATCH_LEN特点是只有当SUOTA有关关贸总协定。当使用L2CAP CoC时,应该建立的连接<代码class="docutils literal notranslate">L2CAP_PSM通过L2CAP信道CoC和流控制使用L2CAP学分。SUOTA服务分配足够的学分才能确保流期间不会停止升级。通知相关<代码class="docutils literal notranslate">PATCH_LEN在图像传输特性不发送,但所有其他通知仍然有效。

5.2.3。SUOTA流

图38图39说明了抽象的固件更新步骤。图40详细说明了SUOTA的流程图。

最后的验证和激活新形象由ROM引导加载程序在执行下一个重启。图图58展示了的引导序列显示一步弗兰克-威廉姆斯形象的接受/拒绝发生。

. . / _images / 112. png

图38Flash布局初始编程后在生产

. . / _images / 113. png

图39Flash图像布局SUOTA后图像写在目的地分区

. . / _images / 114. png

图40Flash图像布局后重新启动和激活的新形象

5.2.4。执行SUOTA升级使用一个移动电话

请注意

下列程序适用于使用Android和iOS设备

5.2.4.1。准备SUOTA启用设备

  1. 构建pxp_reporter应用程序使用<代码class="docutils literal notranslate">DA1469x-00-Release_QSPI_SUOTA配置。

  2. 消除DA1469x使用的闪存<代码class="docutils literal notranslate">erase_qspi_jtag脚本。

  3. 下载pxp_reporter二进制DA1469x使用program_qspi_jtag脚本。

按K2 DK的女儿董事会(重置)按钮。PXP记者应用程序应该开始运行。

5.2.4.2。准备SUOTA形象

SUOTA形象是一个二进制文件,一个合适的标题,可以发送到目标设备从一个Android和iOS设备。

准备一个SUOTA图像使用PXP记者演示应用程序,请执行以下步骤:

  1. 以下两个项目导入SmartSnippets™工作室从这些位置。

    • python_scripts:<代码class="docutils literal notranslate">< sdk_root_directory > \实用工具

    • pxp_reporter:<代码class="docutils literal notranslate">< sdk_root_directory > \ \ dk_apps \演示项目

  2. 构建pxp_reporter应用程序使用<代码class="docutils literal notranslate">DA1469x-00-Release_QSPI_SUOTA配置。一个新的形象命名<代码class="docutils literal notranslate">pxp_reporter.img也是下创建<代码class="docutils literal notranslate">DA1469x-00-Release_QSPI_SUOTA文件夹中。

5.2.4.3。执行SUOTA使用移动应用程序

  1. 下载对话框SUOTA应用程序从谷歌PlayStore或苹果应用商店。

  2. 复制<代码class="docutils literal notranslate">pxp_reporter.imgAndroid手机或平板电脑或者一个iOS设备并放置到SUOTA文件夹。自动创建文件夹,如果它不存在,在设备上通过运行”对话框Suota”应用程序。在Android上它位于“内部存储驱动器的根目录。

  3. 在Android手机上启动对话框SUOTA应用程序并选择您想DA1469x设备更新。

. . / _images / 076. png

图41设备的选择

  1. 选择更新设备

. . / _images / 077. png

图42更新设备

  1. 选择适当的图像文件——这是一个SUOTA目录中的文件列表。

. . / _images / 078. png

图43图像文件

请注意

中所示的屏幕图44,图45Da1469x产品没有影响。

  1. 触摸发送到设备在触摸屏

. . / _images / 079. png

图44SPI的参数设置

. . / _images / 080. png

图45I2C的参数设置

  1. 等到这个过程就完成了。上传图片时,会弹出一个对话框要求设备重启。选择好吧

. . / _images / 081. png

图46上传图像文件

. . / _images / 082. png

图47重新启动设备

  1. 新闻关闭回到主菜单。

. . / _images / 083. png

图48当文件上传完成后,按“关闭”

5.2.5。使用两个DA1469x设备执行SUOTA升级

本节描述的过程执行SUOTA使用两个DA1469x设备。

  • 一个扮演BLE中央。它执行的SUOTA形象发射机运行<代码class="docutils literal notranslate">ble_suota_client应用程序。SUOTA形象将存储在NVMS_BIN_PART NVMS分区。

  • 一个祝福外围。它执行SUOTA图像接收器,运行<代码class="docutils literal notranslate">pxp_reporter应用程序。

使用这个设置,可以测试两个SUOTA方法(在关贸总协定和L2CAP面向连接通道)不使用任何电话。图像传输存储在闪存的NVMS_BIN_PART分区BLE中央设备。

5.2.5.1。准备SUOTA启用设备<代码class="docutils literal notranslate">pxp_reporter

跟描述的步骤5.2.4。1

一旦<代码class="docutils literal notranslate">program_qspi_jtag执行时,会弹出一个新窗口要求选择设备是目标;选择合适的设备。

. . / _images / 094. png

图49选择目标设备

5.2.5.2。准备SUOTA更新图像

看到章5.2.4。2

5.2.5.3。准备<代码class="docutils literal notranslate">ble_suota_client设备

5.2.5.3.1。构建<代码class="docutils literal notranslate">ble_suota_client应用程序

进口下列项目使用SmartSnippets™工作室从以下位置:

  • python_scripts:<代码class="docutils literal notranslate">< sdk_root_directory > \实用工具

  • ble_suota_client:<代码class="docutils literal notranslate">< sdk_root_directory > \ dk_apps \ \项目特性

并选择以下的构建配置ble_suota_client项目:

  • ble_suota_client在<代码class="docutils literal notranslate">DA1469x-00-Release_QSPI配置。

构建和安装<代码class="docutils literal notranslate">ble_suota_client遵循以下程序:

  1. 构建项目ble_suota_client通过执行<代码class="docutils literal notranslate">DA1469x-00-Release_QSPI

  2. 擦除闪存设备的执行<代码class="docutils literal notranslate">erase_qspi_jtag脚本。

  3. 执行<代码class="docutils literal notranslate">program_qspi_jtag脚本程序QSPI闪存。

一旦执行脚本时,会弹出一个新窗口要求dk是目标的选择;选择合适的设备。

. . / _images / 087. png

图50选择目标设备

5.2.5.3.2。存储SUOTA更新的形象<代码class="docutils literal notranslate">ble_suota_client设备

请注意

步中创建的SUOTA更新图像准备SUOTA更新图像

使用<代码class="docutils literal notranslate">cli_programmer下载二进制pxp_reporter。img的设备。

>< SDK_ROOT_PATH > \ \ cli_programmer.exe二进制文件< SERIAL_PORT >write_qspi0 x300000项目< SDK_ROOT_PATH > \ \ dk_apps \ demo \ pxp_reporter \ DA1469x-Debug_QSPI_SUOTA \ pxp_reporter.img

5.2.5.3.3。执行软件升级过程

先前的程序完成时,两个DA1469x设备已经准备好交流。执行SUOTA PXP记者设备,应遵循以下步骤:

  • 需要连接到串行终端<代码class="docutils literal notranslate">ble_suota_client设备和执行SUOTA。在下面的示例中,“真正的术语“用于这一目的。串行终端配置如下:

. . / _images / 131. png

图51配置串口

  • 连接到串口并摁下<代码class="docutils literal notranslate">K2重置按钮。

. . / _images / 130. png

图52连接到串行端口

有关图像信息存储在引导期间NVMS_BIN_PART分区显示

  • 在串行终端的<代码class="docutils literal notranslate">ble_suota_client设备,给下面的命令:

    >扫描开始

. . / _images / 120. png

图53扫描可用的设备

的<代码class="docutils literal notranslate">ble_suota_client设备立即开始扫描可用的设备(图53)。在这个例子中,从列出的设备图53,<代码class="docutils literal notranslate">pxp_reporter装置,设备序列号<代码class="docutils literal notranslate">[01]

  • 一旦<代码class="docutils literal notranslate">pxp_reporter找到设备,扫描操作可以停止使用下面的命令:

    >扫描停止

  • 连接到<代码class="docutils literal notranslate">pxp_reporter设备可以启动命令:

    >连接1

“连接”命令的第一个参数是指设备索引扫描结果列表。一旦建立连接,应用程序会自动查询的远程设备可用的服务和设备信息。设备的特征值信息服务(DIS)阅读。以下输出打印终端:

. . / _images / 121. png

图54连接到装载机设备

“L2CAP PSM”的存在表明,远程设备支持SUOTA和over-L2CAP COC。

  • 更新设备支持L2CAP COC L2CAP,问题更新命令。更新相同的设备在关贸总协定,问题更新关贸总协定命令。如果远程设备不支持L2CAP COC (“L2CAP PSM”不是显示)更新更新关贸总协定命令开始SUOTA关贸总协定。

    >更新关贸总协定

. . / _images / 122. png

图55与新形象装载机设备更新

图像转移已经完成后,远程设备断开连接和重新启动所示图56

. . / _images / 123. png

图56传输完成

当<代码class="docutils literal notranslate">pxp_reporter设备重新启动,开始执行新形象。

软件升级完成。现在,<代码class="docutils literal notranslate">pxp_reporter设备应该开始广告<代码class="docutils literal notranslate"><对话框PX记者>。再次确认,演奏扫描操作,通过发行<代码class="docutils literal notranslate">扫描开始命令。

>扫描开始

. . / _images / 108. png

图57验证装载机运行PX的记者

5.3。引导

引导ROM代码执行的<代码class="docutils literal notranslate">SYSCPU(Cortex-M33)运动后或HW重置。作为一个额外的功能它可以唤醒后执行<代码class="docutils literal notranslate">RESET_ON_WAKEUP功能配置。

四种不同的支持引导口味:

  • 从缓存QSPI FLASH引导没有任何安全特性,配置脚本在OTP (CS)

  • 从缓存QSPI FLASH引导没有任何安全特性,配置脚本(CS)在闪光

  • 从缓存QSPI FLASH引导和安全特性,配置脚本在OTP (CS)

  • 从UART引导没有FLASH和安全特性

Flash和UART可用,橄榄球员仍在一个infinent循环。

配置脚本(CS)是256 32位的表条目。系统可以引导CS,但如果它存在在Flash或OTP存储。橄榄球员预计CS开始地址<代码class="docutils literal notranslate">0 x00000000flash或<代码class="docutils literal notranslate">0 x00000c00OTP。它包含有关橄榄球员的信息,比如产品头位置,发展模式标志条目,可以使用SDK或应用软件将一些值应用到特定的寄存器(地址值对)或使用它们作为一个子系统调整值。在CS的地址值对条目是一种橄榄球员的启用安全特性。额外保护的安全引导模式CS存储OTP以难以改变安全相关的条目。更多信息关于CS有效条目,请参阅DA1469x数据表章“系统概述”,“OTP”段,“配置脚本”。

5.3.1。启动流程

启动流程分为五个不同阶段

  • 初始化:配置权力的橄榄球员负责域和外围时钟。引导代码重置OTP(一次可编程)和闪存为了能够访问它们。它使发展模式默认情况下。在橄榄球员使调试器和开发模式也可以更新设备通过UART固件。开发模式可以得到释放,在CS添加相应的条目。

  • 运行配置脚本:橄榄球员搜索CS在Flash或地址<代码class="docutils literal notranslate">0 x00000c00OTP。如果发现CS开始解析它并应用指令,否则继续下一个状态。

  • 检索应用程序代码:这个阶段取决于发展模式

    发展模式启用
    橄榄球员将使调试器并试图引导UART形式。如果不能从UART检索应用程序,它将尝试找到一个有效的产品标题。如果找到一个产品标题将继续下一个阶段,否则会再次尝试从UART引导。如果没有有效的产品标题橄榄球员将进入一个无限循环。这个循环是活跃的,直到靴子形式UART或调试器连接。

    发展模式禁用
    在这种情况下,调试器和从UART启动特性都是禁用的。橄榄球员试图定位和解析产品并从FLASH图像标题。如果这些标题是无效的,HW执行重置。

  • 设备管理:橄榄球员将首先检查是否有任何等待更新。的更新将验证新的固件图像,如果验证成功橄榄球员将接受更新。否则橄榄球员将拒绝更新,引发HW重置并引导旧图片。如果没有等待更新橄榄球员将验证活动(旧)的形象。如果验证失败橄榄球员将再次引发HW重置。图像验证取决于安全模式。如果图像是不安全的橄榄球员检查“Qq”图像头的开始。如果弗兰克-威廉姆斯图像是安全的橄榄球员必须做以下额外的检查。

    1. 检查图片标题包含安全部分(<代码class="docutils literal notranslate">0 xaa22)。

    2. 检查图像头包含管理部门(<代码class="docutils literal notranslate">0 xaa44)

    3. 检查是否能够提取公共密钥,加密密钥、签名验证价值和特定场合。

    4. 检查使用的公钥签名验证不撤销。

    5. 检查应用程序加密密钥不撤销。

    6. 检查签名值计算<代码class="docutils literal notranslate">Ed25519算法是正确的。

    任何上述检查失败,那么橄榄球员将引发HW重置。

  • 加载图片:这是最后的启动阶段的实际FW图像加载。这一阶段分为以下步骤:
    1. Flash QSPI控制器配置检索信息<代码class="docutils literal notranslate">产品

    2. 启用安全特性的,解密密钥获取通过DMA QSPI控制器。QSPI控制器支持动态图像解密。

    3. 中断矢量表(溶)复制到RAM

    4. 缓存控制器配置为指向的早期开始

    5. 0 x0 QSPI FLASH地址重新映射到地址

    6. SW_RESET触发

    如果发生任何错误,在此阶段HW重置将引发的橄榄球员。

更多细节请参考图58

. . / _images / 003. png

图58BootROM流

5.3.2。FLASH布局

bootROM预计至少三个不同的部分在FLASH能够引导。这些所示:图59

. . / _images / 004. png

图59FLASH布局

配置脚本是一个可选的区域。

产品标题始于“页”,包含积极的地址信息和更新固件图像,QSPI控制器和闪存设备设置和CRC代码用于验证产品头的完整性。有两个产品标题,主要和备份都是相同的。原因是我们想保护系统免受可能的产品标题腐败。橄榄球员第一次做CRC校验的主要标题如果成功解析它,否则一个CRC检查备份的头。以防两头损坏橄榄球员仍然没有<代码class="docutils literal notranslate">产品和行为如上所述<代码class="docutils literal notranslate">引导第一章<代码class="docutils literal notranslate">检索应用程序代码。如果只有主要损坏,橄榄球员拷贝备份头主要头。如果活跃和更新转发图片地址是不同的,橄榄球员将触发更新过程。时更新图像被认为是有效的在设备管理中描述的所有检查阶段是成功的。更新时被认为是成功的橄榄球员成功执行上述引导流动阶段。*产品头字段:

  1. 闪光编程标识符“页”的产品标题标识符

  2. 活跃的弗兰克-威廉姆斯图像地址弗兰克-威廉姆斯标题图片地址在Flash的活跃

  3. 更新弗兰克-威廉姆斯图像地址地址在Flash中更新固件图像标题

  4. 闪光BURSTCMDA注册价值的值写在QSPIC_BURSTCMDA_REG QSPI控制器

  5. 闪光BURSTCMDB注册价值的值写在QSPIC_BURSTCMDB_REG QSPI控制器

  6. 0 xaa11Flash配置部分标识符

  7. 长度闪光配置部分Flash的大小配置部分

  8. 闪光配置注册命令序列命令QSPI控制器

标题图片地区开始“Qq”,分为三个部分,常见的安全与管理。

  • 共同的部分字段:

  1. 图像标识符(“Qq”)图像头标识符

  2. 大小弗兰克-威廉姆斯图像大小

  3. 儿童权利公约CRC值图像完整性检查

  4. 时间戳通过时代以来的秒数(1/1/1970)

  5. 抵消从一开始的<代码class="docutils literal notranslate">图像早期的开始。

  • 安全部分字段:

  1. 0 xaa22安全部分标识符

  2. 长度安全部分大小的安全部分

  3. 指数ECC关键签名关键指标

  4. 指数信谊。关键弗兰克-威廉姆斯解密密钥

  5. 现时标志弗兰克-威廉姆斯加密算法中使用

  6. 长度安全部分大小字节的签名值

  7. 签名签名值用于签名验证

  • 政府部分字段:

  1. 0 xaa44管理部门标识符

  2. 长度政府部分的管理部门

  3. 0 xaa55密钥撤销部分标识符

  4. 长度关键撤销记录撤销记录的关键字的大小

  5. 关键类型类型的关键(如ECC、信谊,用户数据键)

  6. 关键指数关键指标

  7. 下一个关键的记录,如果是可用的

出于安全原因撤销状态的关键是存储在一个特定区域的OTP每个键类型。

行和可执行是早期诊断和应用程序存储的部分中。引导是安全的这一节是加密的。

5.3.3。OTP布局

OTP由几个不同的部分。这些部分需要的不安全的引导。下面的表中有一个段的描述。

表36 OTP布局

字节

描述

OTP地址

1

1024年

配置脚本

~ 100寄存器写操作

0 x00000c00

2

256年

QSPI FW解密密钥区——有效载荷

写/读保护在CS当启用安全模式

安全模式连接这些(8 * 256位)钥匙QSPI控制器

0 x00000b00

3

256年

用户数据加密密钥——有效载荷

写/读保护在CS当启用安全模式。

安全模式连接这些AES(8 * 256位)关键引擎

0 x00000a00

4

32

QSPI FW解密密钥区——指数8条目8 256位的密钥

0 x000009e0

5

32

用户数据加密密钥——指数

8条目8 256位的密钥

0 x000009c0

6

256年

签名密钥区——有效载荷

0 x000008c0

7

32

签名密钥区——指数

0 x000008a0

8

2208年

客户应用领域(二次引导装载程序、二进制文件…)

0 x00000000

5.4。构建配置和启动程序

本节提供了一个简短的描述支持的项目构建配置和启动过程的SmartSnippets™DA1469x SDK。

5.4.1之前。构建配置

SmartSnippets™DA1469x SDK项目默认支持以下两种类型的构建配置:

表37 构建配置

构建配置

代码和只读数据的位置

缓存启用

描述

内存

内存

没有

程序直接加载到内存中。

QSPI

Flash (QSPI模式)

是的

程序运行就地QSPI flash。

5.4.1.1。QSPI构建配置

在这种模式下,代码将被放置在FLASH中而变量将被放置在RAM中。也可以转移到RAM使用特定功能<代码class="docutils literal notranslate">__RETAINED_CODE宏。这可能是有用的,当一个特定的时间实现函数至关重要的功能。一个程序为flash写入缓存模式建造QSPI闪存的CLI程序员工具。随着应用程序映像,QSPI Flash也必须设定有效的产品和图像标题。硬复位后,橄榄球员读取这些头设置外部闪存和准备应用程序映像之前。

硬复位后,罗重新映射到地址0 x0,橄榄球员开始执行。起初,橄榄球员会读产品图像头(FLASH)来验证一个有效的固件图像编程FLASH。它还将计划QSPI FLASH控制器根据相关字段的内容产品头,使QSPI自动模式和执行到位(XIP)。在开始执行程序固件图像之前,橄榄球员设置缓存控制器和应用程序的副本溶(中断矢量表)从FLASH内存。<代码class="docutils literal notranslate">SYS_CTRL_REG [REMAP_INTVECT]启用的虚拟地址0 - 0 x1ff映射到内存的开始,即内存区域<代码class="docutils literal notranslate">0 x00000000- - - - - -0 x000001ff映射到内存区域<代码class="docutils literal notranslate">0 x20000000- - - - - -0 x200001ff。这确保了溶总是位于RAM的快速访问。<代码class="docutils literal notranslate">SYS_CTRL_REG [REMAP_ADR0]设置为2 (FLASH重新映射到虚拟地址0 x0)和软件复位。CPU读取的位置<代码class="docutils literal notranslate">Reset_Handler从RAM(因为<代码class="docutils literal notranslate">SYS_CTRL_REG [REMAP_INTVECT]启用),<代码class="docutils literal notranslate">Reset_Handler开始执行从FLASH。

程序由QSPI构建配置可以使用执行<代码class="docutils literal notranslate">QSPI_DA1469x调试配置使用SmartSnippets™工作室。还可以执行图像在开发工具包,按下复位按钮后编程Flash。

5.4.1.2。RAM构建配置

在这种模式下,代码和数据都是放在内存。程序由RAM构建配置可以直接加载到RAM使用精灵文件和J-Link调试器或首先转换为原始二进制,然后写入内存的CLI程序员工具。RAM模式仅用于调试目的,因为它避免了编程的步骤QSPI闪光。加载程序后,<代码class="docutils literal notranslate">SYS_CTRL_REG [REMAP_ADR0]必须配置,内存映射到地址吗<代码class="docutils literal notranslate">0 x00000000。软复位后,书面程序开始执行。RAM模式并不依赖于引导加载程序。因此,产品图像头QSPI闪不影响执行固件。

程序由RAM构建配置可以使用执行<代码class="docutils literal notranslate">RAM_DA1469x调试配置使用SmartSnippets™工作室。还可以使用加载和执行图像CLI程序员工具。在这两种情况下<代码class="docutils literal notranslate">SYS_CTRL_REG [REMAP_ADR0]配置相应的适当的工具。

5.4.2。启动程序

启动代码是程序复位后运行的一部分,在进入之前<代码class="docutils literal notranslate">main ()。简单地说,它包括以下步骤,如图所示图60(请咨询中的启动代码SmartSnippets™DA1469x SDK):

. . / _images / startup_procedure.png

图60启动程序

  1. Reset_Handler在<代码class="docutils literal notranslate">sdk \ bsp \ \ startup_da1469x.S创业开始执行。

  2. SystemInitPre ()在<代码class="docutils literal notranslate">sdk \ bsp \ \ system_da1469x.c创业被调用,执行以下操作:

    • 启用调试器(如果相应的宏,<代码class="docutils literal notranslate">dg_configENABLE_DEBUGGER启用)。

    • 设置分隔器的安巴高速总线和外围总线。

    • 检查集成电路兼容SW版本。

    • 检查我们复制的一致性和零表。

    • 把垫门闩,内存控制器,PDC和外设的时钟一个众所周知的初始状态。

请注意

没有变量初始化应该发生,因为复制&零表尚未初始化的变量,任何修改将丢弃。出于同样的原因,初始化的函数或使用初始化变量不应该被称为。

  1. Reset_Handler在<代码class="docutils literal notranslate">sdk \ bsp \ \ startup_da1469x.S创业继续执行。

    • 根据代码和数据复制到RAM<代码class="docutils literal notranslate">.copy.table部分。

    • 初始化内存区域显示为零<代码class="docutils literal notranslate">.zero.table部分。

  2. SystemInit ()在<代码class="docutils literal notranslate">sdk \ bsp \ \ system_da1469.c创业被调用,执行以下操作:

    • 配置中断优先级。

    • 配置QSPI Flash和缓存。这样做是为了调整配置适用于特定的橄榄球员代码闪光模式。

    • 读修剪和校准部分(TCS)值一次性可编程(OTP)存储器

    • 配置域控制器(PDC)的力量。

    • 让权力领域众所周知的初始状态。

    • 激活BOD的保护。

  3. __START被调用时,初始化一些libc结构,然后调用<代码class="docutils literal notranslate">main ()

5.5。的内存布局

本节简要描述可用的程序和数据的记忆。给出信息的内存布局图61而在表38在下面。

. . / _images / da1469x_system_mem.png

图61系统内存

表38 的内存布局

存储设备

起始地址|结束地址

大小(字节)

大小(简约)

重新映射设备

0 x00000000

0 x00800000

0 x800000

8192年

0 x00900000

0 x00920000

0 x020000

128年

OTP

0 x10080000

0 x10081000

0 x001000

4

RAM(代码接口)

0 x00800000

0 x00880000

0 x080000

512年

RAM(系统接口)

0 x20000000

0 x20080000

0 x080000

512年

QSPI FLASH(代码接口、缓存)

0 x16000000

0 x16800000

0 x800000

8192年

QSPI FLASH(系统接口,未)

0 x36000000

0 x36800000

0 x800000

8192年

5.5.1。罗

128年简约罗映射到地址<代码class="docutils literal notranslate">0 x900000,只是用于执行橄榄球员的代码。这是第一段代码,将HW重置后,执行之前给应用程序。

5.5.2。OTP

4简约一次性可编程(OTP)内存访问地址<代码class="docutils literal notranslate">0 x10080000和它的主要目的是存储信息(产品标题和配置脚本),将使用橄榄球员之前给应用程序。

5.5.3。系统内存

RAM(512简约)映射到地址<代码class="docutils literal notranslate">0 x80000(代码接口)<代码class="docutils literal notranslate">0 x20000000(系统接口)。访问RAM缓存。BLE项目,有些记忆是小脑模型所使用的CPU。系统内存包含8 RAM细胞(64简约,每个),独立开立可配置为在睡眠中不保留他们的内容,减少能耗。也有可能一个内存单元完全禁用的情况下不需要的应用程序。

5.5.4。外部QSPI闪光

外部闪存(8 mib)映射到地址<代码class="docutils literal notranslate">0 x16000000(代码接口)<代码class="docutils literal notranslate">0 x36000000(系统接口)。访问外部闪存缓存只有当执行通过代码接口(或重新映射区域)和透明地执行由于内部QSPI闪存控制器的使用。BLE主机和应用程序代码都坐落于此。

5.5.5。重新映射区域

这取决于的价值<代码class="docutils literal notranslate">SYS_CTRL_REG [REMAP_ADR0]地区注册字段访问的地址<代码class="docutils literal notranslate">[0 x0,0 x7fffff]可以映射到

  • 罗(<代码class="docutils literal notranslate">0 x900000)

  • 系统内存(<代码class="docutils literal notranslate">0 x80000)

  • 外部QSPI Flash地址范围(<代码class="docutils literal notranslate">0 x16000000)

当<代码class="docutils literal notranslate">SYS_CTRL_REG [REMAP_INTVECT]设置为1时,地址范围<代码class="docutils literal notranslate">[0 x0,0 x1ff]映射到系统内存<代码class="docutils literal notranslate">[0 x800000,0 x80001ff]地址范围,允许中断矢量表在内存执行从FLASH。

当闪光重新映射到地址0 x0 (<代码class="docutils literal notranslate">SYS_CTRL_REG [REMAP_ADR0]2),启用了缓存,FLASH的有效地址的地址范围(0 x0, 0 x7fffff)所使用的CPU或调试器的值取决于<代码class="docutils literal notranslate">CACHE_FLASH_REG:

  • FLASH_REGION_SIZE (<代码class="docutils literal notranslate">CACHE_FLASH_REG [31:16])用于将FLASH地区大小相等的条件。

  • FLASH_REGION_OFFSET (<代码class="docutils literal notranslate">CACHE_FLASH_REG(福音15:4))定义了每个次区域的抵消。

  • FLASH_REGION_BASE (<代码class="docutils literal notranslate">CACHE_FLASH_REG (2:0))定义了FLASH地区基地。

重新映射地址的有效FLASH地址可以计算如下:

(CACHE_FLASH_REG [FLASH_REGION_SIZE]< <16)+(CACHE_FLASH_REG [FLASH_REGION_OFFSET]< <2)+ADDR

这使应用程序图像从地址0 x0编译执行,被放置在不同的FLASH位置允许固件更新。

比如,考虑的情况<代码class="docutils literal notranslate">CACHE_FLASH_REG的值<代码class="docutils literal notranslate">0 x16009006:

  • FLASH_REGION_BASE是<代码class="docutils literal notranslate">0 x1600

  • FLASH_REGION_OFFSET是<代码class="docutils literal notranslate">0 x900分辨率下玩。因为这个领域是在32位的话,实际的字节的偏移<代码class="docutils literal notranslate">0画素

  • FLASH_REGION_SIZE是<代码class="docutils literal notranslate">0 x6。这个值对应于一个flash 0.5 mib的区域大小(<代码class="docutils literal notranslate">0 x80000)。

任何CPU或调试器访问地址<代码class="docutils literal notranslate">0 x1000将重新映射到FLASH的地址吗<代码class="docutils literal notranslate">0 x16002400+<代码class="docutils literal notranslate">0 x1000。自<代码class="docutils literal notranslate">CACHE_FLASH_REG [FLASH_REGION_BASE]是<代码class="docutils literal notranslate">0 x6(0.5 MiB), CPU的有效地址范围是通过重新映射允许访问的地区<代码class="docutils literal notranslate">[0 x0,0 x7ffff- - - - - -0画素],翻译<代码class="docutils literal notranslate">[0 x16002400,0 x1607ffff]闪光灯范围。试图访问一个地址在这个地区将未定义的结果。同样的限制也适用于代码内存范围,如CPU将只能够访问地址<代码class="docutils literal notranslate">[0 x16000000,0 x1607ffff]使用内存范围的代码,<代码class="docutils literal notranslate">0 x16000000来<代码class="docutils literal notranslate">0 x167fffff。不过,注意地址范围<代码class="docutils literal notranslate">[0 x16000000,0 x160023ff]将未访问。然而,调试器可以访问整个代码内存范围,<代码class="docutils literal notranslate">0 x16000000来<代码class="docutils literal notranslate">0 x167fffff,无论<代码class="docutils literal notranslate">CACHE_FLASH_REG配置。

的<代码class="docutils literal notranslate">CACHE_FLASH_REG配置为橄榄球员执行期间适当的值,根据产品和应用FW头。

CPU和调试器都能够访问整个闪存地址范围没有限制使用未系统内存范围,<代码class="docutils literal notranslate">0 x36000000来<代码class="docutils literal notranslate">0 x367fffff

5.6。非挥发性存储器(NVMS)

的SmartSnippets™DA1469x SDK定义非易失存储器存储管理的软件层。至关重要的开发人员有一个清晰的理解的要求,可以使用非易失性存储以下元素:

  • 系统参数需要存储在NVM(如设备地址)

  • 固件升级(双重图像)

  • 特定于应用程序的二进制文件(如预录的音频信息)

  • 日志(例如,事件日志)

  • 应用程序数据(例如传感器值,统计数据,验证密钥)

对于每一个存储类型对应的,专用的区域分配的闪存分区表。每个地区时被一个分区ID。NVMS适配器使得存储器读/写访问,它使用分区ID和一个偏移量。更多细节可以发现在NVMS适配器部分,4.2.4

的SmartSnippets™DA1469x SDK定义了以下闪存分区(non-SUOTA构建)来管理存储:

  • (FW)固件图像区域

  • (PARAMS)参数区域

  • (本)的二进制文件

  • (日志)的事件日志或值

  • (数据)通用数据区域,统计数据等。

具体的内存映射取决于实际的闪存设备(如大小、扇区大小)在黑板上使用。这个映射需要定义在编译时文件<代码class="docutils literal notranslate">< sdk_root_directory > / bsp / config / 4 m / partition_table.h(或<代码class="docutils literal notranslate">< sdk_root_directory > / bsp / config / 4 m / suota / partition_table.h当使用SUOTA)。提供一个默认分区表SmartSnippets™DA1469x SDK,适合在DK QSPI Flash (4 mib的部门4简约),所示的实际定义代码32:

代码32 NVMS映射
PARTITION2(NVMS_PRODUCT_HEADER_PART,0)PARTITION2(NVMS_FIRMWARE_PART,0)PARTITION2(NVMS_GENERIC_PART,PARTITION_FLAG_VES)PARTITION2(NVMS_PLATFORM_PARAMS_PART,PARTITION_FLAG_READ_ONLY)PARTITION2(NVMS_PARAM_PART,0)PARTITION2(NVMS_LOG_PART,0)PARTITION2(NVMS_BIN_PART,0)PARTITION2(NVMS_PARTITION_TABLE,PARTITION_FLAG_READ_ONLY)

当SUOTA实现,需要额外的分区,这样两个当前和更新后的图像可以存储,如所示代码33:

代码33 NVMS映射(SUOTA)
PARTITION2(NVMS_PRODUCT_HEADER_PART,0)PARTITION2(NVMS_FW_EXEC_PART,0)PARTITION2(NVMS_GENERIC_PART,PARTITION_FLAG_VES)PARTITION2(NVMS_PLATFORM_PARAMS_PART,PARTITION_FLAG_READ_ONLY)PARTITION2(NVMS_PARAM_PART,0)PARTITION2(NVMS_FW_UPDATE_PART,0)PARTITION2(NVMS_LOG_PART,0)PARTITION2(NVMS_PARTITION_TABLE,PARTITION_FLAG_READ_ONLY)

请注意

NVMS_PARTITION_TABLE应该总是位于抵消定义的<代码class="docutils literal notranslate">PARTITION_TABLE_ADDR配置宏。

5.7。QSPI FLASH支持

本节描述的QSPI Flash支持SmartSnippets™DA1469x SDK和用户需要遵循的步骤,以添加支持新的Flash类型。

SDK支持默认情况下三种不同的flash设备:

  • Macronix: MX25U3235F, 32兆比特

  • 华邦电子:W25Q32FW, 32兆比特

  • Gigadevice: GD25LE32, 32兆比特

这三个设备测试SDK版本使用下面列出的操作模式。默认的设备是Macronix MX25U3235F。这个设备是安装在ProDK和USB-Kit董事会。可以选择另一个装置通过改变宏部分所示5.7.4

部分5.7.7解释如何添加支持其他flash设备的启动顺序三个支持设备。用户将需要检查仔细Flash命令集和验证正确的读/写/擦除操作所需的时钟速度。

5.7.1。操作模式和配置

的SmartSnippets™DA1469x SDK支持两种操作模式:自动检测模式和手动模式。自动侦测模式可以检测flash类型在运行时,而手动模式需要显式地声明中使用的flash项目在编译时间。

请注意

手动模式是默认和推荐模式。自动侦测模式将大大增加代码大小和保留的内存使用情况,并可能防止项目拟合在RAM中。

5.7.2。自动检测模式

自动侦测模式检测flash在运行时使用,并选择适当的flash司机使用。自动检测模式中只能检测到flash设备支持的正式SmartSnippets™DA1469x SDK。如果没有发现匹配,将使用默认的驱动程序(这可能会或可能不会工作)。

因为自动检测模式需要选择要使用的驱动程序在运行时,它所有的驱动程序二进制代码。它还使选择驱动程序的配置参数在保留内存。因此,自动检测模式建议生产构建。

5.7.3。手动模式

手动模式简单地由一个flash驱动程序使用的硬编码声明。因此,只有选择驱动程序被编译的二进制代码,和没有必要保留司机参数保留内存,因为编译器优化。这种模式适用于生产构建。

5.7.4。Flash配置

Flash子系统配置使用宏所示表39,必须定义<代码class="docutils literal notranslate">配置/ custom_config_qspi.h项目文件:

表39 宏对Flash的配置子系统

qspi_flash_config_t领域

描述

dg_configFLASH_AUTODETECT

默认值:0。这个宏,如果设置,支持自动检测模式。请注意,不推荐使用这个宏。

dg_configFLASH_HEADER_FILE

这个宏必须被定义为一个字符串,该字符串表示特定的头文件使用flash驱动程序。如。qspi_mx25u323.h,qspi_qd25le32.h,qspi_w25q32fw.h。这个头文件必须的qspi_ < part_nr >. h头文件中找到<代码class="docutils literal notranslate">< sdk_root_directory > / sdk / bsp /内存/包括或头文件在项目文件夹下,只要这条路是在编译器包括搜索路径(参见文档部分5.7.7添加支持新的闪存设备)。

当系统处于手动模式(<代码class="docutils literal notranslate">dg_configFLASH_AUTODETECT= =0),这是默认的,上面所有的宏定义<代码class="docutils literal notranslate">sdk / config / bsp_defaults.h启用默认使用flash, Macronix<代码class="docutils literal notranslate">MX25U3235F

5.7.5。代码结构

QSPI Flash访问功能已经实现<代码class="docutils literal notranslate">qspi_automode.c和<代码class="docutils literal notranslate">qspi_automode.h文件。常见的命令定义和函数声明所需的所有设备<代码class="docutils literal notranslate">qspi_common.h。设备具体的代码是在头文件中定义命名为<代码class="docutils literal notranslate">qspi_ <闪设备name > . h

中的代码<代码class="docutils literal notranslate">qspi_automode.c(和其他一些地区的SmartSnippets™DA1469x SDK),调用特定于设备的功能和使用特定于设备的值正确初始化闪存设备。每个驱动程序头文件的结构提供了一个实例<代码class="docutils literal notranslate">qspi_flash_config_t的主要推动力,包含所有特定于设备的函数指针和变量。

5.7.6。flash的配置结构

每个司机的头文件必须提供自己的实例<代码class="docutils literal notranslate">qspi_flash_config_t。请注意,这个实例必须与一个独特的名字,命名<代码class="docutils literal notranslate">flash_ <设备名称> _config,因为头文件包含在所有的设备<代码class="docutils literal notranslate">qspi_automode.c文件。因此,有一个单一的全局名称空间。另外,请注意,struct实例必须声明为常量,编译器可以优化引用它。

的<代码class="docutils literal notranslate">qspi_flash_config_t结构,见表40以下字段(参见<代码class="docutils literal notranslate">< sdk_root_directory > / sdk /内存/包括qspi_common.h更多信息):

表40 qspi_flash_config_t结构

qspi_flash_config_t领域

描述

初始化

指针flash-specific初始化函数。

is_suspended

指针指向一个flash-specific函数,检查如果flash擦除/程序暂停状态。

sys_clk_cfg

指针flash-specific函数执行闪存配置系统时钟发生变更时(如虚拟字节或改变<代码class="docutils literal notranslate">QSPIC时钟分频器)。

get_dummy_bytes

指针指向一个flash-specific函数,它返回虚拟字节的数量目前需要时钟变化时(它可能会改变)。

manufacturer_id

Flash电平供应商ID (<代码class="docutils literal notranslate">Cmd0 x9f1字节)。这和<代码class="docutils literal notranslate">device_type和<代码class="docutils literal notranslate">device_densityflash autodetection,需要在自动检测模式。

device_type

Flash电平设备类型(<代码class="docutils literal notranslate">Cmd0 x9f(2字节)。

device_density

Flash电平设备密度(<代码class="docutils literal notranslate">Cmd0 x9f第三个字节)。

erase_opcode

要使用的闪存擦除操作码。

erase_suspend_opcode

使用Flash擦除暂停操作码。

erase_resume_opcode

使用Flash擦除恢复操作码。

page_program_opcode

使用Flash网页程序操作码。

page_qpi_program_opcode

使用Flash QPI页面程序操作码。

quad_page_program_address

如果这是真的,将传输的地址<代码class="docutils literal notranslate">当写一页模式。否则,它将在串行传输模式。

read_erase_progress_opcode

操作码使用,以检查是否擦除正在进行中(通常读状态注册码<代码class="docutils literal notranslate">0 x5)。

enter_qpi_opcode

Flash操作码输入QPI模式。

erase_in_progress_bit

一些检查阅读时抹去进步。

erase_in_progress_bit_high_level

活动状态(<代码class="docutils literal notranslate">真正的:高,<代码class="docutils literal notranslate">:上面的一些低)。

send_once

如果设置为1,那么“性能模式”(或“破裂”,或“连续”;不同/供应商)将用于读访问。在这种模式下,读操作码只发送一次,后续访问只传输地址。

extra_byte

额外的字节传输,在“性能模式”(<代码class="docutils literal notranslate">send_once1),告诉它应该呆在这连续的flash,性能模式。

address_size

是否flash在24 - 32位寻址模式。

memory_size

最大容量,内存大小兆比特的选定的设备。

break_seq_size

是否打破序列,这使flash的连续模式下,一个或两个字节(字节<代码class="docutils literal notranslate">0 xff)。

ucode_wakeup

QSPIC微码使用flash在唤醒。这是QSPI控制器所使用的自动唤醒后,和之前CPU开始代码执行。这是不同的,基于flash是否活跃,在深断电或关闭系统正在睡觉。

power_down_delay

这是时间,购买所需的flash去断电,断电后命令。

release_power_down_delay

这是时间,购买所需的flash退出关闭模式,发布后关闭命令。

power_up_delay

这是时间,购买所需的flash启动。

is_ram

真如果设备内存,假如果设备是Flash。

qpi_mode

只有在QSPIC2使用。如果设备在QPI运营模式。

burst_len

只有在QSPIC2使用。包装破裂的长度,外部存储设备能够实现。

cs_high_t

只有在QSPIC2使用。的最大允许时间tCEM QSPIC_CS可以保持活跃(购买)。

cs_high_t_en

只有在QSPIC2使用。如果启用了tCEM时间的控制。

在自动检测模式下,这些结构位于<代码class="docutils literal notranslate">.rodata部分的代码。flash子系统的初始化后,<代码class="docutils literal notranslate">电平ID(命令<代码class="docutils literal notranslate">0 x9f)的flash读取识别附加设备。获得的<代码class="docutils literal notranslate">电平ID帮助选择合适的<代码class="docutils literal notranslate">flash_ <闪设备> _config结构,并复制保留内存。从这一点开始,结构在必要时用于所有flash操作。

另一方面,在手动模式<代码class="docutils literal notranslate">杰德ID是阅读,因此没有保留结构复制到RAM。作为替代,常量指针<代码class="docutils literal notranslate">flash_config直接分配给特定的常量<代码class="docutils literal notranslate">flash_ <设备名称> _config结构,驻留在选定的设备驱动程序的头文件。然后,编译器优化了整个结构。

5.7.7。添加新的闪存设备的支持

目前的SmartSnippets™DA1469x SDK驱动子系统支持一组特定的QSPI flash设备。然而,它提供的功能添加对其他flash设备的支持。

每个设备驱动程序都必须有自己的头文件应该命名<代码class="docutils literal notranslate">qspi_ <设备name > . h。程序员可以使用<代码class="docutils literal notranslate">qspi_XXX_template.h,或从现有的驱动程序文件。

警告

新的flash驱动程序文件应该放在项目的路径,在一个文件夹在编译器包括搜索路径(一个显而易见的选择<代码class="docutils literal notranslate">配置文件夹,但其他人可以使用)。这是推荐,这样潜在的SDK升级不会干扰特定项目的flash驱动程序实现。

通用代码flash家庭或厂商可以被分解在公共头文件/家庭/供应商。目前常用的头文件,等等<代码class="docutils literal notranslate">qspi_macronix.h和<代码class="docutils literal notranslate">qspi_winbond.h。然而,这是必要的;此外,它的职责是设备驱动程序头文件包含公共头文件,如果需要的话。

请注意

一个定制的flash驱动程序只能用于手动模式,这意味着宏中描述表39必须定义在<代码class="docutils literal notranslate">配置/ custom_config_qspi.h

下面的步骤通常需要创建新的flash司机:

  1. 复制和重命名模板头文件,或现有的驱动程序文件。

  2. 适当地重命名所有的函数和变量。重要的是要记住,所有的驱动程序驻留在相同的名称空间中所有函数和变量名称必须是唯一的。

  3. 定义适当的<代码class="docutils literal notranslate">电平ID值制造商代码、设备类型、设备密度。

  4. 验证<代码class="docutils literal notranslate">暂停,<代码class="docutils literal notranslate">的简历,<代码class="docutils literal notranslate">退出省电,<代码class="docutils literal notranslate">输入省电,<代码class="docutils literal notranslate">,<代码class="docutils literal notranslate">启用,<代码class="docutils literal notranslate">命令是有效的为新设备类型。

  5. 使用一个警卫的头文件<代码class="docutils literal notranslate">#如果预处理器宏检查特定驱动程序选择。

代码34 例子flash警卫队宏
#如果(dg_configFLASH_MANUFACTURER_ID = = WINBOND_ID & & dg_configFLASH_DEVICE_TYPE = = W25Q32FW & & dg_configFLASH_DENSITY = = W25Q_32Mb_SIZE)
  1. 定义任何其他所需的宏(时间等)。

  2. 定义常数唤醒微码需要的数组,每个配置模式,将支持(<代码class="docutils literal notranslate">dg_configFLASH_POWER_OFF,<代码class="docutils literal notranslate">dg_configFLASH_POWER_DOWN或者他们都没有)。微码将复制驱动程序初始化期间QSPI控制器在一个特殊的记忆,唤醒系统初始化后,将使用QSPI(因为此时CPU尚未运行代码)。请参阅(Ref_01)为<代码class="docutils literal notranslate">uCode格式。

  3. 声明常数struct类型的实例<代码class="docutils literal notranslate">qspi_flash_config_t,名叫<代码class="docutils literal notranslate">flash_ <设备名称> _config用适当的值,并初始化它。请注意,这个必须声明为<代码class="docutils literal notranslate">常量

  4. 扩展功能<代码class="docutils literal notranslate">flash_ <设备名称> _initialize ()如果需要,例如写一些特殊QSPI配置寄存器或院子里启用。否则,留下空的。

  5. 扩展功能<代码class="docutils literal notranslate">flash_ <设备名称> _sys_clock_cfg ()如果需要的话。这可以包括修改虚拟字节当系统(以及QSPI)时钟改变,或者改变QSPI时钟分频器(例如,如果flash设备无法应付96 mhz)。否则,留下空的。

  6. 这个函数<代码class="docutils literal notranslate">is_suspended ()应该看flash状态寄存器返回true,如果擦掉或写悬浮在设备上。

  7. 如果连续读模式(有时称为性能或突发模态),确保集<代码class="docutils literal notranslate">send_once1,集<代码class="docutils literal notranslate">extra_byte为flash来保持一个适当的价值在这种模式下工作。这是特定于设备的。

  8. 如果flash支持32位寻址,请确保使用适当的uCode唤醒。还<代码class="docutils literal notranslate">page_program_opcode,<代码class="docutils literal notranslate">erase_opcode,<代码class="docutils literal notranslate">break_seq_size(这也应该考虑设备是否工作在连续读模式)<代码class="docutils literal notranslate">address_size

  9. 如果在写地址,,将提供四模式,集<代码class="docutils literal notranslate">quad_page_program_address为true。

请注意

的SmartSnippets™DA1469x SDK支持阅读四I / O模式(地址和数据读取在四模式中,只有命令在串行传输模式),在连续阅读和正常模式。

5.7.8。使用一个新的闪存设备

读/删除/程序的新QSPI flash设备应使用SmartSnippets™工作室标准程序(检查的“一般安装和调试程序”页(Ref_04))。

使用新QSPI闪存设备之前需要以下步骤:

  • 支持添加新的flash SDK中描述段落5.7.7

  • SDK uartboot项目(二级引导装载程序使用SDK flash编程工具)是建立支持段落中描述的新QSPI flash5.7.4

  • SDK cli_programmer项目(SDK中使用的工具用于访问flash)重建<代码class="docutils literal notranslate">DA1469x_Release_static_linux(如果在Linux)或<代码class="docutils literal notranslate">DA1469x_Release_static_win32(如果在Windows)配置,所述的“CLI应用程序程序员”页面(Ref_04)

  • 当<代码class="docutils literal notranslate">program_qspi_config工具是贯穿SmartSnippets™工作室时,可用的FLASH设备连同他们的命令(这将被放置在破灭<代码class="docutils literal notranslate">产品FLASH部分)的加载<代码class="docutils literal notranslate">公用事业\ python_scripts \ qspi \ flash_configurations.xmlXML文件。为了避免更改默认SDK XML文件,应该创建一个新的在给定的路径,必须提供<代码class="docutils literal notranslate">公用事业\ python_scripts \ qspi \ program_qspi_config.py如下:

    35码 通过自定义FLASH program_qspi_config.py配置文件
    pythonprogram_qspi_configpy- - -prod_idDA1469x- - - - - -00- - - - - -足球俱乐部custom_flash_configurationsxml

    后执行<代码class="docutils literal notranslate">program_qspi_config.py,一个新的<代码class="docutils literal notranslate">program_qspi.xml文件将在生成<代码class="docutils literal notranslate">公用事业\ python_scripts \ qspi路径。因为这是文件时使用<代码class="docutils literal notranslate">program_qspi_config工具运行在SmartSnippets™工作室程序设备的新形象,产品标题是程序根据新的FLASH设备的规格。

请注意

SmartSnippets™工具箱只支持<代码class="docutils literal notranslate">读/删除/编程默认支持QSPI闪存设备。因此,不建议使用新的闪存设备。

5.7.9。测试一个新的闪存设备

要测试闪光驱动,使用PXP记者演示应用程序,并配置新的flash驱动的<代码class="docutils literal notranslate">custom_config_qspi.h和<代码class="docutils literal notranslate">custom_config_qspi_suota.h文件。做以下测试:

  1. 验证应用程序的靴子用SmartSnippets™工作室分析器和手机连接到设备。

  2. 验证应用程序继续工作在系统启动后睡觉(~ 8秒后),手机可以连接到设备,它可以保持连接。

  3. 重复步骤1和2通过改变应用程序时钟96 MHz(改变<代码class="docutils literal notranslate">sysclk_XTAL32M在<代码class="docutils literal notranslate">c来<代码class="docutils literal notranslate">sysclk_PLL96)

  4. 重复步骤1、2和3和改变<代码class="docutils literal notranslate">dg_configPOWER_1V8_SLEEP0(闪光,这是有道理的)和(分开),<代码class="docutils literal notranslate">dg_configFLASH_POWER_DOWN1、测试支持醒来序列驱动模式。

  5. 重复步骤1到4使用SUOTA PXP Reporter应用程序的配置。这将考验的写/擦除功能驱动程序。

5.8。传感器节点控制器编程框架

5.8.1。介绍-SeNIS

传感器节点控制器(SNC)是一个复杂的硬件状态机能够执行一个非常有限的特定指令而自主操作(没有系统的其余部分被wοken)和消散最小的力量。

SNC指令集(命名SeNIS),总结了表41。它允许操作等

  • 轮询传感器状态位

  • 比较寄存器和内存地址内容(值)

  • 传输的数据通信接口系统内存

  • 分支上的比较

等,因此创建小程序(名为足够uCodes)操纵的通信控制器和传感器连接到它们。

表41 传感器节点指令集(SeNIS)概述

指令

描述

WADAD

Operand1,Operand2

存储寄存器的内容/ RAM地址*定义的价值Operand2地址*定义的值Operand1

WADVA

Operand1,Operand2

商店的价值Operand2地址*定义的值Operand1

TOBRE

Operand1,Operand2

XOR寄存器的内容/ RAM地址定义的值Operand1中定义的面具Operand2。如果面具包含“1”在一个特定的地方,那么这个玩家的价值。

RDCBI

Operand1,Operand2

阅读和比较寄存器的内容/ RAM地址定义的值Operand1与“1”在特定的位置和设置EQUALHIGH_FLAG = true。

RDCGR

Operand1,Operand2

比较寄存器的内容/ RAM地址定义的值Operand1的内容地址定义的价值Operand2并设置GREATERVAL_FLAG = true。

COBR

Operand1,Operand2

部门地址*定义的Operand1根据EQUALHIGH_FLAG GREATERVAL_FLAG或为一个特定的次数(取决于的价值Operand2)。

公司

Operand1

增加的内容定义的内存地址值Operand1通过1或4。

Operand1

启动延迟价值定义的蜱虫Operand1,蜱虫一个8位的最小间隔计时器运行在低功率时钟(32 kHz)。计时器到期后,程序执行仍在继续。

方案得到

指定SNC的终结执行。一个信号脉冲PDC是自动生成的,以设置系统和断电SNC睡觉。

NOP

没有操作。

*根据寻址模式选择特定的命令,操作数的值可以是
  • 系统内存的地址或寄存器(直接寻址)或

  • 一个指向被请求的地址所在内存空间(间接寻址)。

SNC的体系结构和功能的详细信息(如寻址模式选择)中可以找到(Ref_01)

5.8.2。传感器节点控制器编程模型的概述

为了方便DA1469x应用程序的开发集成操作系统(FreeRTOS)任务和SNC uCodes,传感亚博国际官网平台网址器节点控制器编程框架提供的SmartSnippets™DA1469x SDK。

. . / _images / fig_SNC_3.png

图62传感器节点控制器编程模型的概述

更具体地说,所示图62,支持SNC编程模型可以概括如下:

  • DA1469x应用程序包括流程执行的操作系统(FreeRTOS)任务(例如CM33执行上下文)和SNC uCodes并行(例如SNC执行上下文)。

  • SNC uCode注册或未注册的SNC从DA1469x系统的适配器,它创建了一个SNC uCodes列表,每个特定的PDC事件触发的。

  • 每个SNC uCode注册PDC事件条目,以便它可以当事件被触发时执行。

  • 执行优先级注册SNC uCodes每PDC事件触发条目定义。

  • SNC适配器使用一个特殊的SNC uCode(即SNC-main uCode)实现的调度注册SNC uCodes执行基于各自uCode列表,它控制着SNC HW模块利用其低水平的司机。

  • 一组SeNIS-based构造C预处理器宏定义,导致一系列的汇编和C语言结构用于SNC uCode发展。

  • 提供一组低水平司机SNC uCodes可为了推动通信等外围设备SPI, I2C等等。

  • 还提供了一个机制来FreeRTOS任务和SNC uCodes组成应用程序交换:

    • 通知

    • (如果数据(例如SNC队列)<代码class="docutils literal notranslate">dg_configUSE_SNC_QUEUES设置为“1”)

  • 提供一种机制用于调试SNC uCodes,使用(如果SNC断点和分步调试区域<代码class="docutils literal notranslate">dg_configUSE_SNC_DEBUGGER设置为“1”)。

  • SNC模拟器可能代替SNC HW模块为了改善和缓解(如果SNC uCode调试过程<代码class="docutils literal notranslate">dg_configUSE_HW_SENSOR_NODE_EMU设置为“1”)。

5.8.3。传感器节点控制器适配器

提出了在部分5.8。2SNC编程框架的一部分SNC适配器,实现<代码class="docutils literal notranslate">ad_snc.c,通过这个SNC uCodes DA1469x软件系统可以很容易地集成。这是通过隐藏底层控制系统的复杂性(如寄存器,终端请求等),实现各自的注册/取消注册机制、配置和沟通与SNC uCodes(更具体地说,SNCuCode-Blocks(见部分5.8。4)在SYSCPU执行上下文(例如CM33 - FreeRTOS任务),主要的操作系统所在和协调所有流程和数据操作为了支持一组应用程序使用DA1469x生态系统的功能。亚博国际官网平台网址

所支持的功能的概述SNC适配器所示图63,而更多的细节为每个流程,提出对应不同的功能在SNC适配器API中定义<代码class="docutils literal notranslate">ad_snc.h),下面给出。进一步的技术信息的使用API(功能参数、结构、枚举等)中可以找到(Ref_04)

为了使所支持的功能,<代码class="docutils literal notranslate">dg_configSNC_ADAPTER宏观必须定义和设置为“1”项目的配置设置(<代码class="docutils literal notranslate">配置/ custom_config_xxx.h)。

. . / _images / fig_SNC_4.png

图63使用SNC适配器注册和SNC uCode沟通

关于所涉及的主要元素的实现SNC适配器,它们可以列出如下:

  • 注册PDC事件和uCodes列表:这是uCodes列表(即uCode-Blocks)已注册到SNC适配器,因此执行在SNC PDC事件被触发。定义的优先级uCodes和PDC uCodes注册事件,决定了结构的列表,本质上导致多级列表所示每PDC事件和优先级图64

  • SNC-main-uCode:uCode时执行的第一个SNC醒来PDC事件触发。它检查uCode列表和驱动器的状态通过每个注册uCodes执行流程,基于PDC事件被触发和PDC事件注册。uCodes的执行没有采用基于优先级的设计,因此为了注册或注销uCode,这意味着更新各自uCodes列表,需要停止和恢复SNC执行SNC-main-uCode上下文。

  • 传感器节点适配器任务:它处理登记,可以SNC uCodes SNC的适配器。并相应地调整其堆栈大小可能,这取决于大小的SNC uCodes组成的应用程序。在启动,它增加了PDC为了支持SNC-to-CM33通知事件条目,创建SNC-main-uCode和寄存器的起始地址后者SNC基地址,这是SeNIS的SNC的内存地址开始执行命令。

  • 传感器节点适配器IRQ的任务:它通过发送处理通知<代码class="docutils literal notranslate">Sensor_Node_Handler ()硬中断请求优先级别处理函数由SNC uCodes SYSCPU上运行的操作系统任务,通过改变操作系统上下文的执行流从ISR上下文和分派通过各自的回调函数为每个uCode注册

  • 传感器节点仿真器任务:它是操作系统的任务执行的SW Instructions-FSM SNC模拟器(见部分5.8。6)并发(不是并行,SNC HW)的系统的操作系统任务。

  • SNC队列:他们是特殊队列用于支持进程间数据交换执行SYSCPU (CM33)上下文和uCodes在SNC上下文中执行。他们实现一个循环缓冲区可以以先进先出的方式进行处理,包括数据的组织块。SNC队列块头(序言和时间戳字段)和身体,在典型情况下,对应于写作或阅读所需的最大内存空间数据交换与SYSCPU流程(例如FreeRTOS任务)SNC uCode时执行。SNC队列所示的结构图65

. . / _images / fig_SNC_5.png

图64结构的多级优先级列表注册PDC事件和uCodes SNC的适配器

. . / _images / fig_SNC_6.png

图65SNC队列的结构

5.8.3.1。初始化SNC适配器

SNC适配器必须初始化之前使用,通过调用<代码class="docutils literal notranslate">ad_snc_init ()API函数。在所有软件适配器的情况下提供的SDK,这是执行初始化系统时升高后,调用<代码class="docutils literal notranslate">pm_system_init ()系统电源管理器组件中实现的函数<代码class="docutils literal notranslate">sys_power_mgr.h c |

函数

描述

ad_snc_init ()

初始化SNC适配器。

更具体地说,当初始化SNC适配器以下执行:

  • 初始化资源,如互斥事件和操作系统使用的队列任务用于SNC适配器实现。

  • 初始化的维护注册PDC事件和SNC uCodes列表。

  • SNC的创建和初始化适配器操作系统任务(见部分5.8.3.2),即传感器节点适配器任务(在其启动SNC-main-uCode创建),传感器节点适配器IRQ的任务传感器节点仿真器任务(如果启用了SNC模拟器-参见5.8。6)。

5.8.3.2。uCodes注册/取消注册

初始化SNC适配器,它准备uCodes登记和取消登记,因此。创建和删除操作系统任务范式后,采用在SDK应用程序实现在SYSCPU执行上下文,可以创建并注册到SNC uCodes PDC事件,这样他们就可以执行特定事件被触发时,或者他们可以从PDC事件未注册和删亚博国际官网平台网址除时不需要任何更多,释放他们的资源。这两个操作提供的API函数<代码class="docutils literal notranslate">ad_snc_ucode_register ()和<代码class="docutils literal notranslate">ad_snc_ucode_unregister (),分别。

函数

描述

ad_snc_ucode_register ()

注册一个uCode-Block PDC事件。

ad_snc_ucode_unregister ()

注销的uCode-Block PDC事件。

注意:uCode ID作为参数传递的是当调用返回<代码class="docutils literal notranslate">ad_snc_ucode_register ()为了注册uCode-Block。

请注意

SNC uCode已经注册,也应该启用为了被执行。因此,后<代码class="docutils literal notranslate">ad_snc_ucode_register (),<代码class="docutils literal notranslate">ad_snc_ucode_enable ()函数应该调用(参见章节5.8.3.3)使uCode执行。

在的情况下注册一个SNC uCode,有必要通过其上下文数据结构的地址(即ucode_ctx),以及它的配置(即cfg)对于PDC事件,触发其执行,PDC事件和uCode优先,如果需要,notifications-to-SYSCPU回调,SNC队列的配置与SYSCPU执行上下文交换数据的过程。关于上下文数据结构的地址,如部分所述5.8.4.2,它是获得使用<代码class="docutils literal notranslate">SNC_UCODE_CTX ()宏当uCode的名称作为参数。这是当一个uCode定义(即启用。<代码class="docutils literal notranslate">SNC_UCODE_BLOCK_DEF ()(即)或声明。<代码class="docutils literal notranslate">SNC_UCODE_BLOCK_DECL ())提供范围内的特定宏观可见。鉴于uCode上下文数据结构的地址,<代码class="docutils literal notranslate">ad_snc_ucode_register ()功能分配,根据配置结构作为参数传递,所有适当的所需的资源控制和操纵uCode SYSCPU和SNC执行上下文,以及与SNC通信队列,如果定义,并最终返回uCode ID分配,以便uCode可惟一地识别。配置结构可能包括以下:

  1. PDC附近地区事件条目(即.pdc_entry):它定义了PDC事件条目添加/注册的PDC附近地区,以便SNC唤醒并执行注册uCode当事件被触发。可以定义使用的条目<代码class="docutils literal notranslate">HW_PDC_LUT_ENTRY_VAL (trig_selecttrig_id,wakeup_master,旗帜)宏(提供<代码class="docutils literal notranslate">hw_pdc.h)。

  2. PDC事件优先级(即.pdc_evt_pr):它定义了PDC事件的优先级将在处理多个事件被触发同时表示,等待相应的PDC事件等待注册SNC(例如PDC_PENDING_SNC_REG)。可以选择AD_SNC_PDC_EVT_PRIORITY枚举值,定义一个PDC事件与优先级1 - 3或无优先级。然而,只能注册一个PDC事件优先级1 - 3,而优先级不能改变当注册类似PDC事件(即相同的触发类型、触发器ID和主人起床),那些已经注册。

  3. uCode优先(即.ucode_pr):它定义的优先级uCode在其余的uCodes注册到一个特定的PDC事件条目,表示到SNC适配器的秩序uCodes必须触发特定PDC事件时调用的方法。可以选择AD_SNC_UCODE_PRIORITY枚举值,定义一个uCode优先级1到15或没有优先级。

  4. 应用程序通知回调(即.cb):它定义了回调被称为从特定uCode发送通知时使用<代码class="docutils literal notranslate">SNC_CM33_NOTIFY ()宏。

  5. SNC-to-CM33和CM33-to-SNC数据交换队列配置(即.snc_to_cm33_queue_cfg和.cm33_to_snc_queue_cfg):配置结构定义SNC / CM33数据交换队列分配给uCode(参见章节5.8.3.55.8.3.6),其起始地址存储在各自uCode上下文数据结构成员snc_ucode_context_t - > SNC_to_CM33_data_queue和snc_ucode_context_t - > CM33_to_SNC_data_queue。属性包含在SNC队列的配置结构如下(也在图66):

    • 最大的块大小(即.max_chunk_bytes):它定义了数据字节的最大大小,可以存储到32位字(uint32_t)一块由SNC队列的元素。块的实际大小是由元素重量。一些填充32位字元素被添加到最后为了处理数据块大小非的倍数为SNC队列定义的元素重量。

    • 数量的块(即.num_of_chunks):它定义了数据块的数量由SNC队列。如果它是等于零,那么任何SNC创建队列。

    • 元素的重量(即.element_weight):它定义了“重量”或大小(以字节为单位)的数据驻留在一个32位字的LSB部分元素由SNC队列数据块,像数据都写在32位字元素的方式,可以由SNC访问。

    • 启用时间戳(即.enable_data_timestamp):如果设置,它使头文件的时间戳数据块由SNC队列。

    • 使CM33推数据的交换(例如.swap_pushed_data_bytes):如果设置,更改数据的字节顺序被推/写CM33执行上下文内CM33-to-SNC队列通过交换数据字节的位置每32位字元素所隐含的元素重量属性(例如.element_weight)。例如,如果一个16位数据字(存储在一个32位的字元素的2 lsb - SNC_QUEUE_ELEMENT_SIZE_HWORD), 0 x00001122年,是写入SNC队列启用交换后,它终于会写0 x00002211年。(典型用例:写入数据,最后通过SPI总线发送使用16或32位SPI字大小模式)。

    • 使突然CM33数据的交换(例如.swap_popped_data_bytes):如果设置,更改数据的字节顺序被打开/阅读CM33执行上下文内SNC-to-CM33队列通过交换数据字节的位置每32位字元素所隐含的元素重量属性(例如.element_weight)。例如,如果一个32位的数据字(存储在一个32位的字元素- SNC_QUEUE_ELEMENT_SIZE_WORD), 0 x11223344从SNC队列,将阅读与交换启用,它最终将被读0 x44332211。(典型用例:读取数据,已收到SPI总线使用16位或32位SPI字大小模式)。

. . / _images / fig_SNC_7.png

图66SNC队列配置属性

示例代码演示注册三个SNC uCodes提出了不同的配置参数代码36

代码36 示例代码注册SNC uCodes
/ / @file foo_header_file_exposing_ucode_1.h/ / @file foo_header_file_exposing_ucode_1.h/ /其他API函数SNC_UCODE_BLOCK_DECL(foo_ucode1);/ /声明foo_ucode1 uCode-Block/ / EOF/ / @file foo_header_file_exposing_ucodes_2and3.h/ /其他API函数SNC_UCODE_BLOCK_DECL(foo_ucode2);/ /声明foo_ucode2 uCode-BlockSNC_UCODE_BLOCK_DECL(foo_ucode3);/ /声明foo_ucode3 uCode-Block/ / EOF/ / @file foo_src_file_registering_ucodes.c# include“foo_header_file_exposing_ucode_1.h”# include“foo_header_file_exposing_ucode_2and3.h”/ / foo_ucode1通知回调无效foo_ucode1_cb(无效){OS_TASK_NOTIFY(OSTask_handling_ucode1_notif,UCODE1_NOTIF,OS_NOTIFY_SET_BITS);}/ / foo_ucode3通知回调无效foo_ucode3_cb(无效){OS_TASK_NOTIFY(OSTask_handling_ucode3_notif,UCODE3_NOTIF,OS_NOTIFY_SET_BITS);}无效foo_func_register_ucodes123(无效){/ /注册foo_ucode1优先2的系统通过SNC适配器,/ / RTC PDC事件条目的优先级为0,发送通知/ / foo_ucode1_cb和不需要任何SNC队列ad_snc_ucode_cfg_tucode1_cfg={pdc_entry=HW_PDC_LUT_ENTRY_VAL(HW_PDC_TRIG_SELECT_PERIPHERAL,HW_PDC_PERIPH_TRIG_ID_RTC_TIMER,HW_PDC_MASTER_SNC,0),pdc_evnt_pr=AD_SNC_PDC_EVT_PR_0,ucode_pr=AD_SNC_UCODE_PR_2,cb=foo_ucode1_cb,};uint32_tfoo_ucode1_id=ad_snc_ucode_register(&ucode1_cfg,SNC_UCODE_CTX(foo_ucode1));/ /在这一点上:/ / uCode列表- > pdc_event_pr_0_list - > foo_ucode1/ /注册foo_ucode2优先2的系统通过SNC适配器,/ / RTC PDC事件条目的优先级与0要求XTAL32M也/ /启用,不发送通知,要求任何SNC队列ad_snc_ucode_cfg_tucode2_cfg={pdc_entry=HW_PDC_LUT_ENTRY_VAL(HW_PDC_TRIG_SELECT_PERIPHERAL,HW_PDC_PERIPH_TRIG_ID_RTC_TIMER,HW_PDC_MASTER_SNC,HW_PDC_LUT_ENTRY_EN_XTAL),pdc_evnt_pr=AD_SNC_PDC_EVT_PR_0,ucode_pr=AD_SNC_UCODE_PR_1,};uint32_tfoo_ucode2_id=ad_snc_ucode_register(&ucode2_cfg,SNC_UCODE_CTX(foo_ucode2));/ /在这一点上:/ / uCode列表- > pdc_event_pr_0_list - > foo_ucode2 - > foo_ucode1/ /注册foo_ucode3优先5的系统通过SNC适配器,/ /为GPIO 0 _17叫醒PDC事件条目与优先级1,发送通知/ /通过foo_ucode3_cb,启用时间戳和一个SNC-to-CM33数据交换/ /队列的4块,块大小40字节,16位数据存储// / 32位字元素和交换时获得SYSCPU执行上下文/ /(即使用ad_snc_queue_pop()函数)ad_snc_ucode_cfg_tucode3_cfg={pdc_entry=HW_PDC_LUT_ENTRY_VAL(HW_GPIO_PORT_0,HW_GPIO_PIN_17,HW_PDC_MASTER_SNC,0),pdc_evnt_pr=AD_SNC_PDC_EVT_PR_1,ucode_pr=AD_SNC_UCODE_PR_5,snc_to_cm33_queue_cfgmax_chunk_bytes=40,snc_to_cm33_queue_cfgnum_of_chunks=4,snc_to_cm33_queue_cfgelement_weight=SNC_QUEUE_ELEMENT_SIZE_HWORD,snc_to_cm33_queue_cfgenable_data_timestamp=真正的,snc_to_cm33_queue_cfgswap_popped_data_bytes=真正的,};uint32_tfoo_ucode3_id=ad_snc_ucode_register(&ucode3_cfg,SNC_UCODE_CTX(foo_ucode3));/ /在这一点上:/ / uCode列表- > pdc_event_pr_1_list - > foo_ucode3/ / pdc_event_pr_0_list - > foo_ucode2 - > foo_ucode1}/ / EOF

至于注册uCode时正在执行的操作,可以确定以下步骤:

  1. uCode注册请求发送到传感器节点适配器任务uCode上下文和所需的配置。

  2. uCode配置参数进行验证:

    • 如果无效的配置参数值传递或注册uCodes的最大数量已经达到或每优先PDC事件的最大数量已经达到,AD_SNC_INVALID_UCODE_ID返回。

  3. SNC队列为应用程序创建与特定uCode通信,基于给定的配置。

  4. uCode的构造函数被调用时,分配适当的内存空间,初始化uCode上下文数据结构,构建SeNIS-based C预处理器宏定义的代码结构(部分中描述5.8。5)产生SeNIS命令并存储到内存空间。本质上调用构造函数三次,每次应用不同的“构建上下文”,如下:

    1. 计算所需的内存空间大小用于确定uCode地址定义的标签(即当使用<代码class="docutils literal notranslate">SENIS_label ()构建宏观参见5.8。5)指uCode实现。

    2. uCode标签的内存分配和决心,以及计算所需的内存空间大小uCode将存储。

    3. 内存分配和uCode的创造。

  5. SNC-main-uCode停止,列表更新注册PDC事件和uCodes因此,最后呢SNC-main-uCode再次恢复,现在访问更新PDC事件条目和uCodes处理列表。

另一方面,当取消注册一个SNC uCode只,有必要通过uCode ID返回注册uCode时,即当调用<代码class="docutils literal notranslate">ad_snc_register_ucode ()函数。SNC适配器搜索特定uCode uCode列表中的条目的基础上提供uCode ID,它消除了uCode条目,如果最后没有任何相应的PDC事件条目uCode条目,PDC事件条目被删除。一个示例代码演示的注册和可以SNC uCode提出了代码37(扩展的例子代码36)。正在执行的操作,当取消注册uCode可以概括如下:

  1. SNC-main-uCode是停止的。

  2. uCode从uCode列表中删除。

  3. 特定的PDC事件条目uCode登记,从uCode列表中删除如果没有其他uCodes离开了那个注册PDC事件条目,否则相应更新,所以,它可以包括由剩余uCodes所需的旗帜。

  4. 任何等待为特定uCode CM33-to-SNC通知被清除。

  5. SNC-main-uCode又恢复了。

  6. uCode的析构函数被调用时,其分配的资源可以被释放。

  7. SNC队列(如果有的话)的uCode也被删除。

代码37 SNC uCode示例代码注册和取消注册
/ / @file foo_header_file_exposing_ucode_4.h/ /其他API函数SNC_UCODE_BLOCK_DECL(foo_ucode4);/ /声明foo_ucode4 uCode-Block/ / EOF/ / @file foo_src_file_registering_ucodes.c# include“foo_header_file_exposing_ucode_4.h”_SNC_RETAINED静态uint32_tfoo_ucode4_id;无效foo_func_register_ucode4(无效){/ /假设foo_func_register_ucodes123()被称为/ /在这一点上:/ / uCode列表- > pdc_event_pr_1_list - > foo_ucode3/ / pdc_event_pr_0_list - > foo_ucode2 - > foo_ucode1/ /注册foo_ucode4优先1系统通过SNC适配器,/ / RTC PDC事件条目与优先级3(它最后被忽视,因为/ /已经定义的优先级为0),没有发送通知和要求/ /任何SNC队列ad_snc_ucode_cfg_tucode4_cfg={pdc_entry=HW_PDC_LUT_ENTRY_VAL(HW_PDC_TRIG_SELECT_PERIPHERAL,HW_PDC_PERIPH_TRIG_ID_RTC_TIMER,HW_PDC_MASTER_SNC,0),pdc_evnt_pr=AD_SNC_PDC_EVT_PR_3,ucode_pr=AD_SNC_UCODE_PR_1,};foo_ucode4_id=ad_snc_ucode_register(&ucode4_cfg,SNC_UCODE_CTX(foo_ucode4));/ /在这一点上:/ / uCode列表- > pdc_event_pr_1_list - > foo_ucode3/ / pdc_event_pr_0_list - > foo_ucode2 - > foo_ucode4 - > foo_ucode1}boolfoo_func_unregister_ucode4(无效){返回ad_snc_ucode_unregister(foo_ucode4_id);/ /在这一点上:/ / uCode列表- > pdc_event_pr_1_list - > foo_ucode3/ / pdc_event_pr_0_list - > foo_ucode2 - > foo_ucode1}/ / EOF

5.8.3.3。启用/禁用uCodes

当注册一个SNC uCode,它最初是禁用的。这意味着,即使触发相应的PDC事件,SNC执行流不是通过特定的SNC uCode驱动。

为了控制执行注册SNC uCode,提供了两个API函数,即<代码class="docutils literal notranslate">ad_snc_ucode_enable ()和<代码class="docutils literal notranslate">ad_snc_ucode_disable (),允许启用和禁用SNC uCode执行,分别。

函数

描述

ad_snc_ucode_enable ()

使uCode执行。

ad_snc_ucode_disable ()

禁用uCode执行。

5.8.3.4。通知,从uCodes接收通知

SNC uCodes可以被视为并行任务的并发操作系统任务(例如FreeRTOS任务)中执行SYSCPU (CM33)上下文。因此,SNC编程框架扩展了通知操作系统之间交换任务还通知操作系统之间交换任务和SNC uCodes统一。

为了支持SNC-to-CM33通知,因为它已经在前面部分提到的,一个回调函数(即ad_snc_ucode_cfg_t - > cb)为每个注册uCode提供。时调用的回调<代码class="docutils literal notranslate">SNC_CM33_NOTIFY ()叫做SNC执行上下文的uCode,显示相似之处<代码class="docutils literal notranslate">OS_TASK_NOTIFY ()宏定义的操作系统抽象层API(即。<代码class="docutils literal notranslate">osal.h)通知对方操作系统任务。更具体地说,传感器节点适配器IRQ的任务处理uCodes发送的通知,因此处理在特定的回调函数必须保持短(即只使用一个<代码class="docutils literal notranslate">OS_TASK_NOTIFY ()宏,它将通知发送到目标操作系统任务,相应的),所以相对较小的堆栈的大小不能超过任务。

在相反的方向,因为SNC uCodes PDC事件被触发时,执行通知可以发送从一个操作系统任务的SNC uCode force-triggering PDC事件uCode注册。这是当调用SNC适配器执行API函数<代码class="docutils literal notranslate">ad_snc_pdc_set_pending ()返回作为参数uCode ID注册uCode时,并触发相应的PDC PDC附近地区事件条目,因此。不过,考虑到这一事实可以注册多个SNC uCodes相同的PDC或PDC也可以触发事件源是相关(例如GPIO、定时器等),一个SNC API可以使用宏(通常是第一个语句)uCodes的实现,即<代码class="docutils literal notranslate">SNC_CHECK_CM33_NOTIF_PENDING ()可以发现,这种CM33-to-SNC通知和每个uCode返回或继续执行,因此。

函数

描述

ad_snc_pdc_set_pending ()

设置一个PDC事件条目,一个uCode已经注册为悬而未决。

注意:它将force-trigger执行所有uCodes注册PDC事件被设置为等待。<代码class="docutils literal notranslate">SNC_CHECK_CM33_NOTIF_PENDING ()宏函数可用于SNC执行上下文,以检查是否隐含目标特定uCode通知。

说明上述过程由SNC / CM33通知交流机制提出了图67

. . / _images / fig_SNC_8.png

图67通知操作系统任务和SNC uCode之间的交换

5.8.3.5。推动数据uCode CM33-to-SNC队列

在SYSCPU执行上下文,以推动一个特定大小的数据CM33-to-SNC队列定义的一个uCode uCode ID,并添加一个时间戳,意味着一些时间陪他们当他们处理,亚博全网<代码class="docutils literal notranslate">ad_snc_queue_push ()可以使用函数。事实上,自从SNC队列组织块,每次<代码class="docutils literal notranslate">ad_snc_queue_push ()函数被调用时,给定的数据将被写入下一个可用的免费/块,导致“部分”空SNC队列中的每个块数据存储在给定的数据大小小于最大一块定义SNC队列的配置(即注册uCode时,设置属性snc_queue_config_t - > max_chunk_bytes)。另一方面,如果给定的大小大于最大的块大小,函数返回“false”。同样的如果SNC队列已满,没有空闲块写入数据,SNC队列的状态当调用返回<代码class="docutils literal notranslate">ad_snc_queue_is_full ()函数(参见5.8.3.7)。

函数

函数

ad_snc_queue_push ()

数据推送到uCode-Block CM33-to-SNC队列。

关于时间戳属性,如果启用了时间戳在SNC队列配置(即snc_queue_config_t - > enable_data_timestamp = true),然后一段时间参考价值可以添加到各自的头字段中的数据块写入SNC队列。时间戳可以是捕获的事件在时间价值GPIO(使用hw_timer_get_capture[1 | 2 | 3 | 4]()函数<代码class="docutils literal notranslate">hw_timer.h(使用)或一个RTC的时间价值<代码class="docutils literal notranslate">hw_rtc_get_time_bcd ()函数<代码class="docutils literal notranslate">hw_rtc.h),甚至一个简单的计数器值。

最后,要推到SNC队列的数据是“打开”和“交换”存储块的32位字由SNC访问元素,元素重量的基础上(即snc_queue_config_t - > element_weight)和相应的指示交换数据(即snc_queue_config_t - > swap_pushed_data_bytes),分别配置为SNC的队列在注册uCode时。更具体地说,假设一个特定的字节数推到uCode的CM33-to-SNC队列,SNC队列最后写的是什么重量块基于配置的元素呈现如下:

  • 如果所选元素的重量是1字节(例如SNC_QUEUE_ELEMENT_SIZE_BYTE),然后每个字节存储到另一个32位的字块元素。

  • 如果所选元素的重量是2字节(例如SNC_QUEUE_ELEMENT_SIZE_HWORD),然后每组2字节存储到另一个32位的字块元素,如果字节的总数不是2的倍数最后一个字节存储在一个单独的32位字元素。

  • 如果所选元素的重量是4字节(例如SNC_QUEUE_ELEMENT_SIZE_WORD),然后每组4个字节存储到另一个32位的字块元素,如果字节的总数不是4的倍数,最后一个字节存储在一个单独的32位字元素。

如果交换也启用,然后把数据也改变了之前的字节顺序存储在一个32位的字元素,通过交换书面字节lsb。具有代表性的例子是什么最后数据存储到一个SNC队列当推到它的块重量所示为不同的配置元素图68,而一些典型使用情况并给出了特定的API函数38码

. . / _images / fig_SNC_9.png

图68uCode CM33-to-SNC队列数据表示当推CM33上下文中的数据

38码 示例代码将数据uCode CM33-to-SNC队列在CM33上下文
/ / @file foo_header_file_exposing_ucodes.h/ /其他API函数SNC_UCODE_BLOCK_DECL(foo_ucode1);/ /声明foo_ucode1 uCode-BlockSNC_UCODE_BLOCK_DECL(foo_ucode2);/ /声明foo_ucode2 uCode-Block/ / EOF/ / @file foo_src_file_pushing_data_to_ucode_CM33toSNC_queues.c# include“foo_header_file_exposing_ucodes.h”_SNC_RETAINED静态uint32_tfoo_ucode1_id;_SNC_RETAINED静态uint32_tfoo_ucode2_id;无效foo_func_register_ucodes(无效){/ /初始化uCodes/ /注册foo_ucode1系统通过SNC适配器,CM33-to-SNC/ /数据交换队列3块,启用了时间戳,块大小/ / 4字节,16位数据存储/ 32位字元素,而不是交换/ /当SNC队列存储块在SYSCPU执行上下文(即使用/ / ad_snc_queue_push()函数)ad_snc_ucode_cfg_tucode1_cfg={/ /其他的配置参数cm33_to_snc_queue_cfgmax_chunk_bytes=4,cm33_to_snc_queue_cfgnum_of_chunks=3,cm33_to_snc_queue_cfgelement_weight=SNC_QUEUE_ELEMENT_SIZE_HWORD,cm33_to_snc_queue_cfgenable_data_timestamp=真正的,cm33_to_snc_queue_cfgswap_pushed_data_bytes=,};uint32_tfoo_ucode1_id=ad_snc_ucode_register(&ucode1_cfg,SNC_UCODE_CTX(foo_ucode1));/ /注册foo_ucode2系统通过SNC适配器,CM33-to-SNC/ /数据交换队列2块,时间戳残疾和块大小/ / 11字节,其中32位数据存储/ 32位字元素,和交换/ /当SNC队列存储块在SYSCPU执行上下文(即使用/ / ad_snc_queue_push()函数)ad_snc_ucode_cfg_tucode2_cfg={/ /其他的配置参数cm33_to_snc_queue_cfgmax_chunk_bytes=11,cm33_to_snc_queue_cfgnum_of_chunks=2,cm33_to_snc_queue_cfgelement_weight=SNC_QUEUE_ELEMENT_SIZE_WORD,cm33_to_snc_queue_cfgenable_data_timestamp=,cm33_to_snc_queue_cfgswap_pushed_data_bytes=真正的,};uint32_tfoo_ucode2_id=ad_snc_ucode_register(&ucode2_cfg,SNC_UCODE_CTX(foo_ucode2));/ /在这一点上:/ / SNC_UCODE_CTX (foo_ucode1) - > CM33_to_SNC_data_queue - >/ /(免费)块[0]- > 0(时间戳){0}/ /块(免费)[1]- > 0(时间戳){0}/ /块(免费)[2]- > 0(时间戳){0}/ / SNC_UCODE_CTX (foo_ucode2) - > CM33_to_SNC_data_queue - >/ /(免费)块[0]- >{0,0,0,0(填充),0(垫)}/ /块(免费)[1]- >{0,0,0,0(填充),0(垫)}/ /启用foo_ucode1ad_snc_ucode_enable(foo_ucode1_id);/ /启用foo_ucode2ad_snc_ucode_enable(foo_ucode2_id);}_SNC_RETAINED静态uint16_tdata_to_ucode1[]={0 x0201,0 x0403,0 x0605};_SNC_RETAINED静态uint8_tdata_to_ucode2[]={0 x01,0 x02,0 x03,0 x04,0 x05,0 x06,0 x07,(,0 x09,0 x0a,0 x0b,0 x11,0 x12,0 * 13,0 x14,0连接,0 x16,0 x17,0 x18,0 x19,0 x1a,0 x1b};无效foo_FreeRTOS_task_func()/ /定义FreeRTOS任务的功能/ / foo_ucode1和foo_ucode2交流{foo_func_register_ucodes();/ /初始化uCodes注册(,){/ /推的第一个2字节data_to_ucode1 foo_ucode1 CM33-to-SNC队列/ /设置时间戳为1ad_snc_queue_push(foo_ucode1_id,(uint8_t*)&data_to_ucode1(0),2,1);/ /在这一点上:/ / SNC_UCODE_CTX (foo_ucode1) - > CM33_to_SNC_data_queue - >/ /(书面)块[0]- > 1(时间戳){0 x00000201, 0}/ /块(免费)[1]- > 0(时间戳){0}/ /块(免费)[2]- > 0(时间戳){0}/ /推下一个4字节的data_to_ucode1 foo_ucode1 CM33-to-SNC队列/ /设置时间戳2ad_snc_queue_push(foo_ucode1_id,(uint8_t*)&data_to_ucode1(1),4,2);/ /在这一点上:/ / SNC_UCODE_CTX (foo_ucode1) - > CM33_to_SNC_data_queue - >/ /(书面)块[0]- > 1(时间戳){0 x00000201, 0}/ /(书面)[1]- > 2块(时间戳){0 x00000403, 0 x00000605}/ /块(免费)[2]- > 0(时间戳){0}/ /把第一个9字节的data_to_ucode2 foo_ucode2 CM33-to-SNC队列中ad_snc_queue_push(foo_ucode2_id,(uint8_t*)&data_to_ucode2(0),9,0);/ /在这一点上:/ / SNC_UCODE_CTX (foo_ucode2) - > CM33_to_SNC_data_queue - >/ /(书面)块[0]- > {0 x01020304 0 x05060708 0 x00000009, 0, 0}/ /块(免费)[1]- > {0}/ /推下一个7字节的data_to_ucode2 foo_ucode2 CM33-to-SNC队列ad_snc_queue_push(foo_ucode2_id,(uint8_t*)&data_to_ucode2(9),7,0);/ /在这一点上:/ / SNC_UCODE_CTX (foo_ucode2) - > CM33_to_SNC_data_queue - >/ /(书面)块[0]- > {0 x01020304 0 x05060708 0 x00000009, 0, 0}/ /块(书面)[1]- > {0 x0a0b1112, 0 x00000013 0 x00000014 0 x00000015, 0}}}/ / EOF

5.8.3.6。弹出数据从uCode SNC-to-CM33队列

在SYSCPU执行上下文,以流行uCode SNC-to-CM33队列的存储的数据定义为给定uCode ID,获取它们的大小和时间戳,可以陪他们,亚博全网<代码class="docutils literal notranslate">ad_snc_queue_pop ()可以使用函数。事实上,自从SNC队列组织块,每次<代码class="docutils literal notranslate">ad_snc_queue_pop ()函数被调用时,给定的数据将被读取下一块写数据,而他们大小的字节(最大值等于snc_queue_config_t - > max_chunk_bytes),表示在块头,将返回/存储地址所示尺寸参数。如果没有块以书面数据,函数返回“false”, SNC队列的状态也当调用返回<代码class="docutils literal notranslate">ad_snc_queue_is_empty ()函数(参见5.8.3.7)。

函数

描述

ad_snc_queue_pop ()

流行的数据从uCode-Block SNC-to-CM33队列。

关于时间戳属性,如果启用了时间戳在SNC队列配置(即snc_queue_config_t - > enable_data_timestamp = true),然后各自的参考价值存储的时间头字段的数据块从SNC队列读取返回并相应处理。

最后,存储的数据由SNC成块的32位字元素“包装”和“交换”当复制/弹出地址表示通过给定的数据参数,基于元素重量(即snc_queue_config_t - > element_weight)和相应的信号交换出现数据(即snc_queue_config_t - > swap_popped_data_bytes),分别配置为SNC的队列在注册uCode时。更具体地说,假设一个特定的字节数从一块出现在uCode SNC-to-CM33队列,终于从SNC队列读取和存储给定数据地址参数提出了基于配置的元素重量如下:

  • 如果所选元素的重量是1字节(例如SNC_QUEUE_ELEMENT_SIZE_BYTE),然后从每个32位字元素读取LSB的一块并存储到下一个目的地缓冲区的字节所暗示的给定数据处理参数。

  • 如果所选元素的重量是2字节(例如SNC_QUEUE_ELEMENT_SIZE_HWORD),然后两个lsb读取每一个32位的字块元素和存储到下一个目的地的2个字节缓冲区。在块的字节总数不是2的倍数最后一个字节存储在一个单独的32位字元素,因此只有LSB读取和存储到下一个目的地缓冲区的字节。

  • 如果所选元素的重量是4字节(例如SNC_QUEUE_ELEMENT_SIZE_WORD),那么所有四个字节读取从每个32位字块元素和存储到下一个目的地缓冲区的4个字节。在块的字节总数不是4的倍数最后一个字节存储到一个单独的32位字元素,因此只有LSB读取每一个32位的字元素和存储到下一个目的地缓冲区的字节。

如果交换也启用,然后弹出数据也改变了之前的字节顺序存储到目的地缓冲区,通过交换lsb每个阅读的32位字SNC队列中的元素。最后的一个代表性的例子从一个SNC队列读取并存储到目的地从SNC队列缓冲区当弹出数据块重量所示为不同的配置元素图69,而一些典型使用情况并给出了特定的API函数39码

. . / _images / fig_SNC_10.png

图69弹出数据表示在目的地缓冲区的数据uCode SNC-to-CM33队列在CM33上下文

39码 示例代码弹出数据从uCode SNC-to-CM33队列在CM33上下文
/ / @file foo_header_file_exposing_ucodes.h/ /其他API函数SNC_UCODE_BLOCK_DECL(foo_ucode1);/ /声明foo_ucode1 uCode-BlockSNC_UCODE_BLOCK_DECL(foo_ucode2);/ /声明foo_ucode2 uCode-Block/ / EOF/ / @file foo_src_file_popping_data_from_ucode_SNCtoCM33_queues.c# include“foo_header_file_exposing_ucodes.h”_SNC_RETAINED静态uint32_tfoo_ucode1_id;_SNC_RETAINED静态uint32_tfoo_ucode2_id;无效foo_func_register_ucodes(无效){/ /初始化uCodes/ /注册foo_ucode1系统通过SNC适配器,SNC-to-CM33/ /数据交换队列3块,启用了时间戳,块大小/ / 4字节,8位数据存储/ 32位字元素,而不是交换/ /当从SNC队列读取块SYSCPU执行上下文(即使用/ / ad_snc_queue_pop()函数)ad_snc_ucode_cfg_tucode1_cfg={/ /其他的配置参数snc_to_cm33_queue_cfgmax_chunk_bytes=4,snc_to_cm33_queue_cfgnum_of_chunks=3,snc_to_cm33_queue_cfgelement_weight=SNC_QUEUE_ELEMENT_SIZE_BYTE,snc_to_cm33_queue_cfgenable_data_timestamp=真正的,snc_to_cm33_queue_cfgswap_popped_data_bytes=,};uint32_tfoo_ucode1_id=ad_snc_ucode_register(&ucode1_cfg,SNC_UCODE_CTX(foo_ucode1));/ /注册foo_ucode2系统通过SNC适配器,SNC-to-CM33/ /数据交换队列2块,时间戳残疾和块大小/ / 12字节,其中32位数据存储/ 32位字元素,和交换/ /当从SNC队列读取块SYSCPU执行上下文(即使用/ / ad_snc_queue_pop()函数)ad_snc_ucode_cfg_tucode2_cfg={/ /其他的配置参数snc_to_cm33_queue_cfgmax_chunk_bytes=12,snc_to_cm33_queue_cfgnum_of_chunks=2,snc_to_cm33_queue_cfgelement_weight=SNC_QUEUE_ELEMENT_SIZE_WORD,snc_to_cm33_queue_cfgenable_data_timestamp=,snc_to_cm33_queue_cfgswap_poppped_data_bytes=真正的,};uint32_tfoo_ucode2_id=ad_snc_ucode_register(&ucode2_cfg,SNC_UCODE_CTX(foo_ucode2));/ /启用foo_ucode1ad_snc_ucode_enable(foo_ucode1_id);/ /启用foo_ucode2ad_snc_ucode_enable(foo_ucode2_id);}_SNC_RETAINED静态结构体{uint32_t时间戳;uint32_t大小;uint16_t数据(2];}data_from_ucode1(3]={0};/ /定义data_from_ucode1目的地缓冲区_SNC_RETAINED静态结构体{uint32_t大小;uint32_t数据(3];}data_from_ucode2(3]={0};/ /定义data_from_ucode2目的地缓冲区无效foo_FreeRTOS_task_func()/ /定义FreeRTOS任务的功能/ / foo_ucode1和foo_ucode2交流{foo_func_register_ucodes();/ /初始化uCodes注册(,){/ /假设此时SNC uCodes SNC-to-CM33队列存储数据:/ / SNC_UCODE_CTX (foo_ucode1) - > SNC_to_CM33_data_queue - >/ /(书面)块[0]- > 1(时间戳){0 x00000001 0 x00000002 0 x00000003, 0}/ /(书面)[1]- > 2块(时间戳){0 x00000004 0 x00000005, 0, 0}/ /块(免费)[2]- > 0(时间戳){0,0,0,0}/ / SNC_UCODE_CTX (foo_ucode2) - > SNC_to_CM33_data_queue - >/ /(书面)块[0]- > {0 x01020304 0 x05060708 0 x00000009, 0, 0}/ /块(书面)[1]- > {0 x10111213, 0 x00000014 0 x00000015 0 x00000016, 0}/ /流行的第一块foo_ucode1 SNC-to-CM33队列和商店/ / data_from_ucode1,也获得其大小和时间戳ad_snc_queue_pop(foo_ucode1_id,(uint8_t*)&data_from_ucode1(0]- >数据,&data_from_ucode1(0]- >大小,&data_from_ucode1(0]- >时间戳);/ /在这一点上:/ / SNC_UCODE_CTX (foo_ucode1) - > SNC_to_CM33_data_queue - >/ /(免费)[0]- > 1块(时间戳){0 x00000001 0 x00000002 0 x00000003, 0}/ /(书面)[1]- > 2块(时间戳){0 x00000004 0 x00000005, 0, 0}/ /块(免费)[2]- > 0(时间戳){0,0,0,0}/ // / data_from_ucode1 [0] - > {1, 3, {0 x0201, 0 x0003}}/ / data_from_ucode1 [1] - > {0, 0, {0}}/ / data_from_ucode1 [2] - > {0, 0, {0}}/ /流行的下一块foo_ucode1 SNC-to-CM33队列和商店/ / data_from_ucode1,也获得其大小和时间戳ad_snc_queue_pop(foo_ucode1_id,(uint8_t*)&data_from_ucode1(1]- >数据,&data_from_ucode1(1]- >大小,&data_from_ucode1(1]- >时间戳);/ /在这一点上:/ / SNC_UCODE_CTX (foo_ucode1) - > SNC_to_CM33_data_queue - >/ /(免费)[0]- > 1块(时间戳){0 x00000001 0 x00000002 0 x00000003, 0}/ /(免费)[1]- > 2块(时间戳){0 x00000004 0 x00000005, 0, 0}/ /块(免费)[2]- > 0(时间戳){0,0,0,0}/ // / data_from_ucode1 [0] - > {1, 3, {0 x0201, 0 x0003}}/ / data_from_ucode1 [1] - > {2, 2, {0 x0504, 0}}/ / data_from_ucode1 [2] - > {0, 0, {0}}/ /流行的第一块foo_ucode2 SNC-to-CM33队列和商店/ / data_from_ucode2,也获得它的大小ad_snc_queue_pop(foo_ucode2_id,(uint8_t*)&data_to_ucode2(0]- >数据,&data_from_ucode2(0]- >大小,);/ /在这一点上:/ / SNC_UCODE_CTX (foo_ucode1) - > SNC_to_CM33_data_queue - >/ /(免费)块[0]- > {0 x01020304 0 x05060708 0 x00000009, 0, 0}/ /块(书面)[1]- > {0 x10111213, 0 x00000014 0 x00000015 0 x00000016, 0}/ // / data_from_ucode2[0] - >{9日{0 x04030201 0 x08070605 0 x00000009}}/ / data_from_ucode2 [1] - > {0, {0, 0, 0}}/ / data_from_ucode2 [2] - > {0, {0, 0, 0}}/ /流行的下一块foo_ucode2 SNC-to-CM33队列和商店/ / data_from_ucode2,也获得它的大小ad_snc_queue_pop(foo_ucode2_id,(uint8_t*)&data_to_ucode2(1]- >数据,&data_from_ucode2(1]- >大小,);/ /在这一点上:/ / SNC_UCODE_CTX (foo_ucode1) - > SNC_to_CM33_data_queue - >/ /(免费)块[0]- > {0 x01020304 0 x05060708 0 x00000009, 0, 0}/ /块(免费)[1]- > {0 x10111213, 0 x00000014 0 x00000015 0 x00000016, 0}/ // / data_from_ucode2[0] - >{9日{0 x04030201 0 x08070605 0 x00000009}}/ / data_from_ucode2 [1] - > {7, {0 x12121110 0 x00161514, 0}}/ / data_from_ucode2 [2] - > {0, {0, 0, 0}}}}/ / EOF

5.8.3.7。获得的地位uCode SNC队列

SYSCPU执行上下文,以便检查SNC-to-CM33队列的状态或CM33-to-SNC队列定义的一个uCode uCode ID,并相应地进行操作与推动或队列的数据,提供了一组API函数:

函数

描述

ad_snc_queue_is_empty ()

检查是否uCode-Block SNC-to-CM33队列或CM33-to-SNC队列是空的。

ad_snc_queue_is_full ()

检查是否uCode-Block SNC-to-CM33队列或CM33-to-SNC队列已满。

ad_snc_queue_get_free_chunks ()

返回的数量免费(不写/分配)块在uCode-Block SNC-to-CM33队列或CM33-to-SNC队列。

ad_snc_queue_get_alloc_chunks ()

返回的数量分配(书面)块在uCode-Block SNC-to-CM33队列或CM33-to-SNC队列。

ad_snc_queue_get_cur_chunk_bytes ()

返回当前块的字节数(即下一个破灭)uCode-Block SNC-to-CM33的队列或CM33-to-SNC队列。

更具体地说:

  • 为了检查如果SNC队列例如之前出现一块从一个SNC-to-CM33队列通过调用<代码class="docutils literal notranslate">ad_snc_queue_pop ()函数,<代码class="docutils literal notranslate">ad_snc_queue_is_empty ()可以使用函数。SNC队列为空时,还没有写块(或下一块尚未写阅读,所隐含的底层实现)。

  • 为了检查如果SNC队列完整的之前,例如将数据通过调用CM33-to-SNC队列<代码class="docutils literal notranslate">ad_snc_queue_push ()函数,<代码class="docutils literal notranslate">ad_snc_queue_is_full ()可以使用函数。SNC队列满时的所有块SNC队列已经书面(或下一块写已经写好,目前所隐含的底层实现)。

  • 以阅读的数量空闲块SNC的队列,例如之前推动多次在不同的块CM33-to-SNC队列的数据调用<代码class="docutils literal notranslate">ad_snc_queue_push ()函数,<代码class="docutils literal notranslate">ad_snc_queue_get_free_chunks ()可以使用函数。作为自由块被认为是块尚未编写。

  • 以阅读的数量分配/写块例如在SNC队列,在砰的一声从一个SNC-to-CM33队列通过调用多个块<代码class="docutils literal notranslate">ad_snc_queue_pop ()函数,<代码class="docutils literal notranslate">ad_snc_queue_get_alloc_chunks ()可以使用函数。作为分配的块被认为是一个块被写。

  • 以阅读的数量字节写在下一块出现SNC的队列,例如分配适当的内存空间目标缓冲区之前出现一块从一个SNC-to-CM33队列通过调用<代码class="docutils literal notranslate">ad_snc_queue_pop ()函数,<代码class="docutils literal notranslate">ad_snc_queue_get_cur_chunk_bytes ()可以使用函数。像当前块被认为是下一个块突然从一个SNC队列。

5.8.4。添加uCodes CM33-SNC应用程序亚博国际官网平台网址

底层SeNIS-based uCodes编程框架定义了三种不同的类型,对应于三个不同的“uCode角色”实现总的逻辑被SNC上执行。一般而言,当开发相结合的应用程序/扩展到SYSCPU和SNC执行上下文,亚博国际官网平台网址只有uCode-Block使用角色,而另两个角色(例如Function-uCode和SNC-main-uCode)主要应用在底层SNC系统架构实现机制相关调度uCodes执行,驱动系统外围设备(例如SPI, I2C)之间交换通知SYSCPU SNC,等等。

关于uCodes通常由一个应用程序,以下指的是他们uCode-BlocksSNC uCodes或者只是uCodes, SNC上运行的小程序,使用列表实现SeNIS-based C预处理器结构,如后所述部分,有特殊的“属性”,它们的执行是耦合的,可以引发的PDC事件(例如GPIO,计时器,RTC等等),他们已经通过SNC适配器注册,如前所述5.8.3.2。从本质上讲,他们构成了起点的执行相关的操作到一个特定的事件,要在SNC执行,因此一起产生的总行为SNC对内部资源的控制和操纵和外围设备和传感器驱动/由SNC访问。

5.8.4.1。定义一个uCode

每个uCode-Block都有一个惟一的uCode ID,这是产生在其登记系统通过SNC适配器,入站和出站通知从/到SYSCPU支持,并使用一个预定义的数据交换与SYSCPU机制基于入站和出站数据实施循环缓冲区和典型的FIFO队列操作功能,如部分所示5.8。3。为了定义一个uCode-Block及其相应的SNC执行上下文,它是由一系列SeNIS命令存储在RAM中,以及数据结构由特定的命令和其他的系统支持SNC uCode集成在一个SYSCPU-SNC执行上下文相结合,必须使用一个C预处理器宏,叫做<代码class="docutils literal notranslate">SNC_UCODE_BLOCK_DEF (),uCode-Block的名称作为参数传递。所示代码40块内,花括号(即“{…}”)定义这种macro-functions之后,uCode的实现可以定义使用SeNIS-based C宏观结构(部分5.8。5)。

代码40 SNC uCode-Block定义
SNC_UCODE_BLOCK_DEF(foo_ucode)/ /定义foo_ucode uCode-Block{/ / uCode实现- SeNIS-based语句}

5.8.4.2。声明和引用uCode

为了参考uCode在不同的上下文中对它的定义范围(当使用<代码class="docutils literal notranslate">SNC_UCODE_BLOCK_DEF ()宏定义),它可以使用另一个宏函数由SNC提供编程框架,调用<代码class="docutils literal notranslate">SNC_UCODE_BLOCK_DECL ()定义,从本质上说,宣布uCode上下文。提供uCode声明是必要的(例如,在一个头文件,通过它的上下文uCode公开)的典型用例中uCode需要注册到系统通过SNC适配器,允许使用<代码class="docutils literal notranslate">SNC_UCODE_CTX ()宏获取uCode的背景下,提出了部分5.8.3.2和演示代码41

代码41 SNC uCode-Block宣言和上下文参考
/ / @file foo_header_file_exposing_ucode_ctx.h/ /其他API函数SNC_UCODE_BLOCK_DECL(foo_ucode);/ /声明foo_ucode uCode-Block/ / EOF/ / @file foo_src_file_registering_ucode.c/ /某个地方,在一个具体的实现:/ /注册foo_ucode系统通过与给定的SNC适配器/ /配置(即foo_ucode_cfg)uint32_tfoo_ucode_id=ad_snc_ucode_register(&foo_ucode_cfg,SNC_UCODE_CTX(foo_ucode));/ / EOF

5.8.5。传感器节点控制器软件开发工具包

5.8.5.1。SeNIS-based语言结构

如前面的小节所述,SNC是一个复杂的硬件状态机实现一个非常短的指令列表,然而相当足够的用于创建小程序解决典型操作相关传感器和外围设备控制和数据采集。特定的指令集促进assembly-way-of-thinking /编程,通过介绍典型的装配操作相关:

  • 复制内存和寄存器地址内容(WADAD)

  • 写内存和寄存器地址内容(WADVA)

  • 基于一个条件设置标志(RDCBI和RDCGR)

  • 执行算术和位操作(公司和TOBRE)

  • 分支(COBR)

基于SNC指令集(SeNIS), SNC编程框架提供了一组编程构造创建uCodes。他们中的一些人直接使用SeNIS提供一种方便的方法,和其他一些提供更高级别的c的一组操作。

所有的这些SeNIS-based语言结构提供了<代码class="docutils literal notranslate">SeNIS.h和<代码class="docutils literal notranslate">snc.h头文件,它必须包括为了实现一个程序执行在SNC (uCode)。

更多细节关于使用这些结构中可以找到(Ref_04)

一个例子uCode使用SeNIS-based语言结构和相应的“等效”实现使用C语言结构所示代码4243码分别呈现的概述如何使用特定的开发uCode SeNIS-based编程框架。

代码42 例子SNC uCode使用SeNIS-based语言结构
uint32_tfoo_var1=0;/ /定义变量foo_var1uint32_tfoo_buffer(10];/ /定义数组foo_bufferuint32_t*foo_var2_ptr;/ /定义变量foo_var2_ptruint32_tinRangeAndLTmax;/ /定义变量inRangeAndLTmax#定义MAX_THRESHOLD_VALUE 300/ /最大阈值的定义#定义MIN_THRESHOLD_VALUE 100/ /最小阈值的定义SNC_UCODE_BLOCK_DEF(foo_ucode)/ /定义foo_ucode uCode-Block{/ /写一个值(即假)inRangeAndLTmax变量SENIS_assign((&inRangeAndLTmax),);/ /写一个值(例如5)foo_var1变量SENIS_assign((&foo_var1),5);/ /写一个值(即第六foo_buffer数组元素的地址)/ / foo_var2_ptr变量SENIS_assign((&foo_var2_ptr),&foo_buffer(5]);/ /当foo_var1小于(<)10日…SENIS_while((&foo_var1),LT,10){/ /增加foo_var1 1,……SENIS_inc1((&foo_var1));/ /如果该值由foo_var2_ptr foo_buffer指出元素的数组/ /变量大于或等于MAX_THRESHOLD_VALUE (“> =”),…SENIS_if(ia(&foo_var2_ptr),GTEQ,MAX_THRESHOLD_VALUE){/ /然后写假inRangeAndLTmax……SENIS_assign((&inRangeAndLTmax),);/ /打破while循环,…SENIS_break;/ /否则,…SENIS_else{/ /如果指出元素中的值小于(<)/ / MIN_THRESHOLD_VALUE,……SENIS_if(ia(&foo_var2_ptr),LT,MIN_THRESHOLD_VALUE){/ /继续下一个元素SENIS_inc4((&foo_var2_ptr));SENIS_continue;}/ /否则,增量foo_var2_ptr 4点到下一个/ / foo_buffer数组的元素,和……SENIS_inc4((&foo_var2_ptr));/ /写真实inRangeAndLTmaxSENIS_assign((&inRangeAndLTmax),真正的);}}}}
43码 SNC uCode C语言实现相同的例子所示代码42
uint32_tfoo_var1=0;/ /定义变量foo_var1uint32_tfoo_buffer(10];/ /定义数组foo_bufferuint32_t*foo_var2_ptr;/ /定义变量foo_var2_ptruint32_tinRangeAndLTmax;/ /定义变量inRangeAndLTmax#定义MAX_THRESHOLD_VALUE 300/ /最大阈值的定义#定义MIN_THRESHOLD_VALUE 100/ /最小阈值的定义无效foo_ucode(无效)/ /定义foo_ucode uCode-Block{/ /写一个值(即假)inRangeAndLTmax变量inRangeAndLTmax=;/ /写一个值(例如5)foo_var1变量foo_var1=5;/ /写一个值(即第六foo_buffer数组元素的地址)/ / foo_var2_ptr变量foo_var2_ptr=&foo_buffer(5]);/ /当foo_var1小于(<)10日…(foo_var1< 10){/ /增加foo_var1 1,……foo_var1+ +;/ /如果该值由foo_var2_ptr foo_buffer指出元素的数组/ /变量大于或等于MAX_THRESHOLD_VALUE (“> =”),…如果(*foo_var2_ptr> =MAX_THRESHOLD_VALUE){/ /然后写假inRangeAndLTmax……inRangeAndLTmax=;/ /打破while循环,…打破;/ /否则,…}其他的{/ /如果指出元素中的值小于(<)/ / MIN_THRESHOLD_VALUE,……如果(*foo_var2_ptr< MIN_THRESHOLD_VALUE){/ /继续下一个元素foo_var2_ptr+ +;继续;}/ /否则,增量foo_var2_ptr 4点到下一个/ / foo_buffer数组的元素,和……foo_var2_ptr+ +;/ /写真实inRangeAndLTmaxinRangeAndLTmax=真正的;}}}

5.8.5.2。SNC系统功能和驱动程序

此外,在对应的SDK提供的API函数来控制DA1469x系统核心HW组件/模块和外围设备,并获得和操作数据有效SYSCPU执行上下文,宏观功能还提供了一组API在SNC执行上下文执行类似的操作,在开发应用程序时,应使用包括FreeRTOS任务和SNC uCodes。亚博国际官网平台网址这些SNC-context宏函数(在各自发现的<代码class="docutils literal notranslate">snc_hw_xxx.h文件和记录(Ref_04))关注:

  • 系统控制(<代码class="docutils literal notranslate">snc.h&<代码class="docutils literal notranslate">snc_hw_sys.h)

  • GPIO控制和配置(<代码class="docutils literal notranslate">snc_hw_gpio.h)

  • SPI接口控制和数据传输<代码class="docutils literal notranslate">snc_hw_spi.h)

  • I2C接口控制和数据传输<代码class="docutils literal notranslate">snc_hw_i2c.h)

  • GPADC控制和数据采集<代码class="docutils literal notranslate">snc_hw_gpadc.h)

5.8.5.3。SNC队列

已经提出了部分5.8。3,SNC编程框架提供了一种机制,用于操作系统之间的数据交换任务和SNC uCodes;的SNC队列。在这种背景下,宏观功能提供了一组API<代码class="docutils literal notranslate">snc_queues.h(记录在(Ref_04)),实现

  • 采集数据的地址可以被写进一块SNC-to-CM33队列

  • 推动SNC-to-CM33队列的数据块

  • 采集数据的地址可以被从一大块CM33-to-SNC队列读取

  • 出现的数据块的CM33-to-SNC队列

  • 获得的地位uCode SNC队列

  • 重置SNC-to-CM33队列数据

为了使SNC队列机制,<代码class="docutils literal notranslate">dg_configUSE_SNC_QUEUES需要定义和设置为“1”的配置项目。

5.8.6。传感器节点控制器的调试

编程的一个最重要的方面是“调试”。因此,除了SYSCPU代码,开发人员必须能够调试SNC uCodes DA1469x系统集成的应用程序。SNC编程框架扩展了调试过程SNC执行上下文,允许完整的和系统整体调试;不是单独调试每个CPU核心,它可能无法检测到故障时系统行为核心并行操作。

从本质上讲,这提供了调试机制同时适用于SNC和SYSCPU同时执行上下文。也就是说,当调试一个SNC uCode及其执行停止,例如,在一个特定SeNIS命令在其实现中,然后停止SYSCPU执行。这样,整个SYSCPU-SNC系统停止,其状态(即变量、寄存器等)保持不变为了可以检查逻辑错误和错误的系统行为。

为了使SNC调试机制,<代码class="docutils literal notranslate">dg_configUSE_SNC_DEBUGGER需要定义和设置为“1”的配置项目。这样,所有各自SNC调试构建宏,下面给出定义<代码class="docutils literal notranslate">snc_debug.h。进一步技术信息关于SNC的使用调试API中可以找到(Ref_04)

SNC编程框架提供了以下调试解决方案:

SNC断点和分步调试

SNC的断点是软件实现断点“绑定”SNC的执行和SYSCPU通过发送特殊SNC-to-CM33通知当执行流到特定的地方uCode那些SeNIS-based结构定义。更具体地说,当SNC执行SeNIS命令隐含的结构,SNC执行流是停了下来,一个对应于SNC断点CM33执行流创建一般通过特殊的宏观结构或代码典型CM33 (HW)断点可以放置,最后SNC执行从已经停止,恢复了图70为<代码class="docutils literal notranslate">SNC_BKPT ()构建宏。因此,有“注入一块CM33执行流”到SNC执行流,后者可以间接地停在放置CM33断点CM33执行流的一部分。

. . / _images / fig_SNC_19.png

图70SNC断点实现暂停SNC CM33断点执行

重要的是要注意,SNC断点软件断点实现以SeNIS uCode命令,从而创建在uCode-build-time uCode实现的一部分。此外,当添加SNC断点构建宏在uCode实现中,即使没有CM33 (HW)断点,CM33执行流部分仍由SNC断点执行,也就是说,CM33醒来时一个SNC断点在SNC上下文中“执行”。

在SNC执行上下文,一步一步调试可以支持一组SeNIS-based构建宏,通过定义一个地区使用uCode实现<代码class="docutils literal notranslate">SNC_STEP_BY_STEP_BEGIN ()和<代码class="docutils literal notranslate">SNC_STEP_BY_STEP_END ()构建宏。此外,不同组的SNC断点和循序渐进的地区可以定义,以便他们可以单独启用和禁用。

SNC模拟器

为了允许完整的灵活性与SNC uCodes在调试应用程序时,亚博国际官网平台网址SNC模拟器提供的传感器节点控制器编程框架,如果启用<代码class="docutils literal notranslate">dg_configUSE_HW_SENSOR_NODE_EMU定义和设置为“1”的配置项目。更具体地说,SNC模拟器实现在软件中实现同一I_FSM HW SNC的模块,它使用一个操作系统任务执行的SeNIS命令SNC uCodes组成一个应用程序,名为传感器节点仿真器任务。通过这种方式,所有SNC uCodes CM33上下文中执行,同时并行(不)与其他操作系统任务由一个应用程序,但是在完全相同的方式在实现逻辑由SNC HW执行。

由于SeNIS命令执行由SNC模拟器在CM33背景下,执行适当的底层实现机制,允许CM33断点被放置到每个SeNIS-based构造宏观或SNC API宏在SNC uCode函数调用实现,基本上直接翻译CM33 SNC的断点。关于逐步调试,它可以启用以同样的方式执行SNC分步调试区域组SNC断点,通过将一个CM33断点的位置被定义在一个特别小组<代码class="docutils literal notranslate">snc.hSNC模拟器断点,即<代码class="docutils literal notranslate">SNC_BKPT_GROUP_EMU ()宏(隐含组名称:snc_bkpt_group_emu),从而使(设置)所有SNC模拟器断点在整个西南SNC uCodes相关实现。

重要的是要注意,在SNC模拟器(CM33)上下文中执行SeNIS命令明显低于在SNC的背景下,因此SNC模拟器必须只使用在SNC uCodes发展的第一个阶段,或检验正确的一般功能在本文的关键应用程序的执行情况。此外,使用的内存空间SNC uCode堆必须加倍允许CM33断点SNC(模拟器)断点“翻译”在整个西南SNC uCodes相关实现。

图71,它显示的说明当放置CM33断点(即智能片段Studio IDE)在SeNIS-based构造宏观的位置或位置<代码class="docutils literal notranslate">SNC_BKPT_GROU_EMU ()宏定义。

. . / _images / fig_SNC_22.png

图71SNC模拟器使用断点和分步调试智能片段工作室

SNC断言

在SNC执行上下文,为了创建一个断言变量值,<代码class="docutils literal notranslate">SNC_ASSERT ()可以使用宏。如果给定的条件求值为false, CM33和SNC执行将永远被阻塞。

对于条件表达式,它只能:

  • 一个布尔表达式由一个操作数(即op1)暗示,可以是一个uCode-build-time值或一个寄存器的内容/ RAM地址,从而评估“true”当隐含价值等于“真正”或非零。

  • 一个布尔表达隐含两个操作数和两个操作数之间的关系操作符定义一个关系既可能指uCode-build-time值或一个寄存器的内容/ RAM地址,从而评估“true”定义的关系。

代码44,它给出了一个示例代码展示一个使用案例<代码class="docutils literal notranslate">SNC_ASSERT ()宏,说明当“false”的条件表达式求值(即在智能片段Studio IDE)、所示图72

代码44 示例SNC uCode使用<代码class="docutils literal notranslate">SNC_ASSERT ()宏定义一个SNC断言
uint32_tfoo_mode=3;/ /定义变量foo_modeuint32_tfoo_flags;/ /定义变量foo_flagsuint32_tfoo_stat_cnt=10;/ /定义变量foo_stat_cntSNC_UCODE_BLOCK_DEF(foo_ucode)/ /定义foo_ucode uCode-Block{/ /初始化foo_flags 0 x0000SENIS_assign((&foo_flags),0 x0000);/ /如果foo_mode直接(addr) = 3,…SENIS_if((&foo_mode),情商,3){/ /设置/切换bit-15 foo_flags(直接addr。)…SENIS_xor((&foo_flags),1< <15);/ /否则,…SENIS_else{/ /如果foo_mode直接(addr) = 4,……SENIS_if((&foo_mode),情商,4){/ /设置/切换bit-15 foo_flags(直接addr。)SENIS_xor((&foo_flags),1< <13);}}}/ / foo_mode(直接addr。)必须大于0。SNC_ASSERT((&foo_flags),GT,0);/ /如果foo_flags(直接addr。) 13集,…SENIS_if((&foo_flags),,13){/ /增加foo_stat_cnt(直接addr。) 1SENIS_inc1((&foo_stat_cnt));}}
. . / _images / fig_SNC_23.png

图72在聪明的片段使用SNC断言工作室

5.9。USB框架

5.9.1。介绍

本节描述了USB支持SmartSnippets™DA1469x SDK和必要的步骤添加USB支持一个用户应用程序。USB端口可以用作充电端口和/或一个主机接口。

5.9.2。SYS_USB

为了使USB端口,用户必须首先添加<代码class="docutils literal notranslate">sys_usb到应用程序,并设置相对配置宏。

代码45 sys_usb添加到一个项目
# include“sys_usb.h”sys_usb_init();
代码46 使sys_usb
#定义dg_configUSE_SYS_USB (1)

下图说明了<代码class="docutils literal notranslate">sys_usb初始化过程中,当设备配置为使用USB充电器和USB堆栈。

请注意,任何一个可以使用两个特性相互独立的。

. . / _images / usb_init.png

图73SYS_USB初始化

5.9.3。USB充电器

信息如何使用的USB充电器DA1469x请参考章节4.1.3

5.9.4。USB数据连接

使设备能够列举和与连接主机通过USB端口通信,宏<代码class="docutils literal notranslate">dg_configUSE_USB_ENUMERATION必须设置。

代码47 启用USB枚举
#定义dg_configUSE_USB_ENUMERATION (1)

5.9.4.1。SDK USB堆栈

的SmartSnippets™DA1469x SDK包含一个完整的USB堆栈实现,基于emUSB堆栈,版本3.12,由耐火提供。

将USB堆栈添加到用户的项目,链接库对象usb_lib_da1469x给应用程序。必要的头文件位于下

< sdk_root_directory > / sdk /接口/ usb /包括

为了配置和使用USB堆栈,请参阅耐火emUSB用户手册,或检查SDK提供的示例应用程序亚博国际官网平台网址

< sdk_root_directory > /项目/ dk_apps /功能/ usb_cdc_smsd

< sdk_root_directory /项目/ dk_apps /功能/ usb_cdc

5.9.4.2。使用不同的USB堆栈

USB堆栈不同可以使用SDK提供的一个。在这种情况下,请检查章5.9.4。3看到哪个回调函数必须由用户提供的USB实现堆栈。

5.9.4.3。回调函数/钩子

应用程序可以实现以下钩子函数以USB事件通知

表42 USB钩子函数

函数

描述

sys_usb_ext_hook_attach ()

这个函数被调用时,设备在物理上连接到该端口。以防USB充电器使用应用程序,那么这个函数被调用后,充电器已经完成端口检测过程。

sys_usb_ext_hook_begin_enumeration ()

这个函数被调用时,USB主机设备已经发出信号,它必须开始枚举过程。

sys_usb_ext_hook_detach

这个函数被调用时,设备物理上断开USB端口

如果应用程序不使用USB堆栈提供的SDK,那么它需要实现下面的回调函数。

表43 USB接口回调函数

函数

描述

hw_usb_ep_rx_read_by_driver ()

这个函数将指示USB驱动程序是否应该读的处方数据或者别的Rx读取数据。

hw_usb_ep_get_rx_buffer ()

这个函数将调用为了得到一个缓冲区来存储接收到的数据。

hw_usb_ep_rx_done ()

时,将调用此函数接收操作已经完成。

hw_usb_ep_tx_done ()

时,将调用此函数传输操作已经完成。

hw_usb_ep_nak ()

时,将调用此函数NAK已经收到一个端点。

hw_usb_bus_event ()

此函数将调用指示公共汽车事件。

hw_usb_bus_frame ()

这个函数将调用与当前USB帧数。

5.9.5。USB事件

5.9.5.1。通风装置连接

这个事件信号,设备一直在物理上连接到一个USB端口。

  • 在接收中断,<代码class="docutils literal notranslate">sys_usb设置设备功率模式活跃并调用应用程序<代码class="docutils literal notranslate">sys_usb_ext_hook_attach ()钩,如果它是如何实现的。

  • sys_usb然后使USB垫和程序USB中断。

  • 如果应用程序配置有充电器的支持,充电器子系统通知。

  • 初始化之后,USB底层驱动程序和设备被连接到USB总线。

  • 最后,应用钩<代码class="docutils literal notranslate">sys_usb_ext_hook_begin_enumeration ()被调用时,如果它是如何实现的。

此时应该准备开始USB设备枚举时引发的主机。

下图说明了USB连接过程。

. . / _images / usb_attach.png

图74USB通风装置连接

5.9.5.2。通风装置分离

这个事件信号,设备一直身体脱离USB端口。

  • USB垫被禁用

  • sys_usb恢复之前的权力模式使用设备被连接到USB端口。

  • 如果应用程序配置有充电器的支持,充电器子系统通知。

  • 脱离USB总线设备。

  • sys_usb使用锁相环时钟停止。

  • 最后,应用钩<代码class="docutils literal notranslate">sys_usb_ext_hook_detach ()被调用时,如果它是如何实现的。

下图说明了USB分离过程。

. . / _images / usb_detach.png

图75USB通风装置分离

5.9.5.3。USB重置/暂停/恢复

USB重置

这个中断表明设备必须开始枚举过程。

  • sys_usb设备功率模式转换到活跃并开始使用锁相环时钟。

  • USB相应中断程序。

  • USB堆栈是通过回调通知事件<代码class="docutils literal notranslate">hw_usb_bus_event ()与事件<代码class="docutils literal notranslate">UBE_RESET

请注意,应用程序并不直接通知<代码class="docutils literal notranslate">sys_usb,而是通过USB堆栈。

USB暂停

已经暂停这个中断信号,USB主机和设备应该降低功耗。

  • 如果应用程序配置有充电器的支持,充电器子系统通知。

  • USB堆栈是通过回调通知事件<代码class="docutils literal notranslate">hw_usb_bus_event ()与事件<代码class="docutils literal notranslate">UBE_SUSPEND

  • USB相应中断程序。

  • 如果应用程序配置<代码class="docutils literal notranslate">USB_SUSPEND_MODE_IDLE,<代码class="docutils literal notranslate">sys_usb开关电源模式闲置。

  • sys_usb使用锁相环时钟停止。

请注意,应用程序并不直接通知<代码class="docutils literal notranslate">sys_usb,而是通过USB堆栈。

USB的简历

这中断信号,USB主机退出暂停状态和恢复操作。

  • sys_usb开始使用锁相环时钟。

  • USB堆栈是通过回调通知事件<代码class="docutils literal notranslate">hw_usb_bus_event ()与事件<代码class="docutils literal notranslate">UBE_RESUME

  • USB相应中断程序。

  • 如果应用程序配置<代码class="docutils literal notranslate">USB_SUSPEND_MODE_IDLE,<代码class="docutils literal notranslate">sys_usb开关电源模式,活跃。

  • 如果应用程序配置有充电器的支持,充电器子系统通知。

请注意,应用程序并不直接通知<代码class="docutils literal notranslate">sys_usb,而是通过USB堆栈。

下图说明了USB中断处理程序。

. . / _images / usb_irq_handling.png

图76USB中断处理

5.9.6。USB暂停模式

在回应一个挂起信号从USB主机,应用程序可能会切换到一个空闲状态,以降低其功耗。是否这种情况是由宏观控制的配置参数<代码class="docutils literal notranslate">dg_configUSB_SUSPEND_MODE

现DA1469x两暂停模式支持:

USB_SUSPEND_MODE_NONE表明,暂停信号将不会影响系统的功率状态。

USB_SUSPEND_MODE_IDLE表明,暂停信号将导致系统的权力转向闲置状态。

5.9.7。USB功耗的考虑

为了一个设备USB的认证,在其他参数,它需要表现出低电流消耗从USB主机,主机时暂停。USB框架试图使能耗降到最低,当设备被连接到一个主机暂停。但是必要的用户应用程序进入节电模式当主机被暂停。

5.10。触觉(LRA / ERM)的支持

的SmartSnippets™DA1469x SDK包括一组软件模块支持使用触觉司机/控制器硬件模块(中可用DA14697DA14699DA1469x芯片组家族的变体)与外部驱动器,如上帝抵抗军或erm,生产触觉的影响(为了提供触觉反馈(如打字触摸屏)以及警报/通知给用户)。

5.10.1。介绍

5.10.1.1。背景理论

目前最常见的类型的驱动器用于触觉技术领域是上帝抵抗军和erm。他们是机电设备响应一个输入电压信号通过执行周期性的机械运动。这个运动创造了一个振动效应,特点是一定的强度(振动的强度)频率(对应通常也一定声语气)。通过改变振动的强度和/或频率随着时间的推移,我们可以创建一个具体的触觉波形模式(或简单触觉模式)。

5.10.1.1.1。嗯

一个汇率机制(偏心旋转质量)电机由一个直流电机的偏心质量附加到它的轴。通过应用一个直流电压信号,电机,质量不平衡旋转的离心力引起周期性位移motor-mass系统。旋转的速度取决于外加电压的振幅和motor-mass系统特征,并影响的强度和频率振动(两个振动特征相关)。

5.10.1.1.2。上帝抵抗军

一个上帝抵抗军(线性谐振致动器)由一个弹簧磁物体和音圈,轴的对齐到弹簧的轴。电流流过线圈产生磁场引起的位移磁质量。因此,通过应用一个交流电压信号音圈,我们可以创建一个线性周期性位移磁的质量。的运动质量对音圈(更具体地说这个运动的速度)诱发Back-electro-motive力(反电动势),有一个正弦形状(以下机械运动的形状),是反映在一个正弦分量的电流圣主抵抗军。通过不同振幅和频率的应用交流电压信号我们可以控制的强度和频率振动独立(erm)不同。然而,在接下来的小节所述,驱动频率振动特性都可发病。

5.10.1.1.3。上帝抵抗军频率控制

每个弹簧质点振动系统,上帝有一个频率相关的反应,通常在一定频率和最大化(取决于类型的圣主抵抗军)可能下降非常迅速的驱动频率远离它。这共振频率也可能由于环境或其他不同条件(温度、压力、机械耦合等),所以它是重要的是能够遵循这一变化,相应地调整驱动电压信号的频率。

5.10.1.1.4。超速

erm和上帝有一个机械响应时间影响他们花多长时间达到全速/振荡后驱动信号(开始时间)和应用来休息后删除驱动信号(停止时间)。缓慢的机械响应时间可以限制的瞬态影响触觉使它们显得有些少不同的模式。然而通过加速启动/停止时间可以减少/制动执行机构超速暂时,直到达到目标速度/振荡幅度。在加速的情况下,执行机构暂时与较高的驱动电压和驱动制动的情况下,较低或负驱动器的驱动电压。

5.10.1.2。DA1469x触觉司机

DA1469x触觉驱动和控制器硬件模块(从此简单触觉的司机)提供了一种直流或交流差动驱动电压信号适合驾驶触觉致动器。

驱动信号是由一个250 khz PWM信号的常数(DC)或交替极性(AC)。

占空比的PWM信号运行时是可配置的,而且是被致动器驱动信号的振幅。因此直接影响触觉振动强度响应的执行机构,并在ERM也影响振动频率。因为每个触觉致动器的特点是最大支持电压(对应于最大占空比的PWM信号),这个词开车水平可用于描述驱动器的工作周期信号的比例最大的致动器支持的工作周期。

脉宽调制信号的振幅是不可配置的,取决于DA1469x设备的电源电压和触觉司机的负载(致动器的阻抗)。

极性切换的频率在交流传动的情况下,更具体地说半周期极性转换,也运行时配置和执行机构(LRA)认为交流传动的频率信号。它直接影响圣主抵抗军的振动频率也影响振动强度由于产生共鸣的圣主抵抗军的行为(如上所述)。

除了工作周期和频率,自动极性切换模式的驱动信号也可以在运行时。这可以用于制动触觉致动器(以防驱动电压需要应用)。这状态的自动极性切换模式(正常的从今以后只叫极性(不要与混淆即时驱动信号的极性)。

上述三个可配置参数(半周期、驾驶水平、极性)从此简单地叫驱动参数

触觉驱动程序也能够连续测量电流流经的致动器电路采样的电压检测电阻一系列使用ADC。更具体地说,在每半个周期的驱动信号,它存储8样本电流(i-samples)的时候,如果配置适当,也会产生一个中断请求后存储一个特定(8)的样品(如,在捕捉7日样品每半周期)。通过维修这些中断请求,驱动参数可以动态地更新(可能也通过阅读和分析i-samples),生产一个具体的期望的触觉模式和/或为确保有效使用超速驾驶和频率控制原则在前一节中描述。

这种机制的动态更新驱动参数将从此被称为触觉处理。如果触觉处理考虑当前状态的触觉司机和致动器的响应(即驱动参数,即时极性,i-samples)的情况下闭环(触觉)处理。否则,我们有一个开环(触觉)处理的情况。

在任何时候,驱动信号可以暂时关闭。在这种情况下,也禁用中断和触觉司机说空闲状态,因为没有权力交付给执行机构,但保留驱动参数和任何其他配置设置。否则(如果驱动信号开启),据说触觉司机活动状态

更多信息触觉驱动硬件模块中可以找到相关的部分(Ref_01)

5.10.2。SmartSnippets™DA1469x SDK触觉软件模块

提供的触觉软件支持SmartSnippets™DA1469x SDK包含以下软件模块,以及示例应用程序(亚博国际官网平台网址上帝抵抗军),利用他们。

  • 触觉低水平SW司机,它提供了低层次抽象以及触觉驱动硬件的中断处理模块

  • 触觉技术算法图书馆,可以用于有效地推动上帝抵抗军(基于频率控制和超速原则)

  • 波形存储器译码器,它可用于解码编码触觉模式

  • 触觉适配器,它提供了一个集成的API的应用程序安全、抽象的使用其他触觉SW模块为了简单地产生各种触觉效果。

简要概述不同的模块的结构及其交互所示图77

. . / _images / haptic_architecture.png

图77触觉SDK支持概述

建议利用支持的触觉功能通过触觉适配器API,而不是直接使用API的其他触觉SW模块。然而,适配器的配置参数结构(所需初始配置)使用的其他软件模块的参数结构,所以一些基本的了解所有相关软件模块的功能。出于这个原因,一些描述每个软件模块(而不是只有触觉适配器),使用在以下部分中提供。的上帝抵抗军应用程序项目建议作为一个例子使用参考。

5.10.2.1。触觉低水平SW司机

SW司机的触觉低级别(触觉LLD)(<代码class="docutils literal notranslate">sdk / bsp /外围设备/ src / hw_haptic.c和<代码class="docutils literal notranslate">bsp /外围设备包括/ hw_haptic.h)接口直接触觉驱动硬件模块。它的主要目的是提供一个抽象的模块的功能更高层次的SDK和应用程序层,以使他们更容易来初始化和控制模块,不需要相关的寄存器的详细知识,领域和使用。它还处理任何中断生成的模块。

所提供的功能(或函数宏)触觉LLD API的如下:

函数

描述

hw_haptic_init ()

配置触觉司机驾驶的具体执行机构使用和初始化触觉LLD的内部数据

hw_haptic_get / set_drive_level ()

获取/设置驱动水平

hw_haptic_get / set_polarity ()

获取/设置极性

hw_haptic_get / set_half_period ()

获取/设置半周期

hw_haptic_get / set_state ()

获取/设置触觉司机状态(空闲/活动)

hw_haptic_shutdown ()

完全禁用触觉驱动程序

HW_HAPTIC_CONV_FREQ_TO_HALFPERIOD ()

将频率转换为半周期

HW_HAPTIC_CONV_VOLT_TO_DUTYCYCLE ()

将电压转换成工作周期

触觉LLD的配置参数结构,<代码class="docutils literal notranslate">haptic_config_t通过(引用)<代码class="docutils literal notranslate">hw_haptic_init ()包括以下参数:

参数

描述

duty_cycle_nom_max

最大额定工作周期的驱动信号得到了执行机构的支持

duty_cycle_abs_max

最大的绝对责任周期是支持的致动器的驱动信号

half_period

最初的半周期的驱动信号,以防上帝抵抗军(应根据其名义设置/初始共振频率)——或者只是半周期的中断请求ERM案例(可选)

interrupt_cb

回调函数在中断被解雇

signal_out

最初的直流驱动信号的极性(ERM)

笔记:

  • 的<代码class="docutils literal notranslate">interrupt_cb参数应该指向一个回调函数,需要被称为中断处理程序在每个中断请求的触觉司机。如果设置为NULL,那么中断请求被禁用。的<代码class="docutils literal notranslate">hw_haptic_init ()功能配置触觉司机捕捉后产生中断请求7日在每一个样品一半时期。中断处理程序调用回调函数通过喂养它与当前驱动参数,即时极性和八i-samples对应于当前时期的一半。回调函数可以执行触觉处理并更新驱动相应的参数。

    这个特定样本的选择指数(7日)允许回调函数都足够的视图的形状上帝抵抗军的电流在当前半周期的驱动信号以及足够的时间来更新驱动参数之前一半的新时期的开始。

  • 的<代码class="docutils literal notranslate">duty_cycle_nom_max参数对应的最大名义上的RMS电压支持的驱动器。它可以从驱动器中提取的数据表。为了容易RMS电压值转换为一个工作周期值,<代码class="docutils literal notranslate">HW_HAPTIC_CONV_VOLT_TO_DUTYCYCLE ()函数可以使用宏。的<代码class="docutils literal notranslate">duty_cycle_abs_max参数对应的最大绝对RMS电压支持的驱动器。是最大有效值电压支持短时间(即瞬态,例如当加速/制动执行机构)所以应该大于标称电压均方根值。这并不总是提供的数据表。在这种情况下,它可以近似为最大名义RMS电压高出10%。

  • 的<代码class="docutils literal notranslate">half_period参数定义的初始半周期驱动信号,显然也的初始频率中断请求(如果启用)。

    必须只有在圣主抵抗军,应该设置根据圣主抵抗军的最初的共振频率,为致动器中指定的数据表。

    在欧洲汇率机制情况下,参数是可选的,它只定义中断请求的频率(如果启用)。如果没有设置,使用200 hz的默认值。(虽然没有自动极性切换在这种情况下,i-samples仍然捕获相同的方式在交流的情况下,基于当前半周期相关寄存器的设置)。

  • 触觉司机HW模块功能也是一个硬件机制确保驱动器的电流是恒定在每个时期的一半。这是通过监测i-samples使用HW回路滤波器,不断调整占空比的PWM信号。如果使用这种机制,据说在硬件模块恒流模式。否则在恒定的工作周期模式。只有后者(恒定的工作周期)然而之一是使用和支持的SDK。

5.10.2.1.1。编程模型

如前所述,推荐使用触觉适配器API,而不是直接使用其他的触觉SW模块。然而,编程模型使用触觉LLD下面描述的完整性和为了提供更好的理解每个软件模块的功能及其相互作用:

  1. 根据使用的致动器的类型,<代码class="docutils literal notranslate">dg_configUSE_HW_ERM或<代码class="docutils literal notranslate">dg_configUSE_HW_LRA应该定义为1,在适当的<代码class="docutils literal notranslate">custom_config_xxx.h文件。(激活的配置选项,那么在默认情况下“圣主抵抗军”功能将启用。)

  2. 的一个实例<代码class="docutils literal notranslate">haptic_config_t首先必须创建和各自的配置参数应设置根据使用的致动器的致动器特点(从数据表),可能使用呢<代码class="docutils literal notranslate">HW_HAPTIC_CONV_VOLT_TO_DUTYCYCLE ()函数宏。

  3. 如果<代码class="docutils literal notranslate">interrupt_cb设置为指向一个特定的回调函数,这个回调函数应该适当地执行。

  4. 的<代码class="docutils literal notranslate">hw_haptic_init ()函数应该调用通过一个指针<代码class="docutils literal notranslate">haptic_config_t实例。触觉司机被初始化并进入空闲状态。

  5. 的<代码class="docutils literal notranslate">hw_haptic_get / set_drive_level (),<代码class="docutils literal notranslate">hw_haptic_get / set_polarity ()和<代码class="docutils literal notranslate">hw_haptic_get / set_half_period ()功能可以随时(只要前面的步骤已经完成)阅读或动态设置驱动参数。的<代码class="docutils literal notranslate">hw_haptic_set_state ()函数也应该随时呼吁使驱动信号(或禁用它,如在长脉冲/模式)之间的差距。

    请注意

    如果使用闭环处理,使用的<代码class="docutils literal notranslate">hw_haptic_set_drive_level (),<代码class="docutils literal notranslate">hw_haptic_set_polarity ()和<代码class="docutils literal notranslate">hw_haptic_set_half_period ()不推荐功能,在这种情况下,任何更改驱动器参数应该是同步的开始/结束一半时期,为了避免步取样电流的变化,这可能对闭环处理算法产生负面影响(例如超速、频率控制)。所以在这种情况下,任何更新驱动参数的上下文中应该只被应用中断处理程序的回调函数。

  6. 当所有预期的触觉活动已经执行,触觉司机可以完全关闭(最小化能耗)使用<代码class="docutils literal notranslate">hw_haptic_shutdown ()函数。

5.10.2.2。触觉技术算法图书馆

触觉技术算法库(<代码class="docutils literal notranslate">sdk /中间件/触觉/ include / {curve_fitting.h,lra_frequency_control.h,smart_drive.h,haptics_lib.h}&<代码class="docutils literal notranslate">sdk /中间件/触觉/ lib)由一组算法模块的上下文中,可以使用触觉处理(在中断处理程序的回调函数)有效驱动参数的实时控制。它更专门为超速lra和跟踪/他们的共振频率。

一个非常基本的描述每个模块,以及一系列相关API提供的功能如下。每个模块也由一个参数结构,应该适当的初始化。然而,这些参数的列表或描述结构不是这里提供,因为它是这个短暂的用户指南的范围,因为更多详细信息的功能和使用触觉技术算法的图书馆可以找到各自的文档(<代码class="docutils literal notranslate">sdk /中间件/触觉/ README_haptics_lib.md,也很容易从主页的访问(Ref_04))。

5.10.2.2.1。曲线更健康

曲线更健康模块分析i-samples和提取的dc_offset电流以及振幅和相位(抵消对驱动信号阶段)的反电动势组件的电流。

函数

描述

curve_fitter_process ()

处理i-samples并计算dc_offset,反电动势的振幅和相位

5.10.2.2.2。自动频率控制

当圣主抵抗军在其共振频率,其机械振荡阶段的驱动信号。否则,上有相抵消,反映阶段的反电动势。的自动频率控制模块处理反电动势阶段(如曲线提供的装配模块)和计算新的合适的驱动信号的半周期(谐振频率对应的),因此,相抵消消失了。

函数

描述

lra_afc_process ()

计算新的一半时期,基于反电动势的阶段和当前时期的一半

5.10.2.2.3。高速缓冲程序™

高速缓冲程序™模块实现上帝抵抗军的超速传动原理。计算相应的驾驶水平,圣主抵抗军到达所需的振动强度级别(目标水平在最短时间。这是通过考虑电流的反电动势的振幅组件(如曲线提供的健康)。

函数

描述

smart_drive_init ()

初始化高速缓冲程序™算法

smart_drive_process ()

计算所需的新驱动水平,基于反电动势的振幅,当前的驾驶水平与目标水平

5.10.2.2.4。Haptics_lib

一个包装器模块还包括高效的使用图书馆,也提供一些额外的功能未被单独的模块。推荐使用这个模块,而不是直接使用个人的API。

函数

描述

haptics_lib_init ()

初始化库触觉算法

haptics_lib_process ()

处理i-samples,目标水平和当前硬件状态触觉的驱动程序和更新驱动相应的参数

5.10.2.2.5。编程模型

如前所述,推荐使用触觉适配器API,而不是直接使用其他的触觉SW模块。然而,适当的步骤只使用触觉技术算法的库一起触觉LLD下面简要描述(用于完整性和为了提供更好的理解每个软件模块的功能以及它们的相互作用):

除了触觉LLD部分中描述的步骤,应该执行额外的步骤如下:

  1. 中断处理程序应该实现回调函数的调用<代码class="docutils literal notranslate">haptics_lib_process ()功能与当前驱动器参数,即时极性和i-samples(中断处理程序提供的),以及当前的目标水平。

  2. 的一个实例<代码class="docutils literal notranslate">haptics_lib_params首先必须创建和各自的配置参数应设置根据使用的致动器。

  3. 的<代码class="docutils literal notranslate">haptic_lib_init ()函数应该调用之前触觉司机进入活跃状态。

  4. 目标水平应设置(根据所需的振动强度级别)。

5.10.2.3。波形存储器译码器

触觉模式可以表示为一个序列驱动振幅-驱动频率对。这个序列可以编码在一个表单,允许它被存储在内存中没有占用太多的空间。

波形存储器译码器SW模块(<代码class="docutils literal notranslate">sdk /中间件/触觉/ include / wm_decoder.h&<代码class="docutils literal notranslate">sdk /中间件/触觉/ src / wm_decoder.c)解码触觉模式存储在一个字节数组中相同的格式对话框的使用的一个DA7280触觉驱动IC。详细描述的格式是“波形记忆”部分的集成电路数据表)。它存储模式的形式分段线性段,片段,并最终序列。DA7280波形记忆格式编码对应的每个序列因此编码触觉模式和今后被称为波形序列。一组编码的触觉阵列构成所谓的模式编码波形记忆。因此,波形存储器的波形存储器解码器解码才能为我们提供特定波形的幅频双序列在给定时间t(对波形序列)的开始。

更详细的功能和使用波形存储器译码器可以在各自的文档(<代码class="docutils literal notranslate">sdk /中间件/触觉/ README_wm_decoder.md),它也可以很容易从主页的访问(Ref_04)

提供的功能模块的API是以下:

函数

描述

wm_decoder_init ()

初始化波形存储器译码器

wm_decoder_trigger_sequence ()

触发启动/停止播放序列的波形记忆

wm_decoder_update ()

更新的状态波形存储器译码器根据当前时间

5.10.2.3.1。编程模型

如前所述,推荐使用触觉适配器API,而不是直接使用其他的触觉SW模块。然而,仅使用的适当措施,以防波形存储器译码器一起触觉LLD下面简要描述(用于完整性和为了提供更好的理解每个软件模块的功能以及它们的相互作用):

除了触觉LLD部分中描述的步骤,应该执行额外的步骤如下:

  1. 中断处理程序应该实现回调函数的调用<代码class="docutils literal notranslate">wm_decoder_update ()函数通过喂养当前时间(由一个自由运行32位定时器为已读)为了得到当前两幅频(序列波形回放时触发)。然后,驱动参数应该根据当前振幅和频率对更新。

  2. 的<代码class="docutils literal notranslate">wm_decoder_init ()应该呼吁初始化函数波形存储器译码器。如果需要,步骤1中使用的定时器还应该配置/初始化。

  3. 的<代码class="docutils literal notranslate">wm_decoder_trigger_sequence ()函数应该被喂养它与当前时间(读同样的自由运行32位定时器用于步骤1)和所需的波形序列的索引。

可以使用上面的步骤与上帝抵抗军和erm。然而,在欧洲汇率机制情况下,解码频率没有任何明显的影响,因为它只会变化的频率中断。如前所述,ERM的实际振动频率与振动强度,所以实际上取决于解码振幅。

5.10.2.4。触觉适配器

触觉适配器(<代码class="docutils literal notranslate">sdk /中间件/适配器/ src / ad_haptic.c和<代码class="docutils literal notranslate">sdk /中间件/适配器/ include / ad_haptic.h)是一个中间件抽象层模块,与所有其他的触觉交互软件模块以及应用程序层,集成它们的功能,这样他们就可以在一起作为一个整体运作提供一个完整的触觉的解决方案。它提供了一个方便的方式一起使用触觉LLD触觉算法图书馆和波形存储器译码器,与此同时,它确保权力稳定(即域,适当的权力在触觉上操作)并提供多个任务之间的仲裁。

函数

描述

ad_haptic_open ()

打开一个触觉操作会话(配置触觉驱动程序和相关软件模块)

ad_haptic_reconfig ()

应用一个新的触觉配置

ad_haptic_set_drive_level ()

设置激励电平(直接或间接地取决于当前的驱动模式)

ad_haptic_set_polarity ()

设置驱动极性

ad_haptic_set_half_period ()

设置半周期

ad_haptic_set_state ()

设置触觉司机为活跃或空闲状态

ad_haptic_set_drive_mode ()

设置当前驱动的触觉操作模式(即启用/禁用超速和触觉的频率控制部分算法库)。

ad_haptic_play_wm_sequence ()

玩的一个波形序列存储在波形记忆

ad_haptic_stop_wm_sequence ()

停止当前波形序列

ad_haptic_update_drive_parameters ()

更新触觉驱动参数(作为中断处理程序的回调函数)

ad_haptic_close ()

终止触觉操作会话

适配器的配置参数结构,<代码class="docutils literal notranslate">ad_haptic_controller_conf_t通过(引用)<代码class="docutils literal notranslate">ad_haptic_open ()和<代码class="docutils literal notranslate">ad_haptic_reconfig ()有以下成员:

参数

描述

drv

指针指向的触觉LLD配置参数结构(<代码class="docutils literal notranslate">haptic_config_t)实例

自由

指针触觉算法参数库的结构(<代码class="docutils literal notranslate">haptics_lib_params)实例

wm

指针指向的内存配置适配器的波形参数结构(<代码class="docutils literal notranslate">ad_haptic_wm_conf_t)实例

适配器的波形内存配置结构,<代码class="docutils literal notranslate">ad_haptic_wm_conf_t包括以下参数:

参数

描述

数据

指向数组的指针包含所有可用的触觉DA7280波形记忆格式编码模式

accel_en

指定每个片段的振幅值是否会被视为签署或无符号

时基

指定是否最低的时基波形序列女士是1.36或5.44 ms

请注意:适配器可用于上帝抵抗军和erm。然而,由于自动频率控制和高速缓冲程序™模块只适用于上帝抵抗军,是没有意义的有触觉算法库配置。结果,<代码class="docutils literal notranslate">自由的成员<代码class="docutils literal notranslate">ad_haptic_controller_conf_t实例应该在欧洲汇率机制情况下设置为NULL。

编程模型:

  1. 根据使用的致动器的类型,<代码class="docutils literal notranslate">dg_configUSE_HW_ERM或<代码class="docutils literal notranslate">dg_configUSE_HW_LRA应该定义为1,在适当的<代码class="docutils literal notranslate">custom_config_xxx.h文件。(激活的配置选项,那么在默认情况下“圣主抵抗军”功能将启用。)除此之外,<代码class="docutils literal notranslate">dg_configHAPTIC_ADAPTER应该被定义为1。

  2. 的一个实例<代码class="docutils literal notranslate">ad_haptic_controller_conf_t应该创建和所有各自的参数应该初始化。这意味着实例的所有个人配置结构以及波形存储器阵列在这之前还应该创建并初始化。如果任何提供触觉处理软件模块(触觉算法图书馆&波形存储器译码器)的目的是被使用,那么<代码class="docutils literal notranslate">interrupt_cb参数的<代码class="docutils literal notranslate">haptic_config_t实例应该指向<代码class="docutils literal notranslate">ad_haptic_update_drive_parameters ()函数(或自定义调用回调函数<代码class="docutils literal notranslate">ad_haptic_update_drive_parameters ()本身)。

  3. 的<代码class="docutils literal notranslate">ad_haptic_open ()为了打开一个函数应该被称为触觉操作会话基于配置参数设置在步骤2。返回的处理应该存储,因为它必须是适配器中使用的其它函数调用。系统现在无法睡觉,直到<代码class="docutils literal notranslate">ad_haptic_close ()被称为。

  4. 的<代码class="docutils literal notranslate">ad_haptic_set_drive_mode ()函数应该被称为(如果必要的话),以启用或禁用超速和频率控制特性(如由触觉算法实现图书馆)。

  5. 预期的触觉效果可以通过手动设置驱动器参数使用<代码class="docutils literal notranslate">ad_haptic_set_drive_level /极性/ half_period ()功能(通过设置触觉司机活动状态(如果不是已经通过<代码class="docutils literal notranslate">ad_haptic_set_state ()函数)或玩一个可用的波形模式使用<代码class="docutils literal notranslate">ad_haptic_play_wm_sequence ()函数。在后一种情况下,触觉司机进入活动状态在波形序列的开始自动播放。

  6. 应该重复步骤4和5,如果有必要,为了生产更多的触觉效果。同时,以防触觉效果需要生产不同的配置(如不同的触觉算法与不同的波形记忆库参数或数组,其中包含一组不同的触觉模式),<代码class="docutils literal notranslate">ad_haptic_reconfig ()函数可用于改变适配器的配置(在继续之前再次与3和4)。

    如果任何函数中使用步骤4 - 6称为序列波形回放时已经在进步,不断回放的函数将阻塞,直到完成。一个例外是这样的紧急的波形回放请求而非紧急波形回放过程中(见<代码class="docutils literal notranslate">紧迫感参数的<代码class="docutils literal notranslate">ad_haptic_play_wm_sequence ()功能)。如果不需要这个阻塞,那么<代码class="docutils literal notranslate">ad_haptic_stop_wm_sequence ()函数可以使用为了立即停止正在进行的顺序播放。更多细节可以在适配器的头文件(使用相同的内容也很方便了(Ref_04)。)

  7. ad_haptic_close ()应该被称为触觉操作终止会话。

5.10.2.5。示例应用程序亚博国际官网平台网址

的SmartSnippets™DA1469x SDK包含了两个示例应用程序演示的使用上面描述的触觉驱动程亚博国际官网平台网址序和相关的软件支持。

5.10.2.5.1。上帝抵抗军

上帝抵抗军应用程序(<代码class="docutils literal notranslate">项目/ dk_apps /功能/上帝抵抗军)展示了生产各种触觉适配器提供的API的功能使用LRA触觉效果。通过按K1 DA1469x Pro开发工具包的按钮(ProDK),不同的触觉产生影响(通过应用一个具体的触觉模式,或驾驶以恒定的开车水平和圣主抵抗军,在每种情况下,当操作在一个特定的驱动模式)。

5.10.2.5.2。嗯

应用程序(<代码class="docutils literal notranslate">项目/ dk_apps /功能/ erm /)的ERM电动机驱动一个常数(编译时)可配置驱动水平为了创建一个恒定的振动效果。按ProDK K1按钮,驱动信号开启或关闭(通过设置触觉司机分别为活跃或空闲模式)。由于有限的应用程序的功能,触觉LLD API直接使用(虽然,如上所述,它通常是强烈推荐使用触觉适配器API)。

更多的信息可以在应用程序中找到“亚博国际官网平台网址<代码class="docutils literal notranslate">README.md文件,也可以轻易地从主页的访问(Ref_04)

5.11。使用耐火开放Flashloader

5.11.2。工具准备

  1. 智能工作室片段导入项目<代码class="docutils literal notranslate">segger_flash_loader位于sdk<代码class="docutils literal notranslate">sdk / bsp /系统/加载器

  2. 在配置构建项目<代码class="docutils literal notranslate">DA1469x-00_Release

  3. 复制生成的文件<代码class="docutils literal notranslate">segger_flash_loader.elf在耐火JLink安装文件夹<代码class="docutils literal notranslate">segger_flash_loader_da1469x.elf

  4. 确保一个适当的JLink版本安装和聪明的片段中选择工作室。

  5. 在耐火JLink安装文件夹,JLinkDevices编辑文件。xml,并添加以下段内<代码class="docutils literal notranslate"><数据库>段。在这个(更多信息,请参阅“开放Flashloader /添加新设备”章J-Link / J-Trace用户指南)

代码48 DA1469x添加到列表的设备
< 设备>< ChipInfo供应商=“yabo国际娱乐半导体”对话框的名字=“DA14690”WorkRAMAddr=“0 x810000”WorkRAMSize=“0 x10000”核心=“JLINK_CORE_CORTEX_M33”/ >< FlashBankInfo的名字=“赢了。Flash”BaseAddr=“0 x0”最大尺寸=“0 x100000”加载程序=“segger_flash_loader_da1469x.elf”LoaderType=“FLASH_ALGO_TYPE_OPEN”/ >< /设备>

5.11.3。项目准备工作

  1. 添加以下条目中<代码class="docutils literal notranslate">custom_config_qspi.h你想flash文件的项目。

代码49 生产耐火加载程序兼容的图像
#定义dg_configUSE_SEGGER_FLASH_LOADER (1)
  1. 在SmartSnippetsStudio修改QSPI_DA1469x调试配置:
    • 在选项卡主要,使自动构建,如果你想要这个项目开始前自动构建一个调试会话

    • 在调试器选项卡,设置设备名称DA1469x

    • 在选项卡启动,使加载可执行。

5.11.4。闪烁的图像

选择DA1469x调试配置。该项目将自动开始构建,一旦完成,该项目形象将闪到DA1469x,调试器将附呈。