HID 私有协议
本示例用两个工程分别扮演 HID 私有协议用户指南 中的 master 和 slave 两个角色,他们之间可以互相发送消息,演示该协议的基本使用方法:
Master 首次使用或者按键触发时自动配对,Slave 首次使用或者上电时自动配对。
Master 和 Slave 自动回连。
Master 自动按照上报率上报数据,按键切换上报率、开关上报。
Slave 按键下发指令。
连线、数据发送的 led 指示。
环境需求
该示例支持以下开发工具包:
Hardware Platforms |
Board Name |
---|---|
RTL87x2G HDK |
RTL87x2G EVB |
更多要求,请参考 快速入门。
硬件连线
请参考 快速入门 中的 EVB 接口和模块 。
示例会用到 3 个 LED 显示相关状态,参考下表:
类型 |
说明 |
led 名 |
pin |
---|---|---|---|
link status |
连接点亮/断线熄灭 |
LED4 |
P3_0 |
data transmit |
master 向 slave 方向的数据传输每 1000 笔翻转一次 |
LED3 |
P3_1 |
slave cmd |
slave 的 slave cmd 按键按下翻转一次 |
LED2 |
P1_0 |
master 示例会用到 3 个按键,参考下表:
类型 |
说明 |
按键名 |
pin |
---|---|---|---|
pair |
触发配对 |
KEY5 |
P1_2 |
switch report rate |
切换上报率 |
KEY4 |
P0_6 |
switch report |
开关上报 |
KEY3 |
P0_2 |
slave 示例会用到 1 个按键,参考下表:
类型 |
说明 |
按键名 |
pin |
---|---|---|---|
slave cmd |
翻转 master 和 slave 的 LED |
KEY5 |
P1_2 |
配置选项
APP_MSG_COUNT_BLINK_TH
修改 master 向 slave 方向的数据传输时的 LED 闪烁频率。APP_PAIR_TIME
修改 master 按键配对时间和 slave 上电配对时间。编译和下载
该示例可以在 SDK 文件夹中找到:
Project file:
samples\ppt\ppt_sync\proj_master\rtl87x2g\mdk
samples\ppt\ppt_sync\proj_slave\rtl87x2g\mdk
Project file:
samples\ppt\ppt_sync\proj_master\rtl87x2g\gcc
samples\ppt\ppt_sync\proj_slave\rtl87x2g\gcc
编译和运行该示例请遵循以下步骤:
打开项目文件。
要编译目标文件, 请参考 快速入门 中 编译 APP Image 中列出的步骤。
编译成功后,项目文件所在目录的子目录
bin
下会生成app bin文件app_MP_sdk_xxx.bin
。在EVB板上按下reset按钮,程序将开始运行。
测试验证
将两个示例工程分别烧录到两个EVB板后,用按键控制,然后使用 Debug Analyzer
工具获取日志、观察LED状态,查看运行结果。
测试阶段
首次使用此示例时,没有绑定信息,按下reset按钮后,两端都会自动进入配对状态,打印下面的日志。
[APP] !**app_sync_start: pair
配对成功后会打印下面的日志,并且点亮link status led。
[APP] !**app_sync_event_cb: paired
Master 连上之后默认会打开数据上报,此时 master 和 slave 会以相同的频率闪烁 data transmit led。 按下 master 的 switch report rate 按键,切换 master 上报率,会看到 master 和 slave 的 data transmit led 闪烁频率改变。 上报率切换顺序为 125, 250, 500, 1000, 2000, 4000 的循环,默认 1000。 led 在默认闪烁频率下,1K 时 1s 翻转一次,4K 时 0.25s 翻转一次,125 时 8s 翻转一次,其他依次类推。
按下 master 的 switch report 按键一次,开关 master 数据上报。当上报关闭时,master 和 slave 的 data transmit led 停止闪烁。
按下 slave 的 slave cmd 按键一次,master 和 slave 的 slave cmd led 同时翻转。
按下 master 的 pair 按键一次,master 会重新进入配对模式。重启 slave,slave 也会重新进入配对模式。重新配对成功后,会打印下面的日志,并且点亮 link status led。
[APP] !**app_sync_event_cb: paired
代码介绍
本章的主要目的是帮助 APP 开发人员熟悉相关的开发流程。本章将按照以下几个部分进行介绍:
源码路径
Project directory:
samples\ppt\ppt_sync\proj_xxx
Source code directory:
samples\ppt\ppt_sync\src
应用程序项目中的源文件当前被分为几个组,如下所示。
└── Project: master(slave)
└── secure_only_app
├── Device includes startup code
├── CMSE Library Non-secure callable lib
├── Lib includes all binary symbol files that user application is built on
├── ROM_NS.lib
├── lowerstack.lib
├── rtl87x2g_sdk.lib
├── rtl87x2g_io.lib
└── ppt_sync_master(slave).lib includes the sync protocol stack lib
├── Peripheral includes all peripheral drivers and module code used by the application
└── APP includes the ble_peripheral user application implementation
├── main_ns.c includes the io, os and platform initialization
├── app_task.c includes app task initialization and main loop
├── app_bsp.c includes the button, led and timer etc. functions
└── app_sync_master(slave).c includes sync protocol state machine management and button/led handle
初始化
当 EVB 板启动并且芯片被重置时,main
函数将被调用,它执行以下初始化函数:
int main(void)
{
/* increase cpu clock to support 4k report rate */
uint32_t actual_mhz = 0;
pm_cpu_freq_set(125, &actual_mhz);
DBG_DIRECT("Non-Secure World: main, clock %dMHz", actual_mhz);
app_task_init();
/* Start scheduler. */
os_sched_start();
/* Should not reach here as the scheduler is already started. */
for (; ;)
{
}
}
pm_cpu_freq_set()
用于提升 CPU 频率,让 4K 高上报率时来得及处理。app_task_init
用于初始化 app task,注册 task 主函数app_main_task
。os_sched_start
用于启动 os scheduler。当调度器启动后,app task 的主函数app_main_task
会得到调度。app_main_task
执行 sync protocol 和相关内容的初始化,示例如下。
void app_main_task(void *p_param)
{
/* This task calls secure side functions. So allocate a secure context for
* it. */
//must locate at the first line
os_alloc_secure_ctx(configMINIMAL_SECURE_STACK_SIZE);
/* avoid ppt initialization conflict with ble psd procedure */
os_delay(1000);
/* init the basic peripheral */
swd_pin_disable(); // On EVB, led pin reuse the swd pin, so need disable the swd
led_init();
app_hw_timer_init();
/* init sync protocol */
app_sync_init();
app_sync_start();
/* init button after app_sync_start since button may trigger interrupt to change the FSM */
btn_init(app_handle_btn);
#if DLPS_EN
/* call pwr_mgr_init last to make sure sync_dlps_init (app_sync_init) execute before DLPS_IORegister (pwr_mgr_init) */
void pwr_mgr_init(void);
pwr_mgr_init();
#endif
while (1)
{
/* nothing to do */
os_delay(1000000);
}
}
注意
io、sync protocol 和平台 power manager 的初始化有一些依赖关系,注意先后顺序。
app_sync_init
会按角色初始化协议,并注册各类回调:
事件回调
app_sync_event_cb
接收回调
app_sync_receive_msg_cb
心跳回调
app_sync_hb_cb
而在 sync_msg_send()
时都会注册消息发送回调 app_sync_send_msg_cb
。
状态机和事件处理
状态机运转的主要函数是 app_sync_start
,它会根据绑定信息和按键(上电状态)等信息决定是执行配对还是连接。
当配对和连接触发后,会产生各类事件,在 app_sync_event_cb
处理。例如配对失败事件,会重新执行 app_sync_start
。
另外按键也会产生事件,app_handle_btn
根据按键类型执行不同的动作,例如执行重新配对、发送数据等。
当 master 停止数据上报时,会进入 heartbeat 低功耗状态,这时会执行心跳回调 app_sync_hb_cb
,通知心跳状态的进出。
数据收发
master 和 slave 之间会相互发送数据。master 打开上报时,会按照上报率定时持续发送消息,双方分别会根据发送和接收的消息数量来闪烁 led。 slave 只有按键按下时,才会发送控制 led 的消息。
定义格式如下,用户可以根据实际需要修改和扩充。
master 上报函数为 app_report_data
,数据格式如下:
/* Data send from master to slave */
typedef struct
{
uint8_t opcode;
uint32_t pkt_id;
uint8_t data[0];
} __attribute__((packed)) app_master_pdu_t;
slave 下发的控制双方 led 状态函数为 app_send_cmd
,数据格式如下:
/* Data send from slave to master */
typedef struct
{
uint8_t opcode;
bool state;
} __attribute__((packed)) app_slave_pdu_t;