• [转发]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	oolsin"
    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%kalimbaappsa2dp_sinksbc_decoder.xip "[%debugtransport%]"
    
    cscript //NoLogo //B xip_set_transport.vbs %adkpath%kalimbaappsa2dp_sinkaptx_decoder.xip "[%debugtransport%]"
    
    cscript //NoLogo //B xip_set_transport.vbs %adkpath%kalimbaappsa2dp_sinkaptx_acl_sprint_decoder.xip "[%debugtransport%]"
    cscript //NoLogo //B xip_set_transport.vbs %adkpath%kalimbaappsa2dp_sinkaac_decoder.xip "[%debugtransport%]"
    
    set origpath=%cd%

    DSP工程的调试接口需要设置,否则编译时会报错找不到调试器。

    3.5. 编译DSP工程

    echo. *** compile DSP app ***
    cd /D %adkpath%kalimbaappsa2dp_sink
    call %adkpath%xideinxipbuild.exe -f sbc_decoder.xip
    
    cd /D %adkpath%kalimbaappsa2dp_sink
    call %adkpath%xideinxipbuild.exe -f aptx_decoder.xip
    
    cd /D %adkpath%kalimbaappsa2dp_sink
    call %adkpath%xideinxipbuild.exe -f aptx_acl_sprint_decoder.xip
    
    cd /D %adkpath%kalimbaappsa2dp_sink
    call %adkpath%xideinxipbuild.exe -f aac_decoder.xip

    每个VM工程包含一个主工程和多个DSP子工程。

    3.6. 复制psr文件

    cd /D %origpath%
    call %adkpath%	oolsincopyfile %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%xideinxipbuild.exe -f %projectname%.xip
    
    echo. *** erase board ***
    call %adkpath%	oolsinBlueFlashCmd.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 imageheaders headers_temp
    xcopy /E imageprompts prompts_temp
    xcopy /E image
    efname refname_temp
    copy /b imageaudio_prompt_config.csr audio_prompt_config_temp.csr
    
    call rmdir /S /Q image
    mkdir image
    
    xcopy /E headers_temp "imageheaders"
    xcopy /E prompts_temp "imageprompts"
    xcopy /E refname_temp "image
    efname"
    copy /b audio_prompt_config_temp.csr "imageaudio_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%	oolsinmake -R BLUELAB=%adkpath%	ools -f %projectmakefile%.mak flash
    
    cd /D %origpath%
    
    echo. *** merge psr file to board ***
    call %adkpath%	oolsinpscli.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%	oolsinpscli.exe -TRANS "%debugtransport%" cold_reset
    
    echo. *** dump file from board ***
    cd /D %origpath%%ReleasePackageName%"BT_Program file"
    call %adkpath%	oolsinBlueFlashCmd.exe -TRANS "%debugtransport%" dump %projectpsr3%

    3.10. 压缩源码

    echo. *** copy library file to BT_Source code ***
    cd /D %origpath% 
    xcopy /E %adkversion% "%ReleasePackageName%BT_Source codeBT_Source code"
    
    echo. *** copy source file to BT_Source code ***
    xcopy /E %adkpath%apps%projectpath% "%ReleasePackageName%BT_Source codeBT_Source codeParasol_TWS_Code"
    
    echo. *** compress code ***
    call "C:Program FilesWinRAR
    ar.exe" a -ep1 -o+ -ibck %ReleasePackageName%"BT_Source code"BT_SourceCode.rar "%ReleasePackageName%
    BT_Source codeBT_Source code"
    rd /s /Q "%ReleasePackageName%BT_Source codeBT_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%firmwareassistedunifiedgordonloader_unsigned.xdv loader_unsigned.xdv
    
    copy /b %adkpath%firmwareassistedunifiedgordonloader_unsigned.xpv loader_unsigned.xpv
    
    copy /b %adkpath%firmwareassistedunifiedgordonstack_unsigned.xdv stack_unsigned.xdv
    
    copy /b %adkpath%firmwareassistedunifiedgordonstack_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%	oolsincopyfile %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%	oolsinvmbuilder -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%	oolsinBlueFlashCmd.exe -TRANS "%debugtransport%" erase
    call %adkpath%	oolsinBlueFlashCmd.exe -TRANS "%debugtransport%" merge
    
    echo. *** merge signed psr file to board ***
    call %adkpath%	oolsinpscli.exe -TRANS "%debugtransport%" merge image_signed.psr
    
    echo. *** cold reset ***
    call %adkpath%	oolsinpscli.exe -TRANS "%debugtransport%" cold_reset
    
    echo. *** dump signed file from board ***
    cd /D %origpath%%ReleasePackageName%"BT_Program file"
    call %adkpath%	oolsinBlueFlashCmd.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 FilesWinRAR
    ar.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
  • 相关阅读:
    ActiveMQ学习第八篇:Consumer
    ActiveMQ学习第七篇:Messaage
    线性判别分析LDA
    逻辑回归
    那些年,曾踩过的Spark坑
    HBase表创建、删除、清空
    python的多线程
    python的多进程
    python实现读写txt文件
    python的封包和解包
  • 原文地址:https://www.cnblogs.com/fbli/p/8724220.html
Copyright © 2020-2023  润新知