[转发]CSR8670的DFU功能
本文源自:https://blog.csdn.net/wzz4420381/article/details/52371409
作者:RyomaWang
申明:为了保持原作者内容,这里不进行任何修改,后续另写一篇随笔,作为补充和说明。
1. DFU简介
- DFU全称是Device Firmware Upgrade,是一种通过USB升级设备程序的机制,能用来升级以下软件组件:
- 固件协议栈
- VM应用程序
- VM文件系统内的其它文件(语音提示音、额外语言包)
- PS Keys
- DFU协议被USB实施者论坛标准化为一个设备类规范。CSR兼容这个规范,且包含加密检查
- 在制造时设备烧录的程序有RSA公钥
- DFU文件用RSA私钥加密,确保只有为此产品定制的DFU文件能被终端用户使用
2. DFU升级过程
- Loader是出厂时烧录进芯片的
- PS Keys存储了系统的配置
- Firmware是固件协议栈
- VM文件系统包含了VM app和语音提示音
2.1. 详细执行过程
这个章节列出了在使用DFU机制时的选择和限制:
- loader不能被升级
- 这使得DFU升级过程是安全的,loader总是存在且原封不动,因此在升级失败后DFU过程仍可重复
- 固件协议栈可以被升级(但不是必须的)
- 固件协议栈可以不包含在DFU文件里,这种情况下固件不会被更新。
- 如果默认boot模式没有主机接口,必须包含固件协议栈(否则产品只有协议栈,没有VM,没有主机接口,因此不能工作)
- 任何DFU文件内的PS Keys都可以被修改
- VM文件系统可以被升级(但不是必须的)
- 如果VM文件系统存在于DFU文件内,VM文件系统被替换成新的
- 不能单独升级VM文件系统内的文件,文件必须是连续的且没有间隙
2.2. DFU升级工具
DFU升级工具有两种:
- DFUWizard:需要用户安装CSR DFU驱动才能开始DFU过程
- HidDfu:不需要用户安装驱动,使用USB HID接口执行DFU
2.3. PS Keys
PS Keys的类型有很多种:
- 未保护固件(FW)和虚拟机(VM)Keys:
- 这些Keys不需要被签名,但签名也不会有任何问题
- 被保护FW Keys
- 这些Keys被保存在loader内的FW公钥认证
- 被保护VM Keys
- 这些Keys被保存在被保护FW Keys内的VM公钥认证
- 虚拟Keys,有着专门用途
2.4. DFU事件序列
DFU事件序列如下:
- 设备正常运行在独立模式
- USB插入,设备被枚举成USB设备
- 一个用户USB命令或按键序列切换到DFU模式(这导致用户在mode 0内reboot,用户接口在这个模式内必须可用)
- DFUWizard命令设备切换到Loader模式,设备reboot且loader被激活(当使用HidDfu时不需要这个步骤)
- DFU文件被下载到设备且由loader处理
- 设备reboot回到mode 0(当使用HidDfu时不需要)
- 设备reboot回到独立模式
- 设备检测到到USB连接且枚举为一个USB设备
3. 生成DFU文件
官方手册的步骤比较详细,但每次生成代码需要手动操作。我写了一个批处理文件,实现了编译、烧录、生成DFU、生成release文件一键操作。
3.1. 设置CSR安装路径
:: set CSR install path
set dfutoolspath="C:\ADK4.0.0\tools\bin"
set adkpath="C:\ADK4.0.0"
set debugtransport=SPITRANS=USB SPIPORT=0
set adkversion=adk4.0.0
这里的debugtransport指向USB-SPI调试器,在执行批处理文件过程中,确保PC与编程器已经连接。
3.2. 设置全局变量
:: set project path
set ReleasePath=released
set ReleaseVersion=0.0.13
set ReleasePackageName=BT%ReleaseVersion%
set ReleaseNoteName=ReleaseNote_BT%ReleaseVersion%
set projectpath=parasol_v%ReleaseVersion%
set projectmakefile=Speaker.parasol_released
set projectname=speaker
set projectpsr1=sink_system_csr8670
set projectpsr2=Speaker_with_TWS_CNS10001v4
set projectpsr3=Music5_bt_%ReleaseVersion%
set dfupsrfw=example_DFU_fw_Music5_bt_%ReleaseVersion%
set dfupsrvm=example_DFU_vm_Music5_bt_%ReleaseVersion%
projectmakefile需要与工程的编译文件对应。
3.3. 创建release文件夹
:: create package dir
rd /s /Q %ReleasePackageName%
mkdir %ReleasePackageName%
mkdir %ReleasePackageName%\"BT_Program file"
mkdir %ReleasePackageName%\"BT_Source code"
mkdir %ReleasePackageName%\"BT_Upgrade file"
- 首先删除同名文件夹,再分别创建各文件夹
- 第一个文件夹存工厂烧录文件
- 第二个文件夹存源代码(如果库文件被修改了,也要包含在内)
- 第三个文件夹存DFU文件
3.4. 更新调试接口
:: update debug transport in XIP files
cscript //NoLogo //B xip_set_transport.vbs %adkpath%\apps\%projectpath%\%projectname%.xip "[%debugtransport%]"
cscript //NoLogo //B xip_set_transport.vbs %adkpath%\kalimba\apps\a2dp_sink\sbc_decoder.xip "[%debugtransport%]"
cscript //NoLogo //B xip_set_transport.vbs %adkpath%\kalimba\apps\a2dp_sink\aptx_decoder.xip "[%debugtransport%]"
cscript //NoLogo //B xip_set_transport.vbs %adkpath%\kalimba\apps\a2dp_sink\aptx_acl_sprint_decoder.xip "[%debugtransport%]"
cscript //NoLogo //B xip_set_transport.vbs %adkpath%\kalimba\apps\a2dp_sink\aac_decoder.xip "[%debugtransport%]"
set origpath=%cd%
DSP工程的调试接口需要设置,否则编译时会报错找不到调试器。
3.5. 编译DSP工程
echo. *** compile DSP app ***
cd /D %adkpath%\kalimba\apps\a2dp_sink
call %adkpath%\xide\bin\xipbuild.exe -f sbc_decoder.xip
cd /D %adkpath%\kalimba\apps\a2dp_sink
call %adkpath%\xide\bin\xipbuild.exe -f aptx_decoder.xip
cd /D %adkpath%\kalimba\apps\a2dp_sink
call %adkpath%\xide\bin\xipbuild.exe -f aptx_acl_sprint_decoder.xip
cd /D %adkpath%\kalimba\apps\a2dp_sink
call %adkpath%\xide\bin\xipbuild.exe -f aac_decoder.xip
每个VM工程包含一个主工程和多个DSP子工程。
3.6. 复制psr文件
cd /D %origpath%
call %adkpath%\tools\bin\copyfile %adkpath%\apps\%projectpath%\configurations\%projectpsr3%.psr %ReleasePackageName%\BT_Upgrade file\%projectpsr3%.psr"
这里的psr3其实包含了三个部分:psr1、psr2、与项目有关的配置改动。
psr1和psr2是CSR默认的配置。
3.7. 生成未加密的工厂烧录文件
cd /D %adkpath%\apps\%projectpath%
call %adkpath%\xide\bin\xipbuild.exe -f %projectname%.xip
echo. *** erase board ***
call %adkpath%\tools\bin\BlueFlashCmd.exe -TRANS "%debugtransport%" erase
echo. *** delete the image directory before copying files into it ***
echo. *** this will also flash the unsigned image onto the board
echo. *** prevent voice file from delect ***
call rmdir /S /Q headers_temp
call rmdir /S /Q prompts_temp
call rmdir /S /Q refname_temp
del /f /s /Q audio_prompt_config_temp.csr
mkdir headers_temp
mkdir prompts_temp
mkdir refname_temp
xcopy /E image\headers headers_temp
xcopy /E image\prompts prompts_temp
xcopy /E image\refname refname_temp
copy /b image\audio_prompt_config.csr audio_prompt_config_temp.csr
call rmdir /S /Q image
mkdir image
xcopy /E headers_temp "image\headers\"
xcopy /E prompts_temp "image\prompts\"
xcopy /E refname_temp "image\refname\"
copy /b audio_prompt_config_temp.csr "image\audio_prompt_config.csr"
call rmdir /S /Q headers_temp
call rmdir /S /Q prompts_temp
call rmdir /S /Q refname_temp
del /f /s /Q audio_prompt_config_temp.csr
%adkpath%\tools\bin\make -R BLUELAB=%adkpath%\tools -f %projectmakefile%.mak flash
cd /D %origpath%
echo. *** merge psr file to board ***
call %adkpath%\tools\bin\pscli.exe -TRANS "%debugtransport%" merge "%ReleasePackageName%\BT_Upgrade file\%projectpsr3%.psr"
这里完成了4件事:
- 编译VM工程
- 擦除目标板
- 烧录VM文件系统到目标板
- 烧录psr文件到目标板
在执行第3部之前,需要首先删除image文件夹。image文件夹的截图如下:
image文件夹由如下部分组成:
- VM应用(vm.app)
- 各个DSP工程的映像(aac_decoder等几个decoder)
- 语音提示音(headers、prompts、refname)
headers文件夹内的文件数量与pskey中设定的语音提示音数量是对应的。
语音提示音文件夹是通过sink configuration tool生成的,然后通过编译工程来添加到最终生成的image.fs文件里。所以在删除image文件夹之前需要把相关内容缓存一下,并在生成image之前再次放回到image文件夹。
把image和psr一起烧录进目标板后,就可以读出完整的工厂烧录文件。
echo. *** cold reset ***
call %adkpath%\tools\bin\pscli.exe -TRANS "%debugtransport%" cold_reset
echo. *** dump file from board ***
cd /D %origpath%\%ReleasePackageName%\"BT_Program file"
call %adkpath%\tools\bin\BlueFlashCmd.exe -TRANS "%debugtransport%" dump %projectpsr3%
3.10. 压缩源码
echo. *** copy library file to BT_Source code ***
cd /D %origpath%
xcopy /E %adkversion% "%ReleasePackageName%\BT_Source code\BT_Source code\"
echo. *** copy source file to BT_Source code ***
xcopy /E %adkpath%\apps\%projectpath% "%ReleasePackageName%\BT_Source code\BT_Source code\Parasol_TWS_Code\"
echo. *** compress code ***
call "C:\Program Files\WinRAR\rar.exe" a -ep1 -o+ -ibck %ReleasePackageName%\"BT_Source code"\BT_SourceCode.rar "%ReleasePackageName%
\BT_Source code\BT_Source code"
rd /s /Q "%ReleasePackageName%\BT_Source code\BT_Source code\"
这里首先把有修改的库文件和源码一起拷贝到目标文件夹下,然后调用了WinRAR提供的压缩程序用来生成压缩文件。
3.11. 生成已加密的image文件
echo. *** generate keys ***
cd /D %origpath%\dfu_key
copy /b keys.private.key %origpath%\%ReleasePackageName%\"BT_Upgrade file"\keys.private.key
copy /b keys.public.key %origpath%\%ReleasePackageName%\"BT_Upgrade file"\keys.public.key
cd /D %origpath%\%ReleasePackageName%\"BT_Upgrade file"
:: call %dfutoolspath%\dfukeygenerate.exe -o keys
echo. *** sign firmware ***
copy /b %adkpath%\firmware\assisted\unified\gordon\loader_unsigned.xdv loader_unsigned.xdv
copy /b %adkpath%\firmware\assisted\unified\gordon\loader_unsigned.xpv loader_unsigned.xpv
copy /b %adkpath%\firmware\assisted\unified\gordon\stack_unsigned.xdv stack_unsigned.xdv
copy /b %adkpath%\firmware\assisted\unified\gordon\stack_unsigned.xpv stack_unsigned.xpv
call %dfutoolspath%\dfukeyinsert -v -o loader_signed -l loader_unsigned.xdv -ks keys.public.key
call %dfutoolspath%\dfusign -v -o stack_signed -s stack_unsigned.xpv -ks keys.private.key
echo. *** copy image.fs to BT_Upgrade file ***
call %adkpath%\tools\bin\copyfile %adkpath%\apps\%projectpath%\image.fs app.fs
echo. *** sign app ***
call %dfutoolspath%\dfukeyinsert -v -o image_signed -ps %projectpsr3%.psr -ka keys.public.key
call %dfutoolspath%\dfusign -v -o image_signed -h app.fs -ka keys.private.key
echo. *** build binary ***
call %adkpath%\tools\bin\vmbuilder -size 16064 merge.xpv stack_signed.xpv image_signed.fs
上述代码完成了如下几件事:
- 生成密钥,这个密钥需要保存好,后续release DFU文件时需要用到
- 加密固件,包括loader和stack
- 加密VM app和psr,生成加密后的image文件
3.12. 生成已加密的工厂烧录文件
echo. *** merge signed xpv file to board ***
call %adkpath%\tools\bin\BlueFlashCmd.exe -TRANS "%debugtransport%" erase
call %adkpath%\tools\bin\BlueFlashCmd.exe -TRANS "%debugtransport%" merge
echo. *** merge signed psr file to board ***
call %adkpath%\tools\bin\pscli.exe -TRANS "%debugtransport%" merge image_signed.psr
echo. *** cold reset ***
call %adkpath%\tools\bin\pscli.exe -TRANS "%debugtransport%" cold_reset
echo. *** dump signed file from board ***
cd /D %origpath%\%ReleasePackageName%\"BT_Program file"
call %adkpath%\tools\bin\BlueFlashCmd.exe -TRANS "%debugtransport%" dump %projectpsr3%_signed
- 首先把已加密的image文件merge到目标板
- 然后merge已加密的psr文件
- 最后dump出已加密的工厂烧录文件
如果设备出厂时烧录的是已加密的烧录文件,后续DFU升级就可以更改被保护的PS Keys,否则只能更改未被保护的PS Keys。
3.13. 生成DFU文件
echo. *** sign PSKEYs to be included in the DFU image ***
cd /D %origpath%\%ReleasePackageName%\"BT_Upgrade file"
copy %origpath%\%dfupsrvm%.psr app_vm.psr
copy %origpath%\%dfupsrfw%.psr app_fw.psr
call %dfutoolspath%\dfusign -v -o dfu_vm_signed -pa app_vm.psr -ka keys.private.key
call %dfutoolspath%\dfusign -v -o dfu_fw_signed -ps app_fw.psr -ks keys.private.key
echo. *** generate the DFU file ***
call %dfutoolspath%\dfubuild -v -pedantic -f %projectpsr3%.dfu -uv 0x0a12 -up 0x0001 -ui "ADK DFU" -s stack_signed.xpv -d
stack_signed.xdv -h image_signed.fs -p3 . dfu_fw_signed.stack.psr dfu_vm_signed.app.psr
echo. *** delete middle files ***
cd /D %origpath%\%ReleasePackageName%\"BT_Upgrade file"
del /f /s /Q dfu_fw_signed.stack.psr
del /f /s /Q dfu_vm_signed.app.psr
del /f /s /Q image_signed.fs
del /f /s /Q image_signed.psr
del /f /s /Q loader_signed.xdv
del /f /s /Q loader_unsigned.xdv
del /f /s /Q merge.xdv
del /f /s /Q stack_signed.xdv
del /f /s /Q stack_unsigned.xdv
del /f /s /Q loader_signed.xpv
del /f /s /Q loader_unsigned.xpv
del /f /s /Q merge.xpv
del /f /s /Q stack_signed.xpv
del /f /s /Q stack_unsigned.xpv
DFU文件由以下部分组成:
- 已加密的stack
- 已加密的image
- 已加密的psr,包括vm和fw两部分
DFU文件中的psr会覆盖掉设备原有的psr。
3.14. 打包release文件
echo. *** copy release note ***
copy %origpath%\%ReleaseNoteName%.xlsx %ReleaseNoteName%.xlsx
echo. *** package all files ***
cd /D %origpath%
call "C:\Program Files\WinRAR\rar.exe" a -ep1 -o+ -ibck %ReleasePackageName%.rar %ReleasePackageName%
4. 总结
- DFUWizard只支持windows平台,别的平台需要另行开发。
- loader最好要加密,且生成的密钥需要妥善保存。如果密钥丢失会导致后续DFU升级都不能成功,只能重新生成密钥并重新烧录loader。
- 如果设备中的loader是未加密的,在跨ADK版本升级时(4.0.0升级到4.0.1),即使DFU升级过程完成了,新的程序也无法正常运行,原因就是被保护PS Keys没有升级成功,导致程序崩溃。
- 如果启用了UART口,进入DFU模式时芯片会reboot失败,因为UART和USB口功能冲突。这种情况下,DFU模式需要从reboot mode 1启动,且确保在reboot mode 1内把host interface设成USB。
// --------MODE0--------------------------------------------------------
// BOOTMODE_KEY_LIST_0: Overwrite :
// HOST_INTRFACE (1F9)
// USB PRODUCT ID (2bf)
&04B0 = 01F9 02BF
// BOOTMODE_KEY_TABLE_0+0: PSKEY_HOST_INTERFACE = USB
&04B8 = 0002
// BOOTMODE_KEY_TABLE_0+1: USB PID = 0xffff (DFU)
&04B9 = ffff
// PSKEY_INITIAL_BOOTMODE
&03cd = 0001
- 如果PC识别不到设备,需要检查PS Keys是否符合以下设置:
- PSKEY_USB_PIO_VBUS:开发板需要设置成VDD_CHG
- PSKEY_USB_DFU_PRODUCT_ID=0xffff
[转发]CSR8670的DFU功能的更多相关文章
- 十、CSR8670的DFU功能[补充]
前一篇转载的博文很清楚,全面的介绍了DFU功能的实现步骤.关于DFU功能,你还需要知道以下信息: 一.image.fs,firmware,loader,psr之间的关系 图1-1 image.fs示意 ...
- 定向转发和重定向实现 <select >下拉表单数据传送
定向转发的特点: (1). 实行转发时浏览器上的网址不变 (如果你这点忽视了,那你就要接受我无尽的鄙视吧! 哇咔咔~~~) (2). 实行转发时 : 只有一次请求. 不信,看这下面的 ...
- SSH有端口映射功能(访问本地端口=访问远程端口)
大部分SSH连接软件都有SSH通道转发功能,就是用这个实现的. 如果Delphi在代码上实现的话,用libSSH 或者 SecureBridge都可以. 代码基本不用帖,思路给大家讲一下吧. SSH有 ...
- SSH端口转发详解及实例
一.SSH端口转发简介 SSH会自动加密和解密所有SSH客户端与服务端之间的网络数据.但是,SSH还能够将其他TCP端口的网络数据通SSH链接来转发,并且自动提供了相应的加密及解密服务.这一过程也被叫 ...
- ServletRequest HttpServletRequest 请求方法 获取请求参数 请求转发 请求包含 请求转发与重定向区别 获取请求头字段
ServletRequest 基本概念 JavaWeb中的 "Request"对象 实际为 HttpServletRequest 或者 ServletRequest, ...
- SSH端口转发详解及实例-转载
作者:珂儿吖 出处:http://www.cnblogs.com/keerya/ 目录 1.1 SSH端口转发的两大功能 实验一:实现SSH端口转发——本地转发 实验二.实现SSH端口转发——远程转发 ...
- Linux 网卡驱动学习(九)(层二转发)
1.mac 地址表的自学习过程 port1上的A计算机要与port2上的B计算机通信时,A发到交换机上,交换机收到信息后,交换机先记录发port1所相应的a的mac地址并记录在自己的mac表中,然后再 ...
- 6tunnel数据转发
6tunnel 一条命令实现端口映射.数据转发,实现代理服务器功能. 安装脚本 #!/bin/bash DIR=/opt/software INSTALL=6tunnel-master.tar.gz ...
- Qt编写气体安全管理系统15-网络转发
一.前言 在本系统中网络转发是个什么功能含义呢,其实就是将本地采集设备的所有数据打包发送到指定的网络地址,默认采用UDP的形式,无连接开销小,我也是看到很多的组态软件有这个功能,其实现有的很多的气体探 ...
随机推荐
- 题解 CF600E 【Lomsat gelral】
没有多少人用莫队做吗? 蒟蒻水一波莫队 这是一道树上莫队好题. 时间复杂度(\(n\sqrt{n}logn\)) 蒟蒻过菜,不会去掉logn的做法qaq 思路很简单: 1.dfs跑一下树上点的dfs序 ...
- 5G:今天不谈技术,谈谈需求和应用
4G改变生活,5G改变社会.随着2019年5G手机的发布,5G时代已经拉开帷幕,无数嗅觉灵敏的投资人和创业者在研究5G行业的投资机会. 但是,市场研究侧重于技术细节与上游产业链设备投资居多,对于贴近消 ...
- .NET Core 3.0 构建和部署
Default Executables 默认可执行文件 在 dotnet build 或 dotnet publish 期间,将创建一个与你使用的 SDK 的环境和平台相匹配的可执行文件. 和其他本机 ...
- Kubernetes2-K8s的集群部署
一.简介 1.架构参考 Kubernetes1-K8s的简单介绍 2.实例架构 192.168.216.51 master etcd 192.168.216.53 node1 192.168.216 ...
- 设计模式(十九)State模式
在面向对象编程中,是用类表示对象的.也就是说,程序的设计者需要考虑用类来表示什么东西.类对应的东西可能存在于真实世界中,也可能不存在于真实世界中.对于后者,可能有人看到代码后会感到吃惊:这些东西居然也 ...
- django-数据库之连接数据库
1.连接数据库出现的一些问题 基本目录如下: 首先我们pip install pymysql 然后在项目中,进行配置settings.py: 然后在__init__.py中进行输入: 启动服务器: 报 ...
- 选择器, ,>,+,~
一.后代选择器 选取指定元素的后代元素 与子元素选择器相比,后代选择器选取的不一定是直接后代(儿子),而是作用于所有后代元素(儿子.孙子.重孙…)都可以. 二.(>)子元素选择器 选取某个元素的 ...
- 消息中间件-RabbitMQ环境搭建
一直在传统行业工作(早九晚五不加班),没有考虑消息中间件的性能,所以一直再用activeMQ也没有想过学习别的中间件,时间长也没什么技术上的进步,而且感觉到了 工作的麻木,所以决定学一些新的技术(其实 ...
- 阿里云和微软共同开源的 OAM 对 Kubernetes 开发人员意味着什么?
上周,微软和阿里巴巴共同推出了开放应用模型(OAM),用于定义部署在任何地方的应用模型的一种规范.Rudr是Microsoft基于Kubernetes环境的OAM标准实现. 我用了一个周末来了解OAM ...
- Scrapy 框架入门简介
一.Scrapy框架简介 Scrapy 是用 Python 实现的一个为了爬取网站数据.提取结构性数据而编写的应用框架. Scrapy 常应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中. ...