PRF Dongle¶
重要
此例程仅存在于特殊版本的SDK中,如有需要请联系Panchip。
1 功能概述¶
此sample为pan107/pan101上演示Dongle配合108鼠标端控制功能
2 环境要求¶
board:
pan107QFN32核心板/pan101MSOP10核心板 + evb底板uart0: 设置P16,P17作为默认的LOG输出端口,波特率921600
3 编译和烧录¶
例程位置:<home>\nimble\samples\solutions_hid\prf_dongle\keil_107x
使用keil进行打开项目进行编译烧录,需要先移植确认flm文件(modules\hal\panchip\panplat\pan1070_hal_release\mcu_misc)拷贝至keil安装目录
4 演示说明¶
4.1 单设备配对流程¶
keil全擦芯片后,编译烧录boot程序
pan10xx_mcu_boot\keil,之后烧录prf_dongle程序,此时进入对码状态Dongle端在2412 MHz频点、地址
{ 0x7b, 0x41, 0x29, 0x71 }(PIPE0)进行扫描PAN108鼠标进入强制配对,在相同频点和地址发送鼠标端的MAC地址
PAN107 Dongle收到配对请求后:
回复本地MAC地址
根据Dongle MAC地址计算出9个私有跳频频点
将鼠标MAC地址后4位设置为PIPE1的接收地址
鼠标收到Dongle回复后:
计算出相同的9个私有跳频频点
切换到私有地址和频点通信
Dongle在PIPE1上接收到鼠标数据后,结束对码状态,进入正常通信模式
4.2 双设备配对(可选)¶
通过修改宏PAIR_ONLY_ONE=0,可以支持第二个设备配对:
第一个设备配对成功后,保持连接
第二个设备进入配对状态
Dongle将第二个设备分配到PIPE2
两个设备可以同时工作,通过重传机制实现并发通信
注意: PAIR_ONLY_ONE=1(默认)时仅支持单设备,性能最优;=0时支持双设备,但需要合理调度上报率。
5 开发说明¶
5.1 Flash配置及接口说明¶
PAN107(512K 32pin)芯片作为调试芯片,最终PAN101(仅4个IO:P00 P01作为烧录脚,可以复用;P13 P14作为USB通信线,无Reset脚,reset需要重新上电;16K RAM 256K flash)作为实际使用芯片
为确保PAN107编译的程序可以直接切换到PAN101芯片中
BOOT默认划分40k flash,APP默认划分440k flash,可在samples\solutions_hid\keil_107x\configuration\sdk_config.h中查看
CONFIG_ENABLE_BOOTLOADER=1:程序从boot启动后跳转到APP编译地址0xA000,需要先进行boot烧录
CONFIG_ENABLE_BOOTLOADER=0:设置0可以将APP编译到0x0地址,rebuild烧录后,芯片不含boot区域
其他配置可以参考,不建议改动
// <h> Flash Partition Config
// <e> Enable Bootloader
// <i> Enable bootloader for current App Project.
// <i> That means, App Image would not be generated (linked) at Flash 0 address, instead, it would be generated (linked) at flash address right after Bootloader Flash Partition.
#define CONFIG_ENABLE_BOOTLOADER 1
// <o> Bootloader Flash Partition Size (KB)
// <i> Note that partition size should be multiple of 4KB!
#define CONFIG_FLASH_PARTITION_BOOTLOADER_SIZE_KB 40
// <s> Bootloader Project Path (Directory)
// <i> Specify relative or absolute path of Bootloader project.
// <i> NOTE here we should use slash ('/') as path separator instead of backslash ('\')!
#define CONFIG_BOOTLOADER_PROJECT_PATH "../../bootloader/keil_107x"
// <e> Forcibly Build Bootloader Project
// <i> Build bootloader project:
// <i> - AFTER current App Image build done
// <i> - BEFORE Bootloader/App image merging (if enabled).
#define CONFIG_FORCE_BUILD_BOOTLOADER_PROJECT 0
// <o> Select Bootloader Build Command
// <i> Here provides two build commands for selection, they are completely equal with corresponding buttons on Keil UI.
// <0=> Build
// <1=> Rebuild
#define CONFIG_BOOTLOADER_BUILD_COMMAND 0
// <q> Show Bootloader Build Logs
// <i> Show bootloader build logs in Build Output window of current App project.
#define CONFIG_SHOW_BOOTLOADER_BUILD_LOG 1
// </e> Forcibly Build Bootloader Project End
// <e> Merge Bootloader and App Into One Single Image
// <i> Copy bootloader image to App 'Images' folder and then merge bootloader and app into one single image.
// <i> It is recommended to flash the Merged Image when using PanLink or JFlash Tool.
#define CONFIG_MERGE_IMAGES 1
// <s> Merged Image Name
// <i> Specify the name of generated merged image.
#define CONFIG_MERGED_IMAGE_NAME "nImageMerged"
// </e> Enable App Image Header End
// <o> App Flash Partition Size (KB)
// <i> Note that partition size should be multiple of 4KB!
#define CONFIG_FLASH_PARTITION_APP_SIZE_KB 440
// <o> App Backup Flash Partition Size (KB)
// <i> Note that partition size should be multiple of 4KB!
#define CONFIG_FLASH_PARTITION_APP_BACKUP_SIZE_KB 0
// <o> KVStore Flash Partition Size (KB)
// <i> Note that partition size should be multiple of 8KB!
#define CONFIG_FLASH_PARTITION_KVSTORE_SIZE_KB 16
// <o> User Custom Flash Partition Size (KB)
// <i> Note that partition size should be multiple of 4KB!
#define CONFIG_FLASH_PARTITION_USER_CUSTOM_SIZE_KB 12
samples\solutions_hid\bootloader\Keil_107x\project.sct 中限制了RAM使用大小16K
#! armcc -E
#include ".\configuration\sdk_config.h"
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LOAD_FLASH CONFIG_FLASH_PARTITION_BOOTLOADER_ADDR CONFIG_FLASH_PARTITION_BOOTLOADER_SIZE
{
FLASH_TEXT +0
{
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
SRAM_DATA_TEXT 0x20000000 0x0000C000 // 48KB Common SRAM for PAN107x SoC
{
.ANY (+RW +ZI)
*.o (.ramfunc)
}
}
以上,确保107芯片上编译验证后可以进行直接切换下载到101芯片中
BOOT跳转注意点:
可以使用 boot工程中BOOT_ENABLE_USB_DFU来控制实现boot升级流程,也可以不使用,最终跳转接口jump_to_app
Flash存读接口:
参考prf dongle代码中,对 配对的mac地址的操作,参考代码在200k位置进行配对信息存储
/* 200k start save pair addr two */
FMC_ReadStream(FLCTL, PRF_PAIR_ADDR_FLASH_ADDR0, CMD_DREAD, read_addr0, 6);
FMC_ReadStream(FLCTL, PRF_PAIR_ADDR_FLASH_ADDR1, CMD_DREAD, read_addr1, 6);
FMC_WriteStream(FLCTL, PRF_PAIR_ADDR_FLASH_ADDR0, &prf_state.pair_private_addr[0][0], 6);
FMC_WriteStream(FLCTL, PRF_PAIR_ADDR_FLASH_ADDR1, &prf_state.pair_private_addr[1][0], 6);
5.2 PRF说明¶
5.2.0 关键配置宏¶
在app_prf.c中有两个重要的配置宏:
#define PRF_DBG_PIN 0 // RF调试引脚使能
#define PAIR_ONLY_ONE 1 // 单设备模式(默认)
PAIR_ONLY_ONE宏说明:
值 |
模式 |
说明 |
|---|---|---|
1(默认) |
单设备模式 |
- 仅支持1个设备配对 |
0 |
双设备模式 |
- 支持2个设备同时配对 |
修改方法:
// 在 app_prf.c 中修改
#define PAIR_ONLY_ONE 0 // 改为0启用双设备模式
注意:
双设备模式下,第二个设备的程序需要设置
PAIR_COMBO_DG_DEV2=1来区分设备类型建议在单设备稳定后再尝试双设备模式
5.2.1 初始化¶
pan_prf_config_t rx_config =
{
.work_mode = (prf_mode_t)PRF_MODE_ENHANCE,
.chip_mode = (prf_chip_mode_sel_t)PRF_CHIP_MODE_SEL_XN297,
.trx_mode = (prf_trx_mode_t)PRF_RX_MODE,
.phy = (prf_phy_t)PRF_PHY_2M,
.crc = (prf_crc_sel_t)PRF_CRC_SEL_CRC16,
.src = (prf_scramble_sel_t)PRF_SRC_SEL_EN,
.mode_conf = (prf_mode_conf_sel_t)PRF_BLE_CONF,
.rx_timeout = 10000,
.rf_channel = PAIR_PUBLIC_CHANNEL,
.tx_no_ack = DISABLE,
.trf_type = (prf_trf_t)PRF_TRF_NORMAL,
.rx_length = 64,
.sync_length = 4,
.crc_include_sync = ENABLE,
.src_include_sync = ENABLE,
.sync = PAIR_PUBLIC_ADDR,
.pid_manual_flag = ENABLE,
.tx_power = 9,
.pipe = PRF_PIPE0,
};
void mouse_prf_init(void)
{
ana_prf_ldo_en();
panchip_prf_init(&rx_config);
/* init not init channel, must init channel after init */
panchip_prf_set_chn(rx_config.rf_channel);
/* adr match bit match whole absolutely */
PRI_RF_SetAddrMatchBit(PRI_RF, 0);
/* disable pid err isr */
panchip_prf_pid_cfg(&rx_config, 0);
/* enable len err isr */
panchip_prf_rx_length_irq_cfg(ENABLE);
#if PRF_DBG_PIN
PRI_RF_WRITE_REG_VALUE(PRI_RF, TEST_MUX02, TST_MUX_SELECT_11, 0x14); // tx on
SYS->P1_MFP |= SYS_MFP_P10_LL_DBG_11;
PRI_RF_WRITE_REG_VALUE(PRI_RF, TEST_MUX02, TST_MUX_SELECT_09, 0x15); // rx on
SYS->P0_MFP |= SYS_MFP_P04_LL_DBG_9;
PRI_RF_WRITE_REG_VALUE(PRI_RF, TEST_MUX02, TST_MUX_SELECT_10, 0x17); // data
SYS->P0_MFP |= SYS_MFP_P07_LL_DBG_10;
PRI_RF_WRITE_REG_VALUE(PRI_RF, TEST_MUX03, TST_MUX_SELECT_12, 0x13); // acc match
SYS->P0_MFP |= SYS_MFP_P05_LL_DBG_12;
#endif
mouse_prf_pair_init();
panchip_prf_trx_start();
}
全局变量
rx_config,部分来源于config文件,部分来源于直接配置,定义好后,panchip_prf_init(&rx_config);会进行除了频点之外的初始化,一定要在之后进行频点设置panchip_prf_set_chn(rx_config.rf_channel);init后,设置地址全匹配,关闭pid err中断,开启len err中断,rf状态可控,增强型模式下,一定会进行完成
r->t/timeout/crc/len err状态,中断内控制好下一次trx start之前进行flash操作、状态控制,不会引起rf死机状态PRF_DBG_PIN控制lldbg信号,可以抓取rf工作中的时序,但需要注意,开启debug信号时会一定程度影响rf,crc率会变高,关闭后正常mouse_prf_pair_init();中获取dongle mac地址,计算出配对频点(通过dongle mac后四字节),并且设置可能存储过的配对地址作为rf 收取地址私有频点计算:
// app_prf.c 中的定义 uint16_t channel_list_private[9] = { 2404, 2412, 2418, 2430, 2438, 2444, 2456, 2474 }; // 实际使用8个频点,第9个(索引8)固定为2412作为备用
/* set PRI_RF_MODE_SEL_RX addr will set the rx addr & pipe */ /* set PRI_RF_MODE_SEL_TX addr will set the single tx addr, no set tx will use init tx addr */ /* set PRI_RF_MODE_SEL_TRX addr will set the trx addr both, no set tx will use init tx addr */ panchip_prf_set_addr(addr_format, 4, PRF_PIPE1, PRI_RF_MODE_SEL_RX); #if !PAIR_ONLY_ONE panchip_prf_set_addr(addr_format, 4, PRF_PIPE2, PRI_RF_MODE_SEL_RX); // 双设备模式 #endif
设置PRI_RF_MODE_SEL_RX地址仅设置接收PIPE,不会设置发送地址
rx isr中需要设置payload并且设置回复时的tx地址,设置发送地址参考
/* set addr will set the tx addr, if want to ack data from dynamic rx pipe ,rx isr must set tx addr */ CONFIG_RAM_CODE void app_prf_set_tx_addr(uint8_t addr) { #if SET_TX_ADDR_DIRECT / 1.25us */ uint32_t tx_addr;
tx_addr = (addr[0]) | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
PRI_RF_WRITE_REG_VALUE(PRI_RF, R05_TX_ADDR_L, L32B, tx_addr);
#else
/* 6us no used third param */
panchip_prf_set_addr(addr, 4, PRF_PIPE0, PRI_RF_MODE_SEL_TX);
#endif
}
5. 最后进行panchip_prf_trx_start();开启tx;
#### 5.2.2 时间说明
说明比较重要的时间量取参数

1. timeout debug信号结束到进入timeout中断:9us
2. 设置频点时间:50us
3. trx start调用到debug信号拉取到发送出数据:24us
4. DG端 rx自动转tx发送出时间:26us
5. trx start执行占用时间
6. rx isr中需要设置payload并且设置回复时的tx地址,设置地址时,可以快速设置4字节地址或者调用底层封装接口设置,分别占用1us或者6us,影响还好,就算当前次不能及时设置好地址,依然会在下次配对地址收到数据后在对应地址回复出
```c
/* set addr will set the tx addr, if want to ack data from dynamic rx pipe ,rx isr must set tx addr */
CONFIG_RAM_CODE void app_prf_set_tx_addr(uint8_t *addr)
{
#if SET_TX_ADDR_DIRECT
/* 1.25us */
uint32_t tx_addr;
tx_addr = (addr[0]) | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
PRI_RF_WRITE_REG_VALUE(PRI_RF, R05_TX_ADDR_L, L32B, tx_addr);
#else
/* 6us no used third param */
panchip_prf_set_addr(addr, 4, PRF_PIPE0, PRI_RF_MODE_SEL_TX);
#endif
}
5.2.3 多pipe使用说明¶
107相对于108,增加feature 多pipe地址收取的功能,灵活使用可以实现配对地址和多通道地址同时可以收取回复数据,基于此feature可以扩展多个主机设备配对同一dongle,目前主机端最快速度在250us内可以完成发收,所以多设备自行处理的条件下,通过重传可以做到至少2个设备配对同一dongle后,可以达到1000hz上报率
演示说明:
准备2个108 8k鼠标,鼠标1下载默认程序,鼠标2下载 PAIR_COMBO_DG_DEV2=1的第二设备程序
编译下载PAIR_ONLY_ONE=0的107 dongle程序
鼠标1进入配对状态,复位107,鼠标1配对成功,鼠标1不移动情况下鼠标2进入配对或者上电状态,鼠标2配对成功
鼠标1可以达到1000hz上报率,鼠标2默认配对后125hz上报率
对码说明参考演示说明部分的第四点,补充说明鼠标1和鼠标2的区别在于,配对过程数据字段,回复的数据除了各自mac地址,还有额外的数据字段区分对应配对到哪一个pipe,107 rf中确认私有mac搜索到数据通信后不再添加其他地址,重新上电会重新进入可添加pipe地址状态
pkt_pair.magic = PAIR_MAGIC;
#if PAIR_COMBO_DG_DEV2
pkt_pair.type = 0x20;
#else
pkt_pair.type = PAIR_MOUSE_8K_FLAG;
#endif
memcpy(pkt_pair.mac, pair_ctrl.pair_own_addr, 6);
memcpy(tx_payload.data, &pkt_pair, 9);
5.3 USB说明¶
USB init软件过程基本与108一致,其他部分使用也一致
硬件需要注意,101/107系列早期存在USB有问题版本,接入hub并且在hub上的第一个口通常能识别成功但也不稳定,直插线的方式在大部分电脑上都不能成功识别,一定要选用MPC版本之后USB修复后的芯片
void usb_init(void)
{
usbd_desc_register(0, hid_descriptor);
usbd_add_interface(0, usbd_hid_init_intf(0, &intf0, standard_keyboard_report, DEF_Intface0_ReportDes_SIZE));
usbd_add_endpoint(0, &hid_intf0_in_ep);
usbd_add_interface(0, usbd_hid_init_intf(0, &intf1, keyboard_report, DEF_Intface1_ReportDes_SIZE));
usbd_add_endpoint(0, &hid_intf1_in_ep);
usbd_add_endpoint(0, &hid_intf1_out_ep);
usbd_add_interface(0, usbd_hid_init_intf(0, &intf2, dfu_report, DEF_Intface2_ReportDes_SIZE));
usbd_add_endpoint(0, &hid_intf2_in_ep);
usbd_add_endpoint(0, &hid_intf2_out_ep);
usbd_initialize(0, USB_BASE, usbd_event_handler);
}
6 RAM/Flash资源使用情况¶
PAN107x资源配置:
Flash Total: 508 KB (0x7F000)
SRAM Total: 48 KB (0xC000)
实际使用情况(单设备模式 PAIR_ONLY_ONE=1):
Flash Size: ~38.82 KB
RAM Size: ~10.48 KB
实际使用情况(双设备模式 PAIR_ONLY_ONE=0):
Flash Size: ~40 KB (+1.2 KB)
RAM Size: ~11 KB (+0.5 KB)
资源占用分析:
Flash主要占用:
PRF协议栈代码: ~15KB
USB HID驱动: ~10KB
Bootloader跳转逻辑: ~5KB
应用层代码: ~8KB
RAM主要占用:
2个Ring Buffer: 2 × 448 = 896字节
PRF状态管理: ~1KB
USB缓冲区: ~2KB
系统栈和堆: ~6KB
优化建议:
关闭日志:
DBG_PRF_LOG_ENABLE=0可节省~2KB Flash关闭调试引脚:
PRF_DBG_PIN=0可提升RF性能单设备优先: 如果不需要多设备,保持
PAIR_ONLY_ONE=1减小Ring Buffer: 如果数据量不大,可以减小
RINGBUFFER_SIZE