HID 私有协议

本示例用两个工程分别扮演HID 私有协议用户指南中的master和slave两个角色,他们之间可以互相发送消息,演示该协议的基本使用方法:

  • Master首次使用或者按键触发时自动配对,Dongle首次使用或者上电时自动配对。

  • Master和Slave自动回连。

  • Master自动按照上报率上报数据,按键切换上报率、开关上报。

  • Slave按键下发指令。

  • 连线、数据发送的led指示。

环境需求

该示例支持以下开发工具包:

开发套件

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

更多要求,请参考 快速入门

硬件连线

请参考 快速入门 中的 EVB接口和模块

示例会用到3个LED显示相关状态,参考下表:

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个按键,参考下表:

master按键

类型

说明

按键名

pin

pair

触发配对

KEY5

P1_2

switch report rate

切换上报率

KEY4

P0_6

switch report

开关上报

KEY3

P0_2

slave示例会用到1个按键,参考下表:

slave按键

类型

说明

按键名

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

编译和运行该示例请遵循以下步骤:

  1. 打开项目文件。

  2. 要编译目标文件, 请参考 快速入门编译APP Image 中列出的步骤。

  3. 编译成功后,项目文件所在目录的子目录 bin 下会生成app bin文件 app_MP_sdk_xxx.bin

  4. 要下载app bin到EVB板,请参考 快速入门MPTool 中列出的步骤。

  5. 在EVB板上按下reset按钮,程序将开始运行。

测试验证

将两个示例工程分别烧录到两个EVB板后,用按键控制,然后使用 DebugAnalyzer 工具获取日志、观察LED状态,查看运行结果。

测试阶段

  1. 首次使用此示例时,没有绑定信息,按下reset按钮后,两端都会自动进入配对状态,打印下面的日志。

    [APP] !**app_sync_start: pair
    

    配对成功后会打印下面的日志,并且点亮link status led。

    [APP] !**app_sync_event_cb: paired
    
  2. 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翻转一次,其他依次类推。

  3. 按下master的switch report按键一次,开关master数据上报。当上报关闭时,master和slave的data transmit led停止闪烁。

  4. 按下slave的slave cmd按键一次,master和slave的slave cmd led同时翻转。

  5. 按下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;