• 详解蓝牙空中升级(BLE OTA)原理与步骤

    如何实现BLE OTA?什么叫DFU?如何通过UART实现固件升级?又如何通过USB实现固件升级?怎么保证升级的安全性?什么叫双区(dual bank)DFU?什么叫单区(single bank)DFU?什么叫后台式(background)DFU? 本文将对上述问题进行探讨。 1.概述 所谓DFU(Device Firmware Update),就是设备固件升级的意思,而OTA(Over The Air)是实现DFU的一种方式而已,准确说,OTA的全称应该是OTA DFU,即通过空中无线方式实现设备固件升级。只不过大家为了方便起见,直接用OTA来指代固件空中升级(有时候大家也将OTA称为FOTA,即Firmware OTA,这种称呼意思更明了一些)。只要是通过无线通信方式实现DFU的,都可以叫OTA,比如2G/3G/4G/WiFi/蓝牙/NFC/Zigbee,他们都支持OTA。DFU除了可以通过无线方式(OTA)进行升级,也可以通过有线方式进行升级,比如通过UART,USB或者SPI通信接口来升级设备固件。不管采用OTA方式还是有线通信方式,DFU包括后台式(background)和非后台式两种模式。后台式DFU,又称静默式DFU(Silent DFU),在升级的时候,新固件在后台悄悄下载,即新固件下载属于应用程序功能的一部分,在新固件下载过程中,应用可以正常使用,也就是说整个下载过程对用户来说是无感的,下载完成后,系统再跳到BootLoader模式,由BootLoader完成新固件覆盖老固件的操作,至此整个升级过程结束。比如智能手机升级Android或者iOS系统都是采用后台式DFU方式,新系统下载过程中,手机可以正常使用哦。非后台式DFU,在升级的时候,系统需要先从应用模式跳入到BootLoader模式,由BootLoader进行新固件下载工作,下载完成后BootLoader继续完成新固件覆盖老固件的操作,至此升级结束。早先的功能机就是采用非后台式 DFU来升级操作系统的,即用户需要先长按某些按键进入bootloader模式,然后再进行升级,整个升级过程中手机正常功能都无法使用。下面再讲双区DFU(dual bank)和单区DFU(single bank),双区或者单区DFU是新固件和老固件覆盖的两种方式。后台式DFU必须采用双区模式进行升级,即老系统(老固件)和新系统(新固件)各占一块bank(存储区),假设老固件放在bank0中,新固件放在bank1中,升级的时候,应用程序先把新固件下载到bank1中,只有当新固件下载完成并校验成功后,系统才会跳入BootLoader模式,然后擦除老固件所在的bank0区,并把新固件拷贝到bank0中。非后台式DFU可以采用双区也可以采用单区模式,与后台式DFU相似,双区模式下新老固件各占一块bank(老固件为bank0,新固件为bank1),升级时,系统先跳入BootLoader模式,然后BootLoader程序把新固件下载到bank1中,只有新固件下载完成并校验成功后,才会去擦除老固件所在的bank0区,并把新固件拷贝到bank0区。单区模式的非后台式DFU只有一个bank0,老固件和新固件分享这一个bank0,升级的时候,进入bootloader模式后立马擦除老固件,然后直接把新固件下载到同一个bank中,下载完成后校验新固件的有效性,新固件有效升级完成,否则要求重来。跟非后台式DFU双区模式相比,单区模式节省了一个bank的Flash空间,在系统资源比较紧张的时候,单区模式是一个不错的选择。不管是双区模式还是单区模式,升级过程出现问题后,都可以进行二次升级,都不会出现“变砖”情况。不过双区模式有一个好处,如果升级过程中出现问题或者新固件有问题,它还可以选择之前的老固件老系统继续执行而不受其影响。而单区模式碰到这种情况就只能一直待在bootloader中,然后等待二次或者多次升级尝试,此时设备的正常功能已无法使用,从用户使用这个角度来说,你的确可以说此时设备已经“变砖”了。所以说,虽然双区模式牺牲了很多存储空间,但是换来了更好的升级体验。可参考下面三个图来理解上述过程。 2. Nordic nRF5 SDK DFU工作原理 如文章“nRF5 SDK软件架构及softdevice工作原理”所述,Nordic nRF5 SDK软件架构跟其他家有点不一样,程序存储区最开始部分放得不是Bootloader,而是蓝牙协议栈Softdevice,应用程序则紧挨着Softdevice,Bootloader则被nRF5 SDK放在程序存储区的最上面,整个存储区结构图如下所示。如果用户还有Flash数据需要存放,那么这些数据紧挨着BootLoader下面。 目前Nordic SDK默认只提供非后台式DFU开箱即用的例子(SDK16.0开始也支持后台式DFU框架),即系统必须先跳到BootLoader中,然后才能通过BLE/UART/USB去接收新的固件。如上所示,如果采用双区模式DFU,那么Bank0放的是应用程序,即老固件,Bank1放的是新固件。平时,Bank1为空或者忽略,系统只跑Bank0里面的应用程序;升级的时候,先跳到BootLoader,然后接收新固件并把它放在Bank1中,最后把Bank1里面的固件拷贝到Bank0中。如果采用单区模式,则没有Bank1这个区。平时,系统只跑Bank0里面的代码;升级的时候,跳到BootLoader,先擦除Bank0里面的老程序,并把新固件直接放在Bank0中。 根据升级时如何跳转到Bootloader,Nordic SDK又将DFU分为按键式DFU和非按键式(Buttonless)DFU,所谓按键式DFU,就是上电时长按某个按键以进入bootloader模式,而非按键式DFU,就是整个DFU过程中设备端无任何人工干预,通过BLE/UART/USB接口给应用程序发送一条指令,应用程序收到指令后再自动跳入bootloader模式。不管是按键式DFU还是非按键式DFU,两者只是进入BootLoader的方式不一样,其余基本一样,尤其是BootLoader工作过程基本上是一模一样的。后面只会阐述非按键式DFU的过程,按键式DFU以此类似,就不再赘述。 程序跳到BootLoader后,根据BootLoader需不需要对新固件进行验签,Nordic SDK又把DFU分为开放式DFU和安全式DFU(又称签名DFU)。开放式DFU,BootLoader不做任何验证,直接把新固件接收下来。安全式DFU,BootLoader存有一把公钥,BootLoader会先用这把公钥验证新固件的签名,只有验签通过,才允许后续的工作:比如把新固件接收下来;如果验签失败,BootLoader将拒绝升级,重新跳回应用程序。 BootLoader可以通过不同的通信接口来接收新的固件,目前Nordic SDK支持BLE,UART和USB三种接口,所以大家可以在Nordic SDK中看到如下三种工程目录: 其中pca0056表示nRF52840对应的开发板编号,S140对应Softdevice的型号,然后ble有两个目录:无debug和有debug,uart和usb也包含同样的两个目录。有debug和无debug两者功能是一样的,两者的区别是:debug版本BootLoader支持日志打印(大家可以通过打印出的日志去理解BootLoader的工作过程),并可以忽略各种校验,debug版本占据的代码空间要大很多;无debug版本 BootLoader不支持日志打印功能并且版本和有效性校验是强制的。正式量产的时候推荐使用无debug版本以节省代码空间。这里要强调一下,不管是debug版本还是无debug版本,两者都可以用Keil进行单步和断点调试。 BLE,UART和USB只是通信方式不一样,他们遵守的DFU流程是一模一样的,这里会以BLE通信接口为例,详细阐述DFU过程,UART和USB与之类似,就不再赘述。 讲述DFU升级之前,先讲一下nRF52的启动流程,上电后,系统先执行softdevice,softdevice通过读取UICR一个寄存器的值,来判断目前系统是否有BootLoader,如果没有BootLoader,系统直接跳到application;如果有BootLoader,系统先跳到BootLoader,BootLoader再根据目前的情况来决定是进入升级模式还是跳往application,BootLoader主要判断如下几种情况: 按键是否按下 保持寄存器GPREGRET1是否为0xB1 上次DFU过程是否还在进行中 应用程序校验是否通过 如果按键没有按下,GPREGRET1不为0xB1,本次复位不是上次DFU的继续,并且应用程序校验通过,那么BootLoader就会直接跳到application,去执行application应用程序。那怎么去校验应用程序的有效性呢?为此BootLoader引入了一个放在Flash的结构体参数:m_dfu_settings_buffer(数据类型:nrf_dfu_settings_t),这个结构体参数虽然只有896字节,但由于Flash只能按页擦除,所以这个参数实际占用了一个Flash page,这个page称为settings page,settings page放在Flash的最后一个页面,settings page目前有2个版本:版本1(SDK15.2及以前版本)和版本2(SDK15.3及以后版本),版本2可以兼容版本1,前面所述的896字节是指settings page版本2的大小。Settings page包含的信息比较多,大家用得比较多的是: 各种版本信息 DFU升级过程信息 Application image的CRC值和大小 应用程序的bonding信息 Init command内容 application/softdevice的启动校验信息(版本2才有) 版本1的settings page只校验application image的CRC值,如果CRC匹配,则认为application有效。版本2的settings page不仅可以校验application image的CRC值,还可以校验application/softdevice的CRC值或者hash值或者签名,你可以选择你自己想要的校验方式,只有CRC值或者hash值或者签名校验通过(三选其一),应用程序才算有效,这时BootLoader才会跳到application去执行。为了保证settings page在发生意外时,比如写settings page过程中发生了复位或者掉电,系统也能正确恢复,SDK15及以后版本引入了一个backup page,backup page也占用一个Flash page,内容和settings page一模一样。 上面是没有触发升级的情况下nRF52的正常启动流程,那如果要执行DFU升级,流程又是怎么样的呢?下面详细讲一下无按键式BLE OTA的工作流程。 1)      正常启动后,系统运行在应用程序中,此时手机通过app发送一条开始DFU的指令给设备,设备收到指令后,将GPREGRET1赋值0xB1,并触发软复位 2)      复位后,系统再次进入BootLoader,因为GPREGRET1等于0xB1,BootLoader进入DFU模式,等待新固件接收 3)      手机先将init packet发送给设备,设备先做前期检验prevalidation,主要是各种版本校验以及签名验签,校验通过后,更新settings  page并准备开始数据接收 4)      接收新固件。每接收4kB数据,回复一次CRC校验值,直至整个新固件image接收完毕,如果新固件校验通过(版本1校验CRC值,版本2校验hash值),就会去invalidate(无效化) bank0里面的老固件,更新settings page,并再次触发软复位 5)      BootLoader启动后发现有新固件需要activate(激活),此时会去擦掉bank0里面的固件,并把bank1里面的固件拷贝到bank0,然后更新settings page,并再次触发软复位。注:上面讲的是dual bank的流程,single bank与之相似,只不过在第3)步的时候就会去擦除老固件 6)      BootLoader再次启动后,检查新image的有效性,校验通过后,跳到新的application去执行代码 从上面流程可以看出,DFU过程中,系统需要跑两段完全独立的代码:Application和BootLoader,Application和BootLoader都支持蓝牙功能,也就是说,两者都有自己的蓝牙广播和蓝牙连接。这里面有一个问题:当系统从Application跳到BootLoader后,手机怎么辨别两者为同一个设备?很多人会说,可以让BootLoader和Application两者的广播名字一样,根据广播名字的一致性,来判断二者来自同一个设备。这种方法存在两个问题:一大部分手机都支持GATT cache(缓存)功能,当application跟手机相连后,手机会把application的GATT数据缓存下来以加快下次连接的速度(这个现象在苹果手机最明显),之后如果系统跳到BootLoader,然后再跟手机相连,如果两者的蓝牙设备地址一样,手机会认为是同一个设备,从而跳过服务发现的过程而直接使用之前缓存下来的GATT数据,这样会导致BootLoader的服务无法被手机发现,从而出现升级失败。二如果多个设备同时在升级,而我们仅仅依靠广播名字来决定两者属不属于同一个设备,这会导致设备A application有可能跟设备B的BootLoader进行错配。为了解决这个问题,Nordic提出了两套方案。方案一,假设application的蓝牙设备地址为x,跳到BootLoader后蓝牙设备地址会变成x+1,这样手机就可以通过这种地址+1的方式来辨别两者属不属于同一个设备,由于application和BootLoader使用不同的蓝牙设备地址,前面的GATT缓存问题也就不存在。关于方案一,有一个问题需要特别注意:如果你想修改例子默认的蓝牙设备地址(比如使用IEEE的public蓝牙MAC地址),此时一定要记得同时更改application和BootLoader的蓝牙设备地址,使他们满足+1的条件,否则Nordic手机DFU库无法辨别两者是否属于同一个设备,以致于无法完成OTA过程。方案二,application和BootLoader的蓝牙设备地址一模一样,但设备跟手机执行配对和bonding操作,设备跟手机bonding后,就可以支持service changed indicate操作,这样跳到BootLoader后可以让手机主动再执行一次服务发现过程,从而解决GATT缓存问题。 很多人对签名验签不是很理解,这里详细说一下它的工作原理。首先,你需要一对公私钥,其中私钥用来生成新固件的签名,公钥用来验证签名的有效性,大家可以用nrfutil来生成自己需要的公私钥对,公私钥制作成功后,私钥一定要妥善保管(一般放在云端),千万不能丢,否则你自己也无法升级自己的设备;也不能被第三方知道,否则升级的安全性就不能保证了。公钥可以变成一个.c文件,并覆盖DFU工程下的同名文件:dfu_public_key.c 。其次,BootLoader要支持签名验签密码算法,这个DFU代码已经有了,并且有四种后端可选:micro-ecc,cc310_bl,Oberon和mbedtls,四选其一即可(这4种后端,只有cc310是硬件实现,其余都是软件实现),nRF52840推荐选择cc310作为算法后端,其他nRF52芯片推荐选择micro-ecc作为算法后端。micro-ecc效率高,占用的代码空间最小,但它的版权是CPOL,只要你能接受CPOL,那么推荐使用micro-ecc;反之,如果接受不了CPOL版权,而且硬件又不支持cc310,那么推荐使用Oberon,不过Oberon占用的代码空间比micro-ecc要大一些,这个大家注意一下。再次,手机端要生成新固件的签名,并把新固件的签名传给设备端。大家还是可以用nrfutil去生成新固件的签名。最后,BootLoader接收到新固件hash值和签名,并使用自己的公钥对该签名进行验签。这里说一下,由于nrfutil是PC端应用程序,所以它可以集成各种加密算法库,并完成上面提及的公私钥对,hash和签名的生成工作。 3. DFU升级步骤详解 3.1 安全式蓝牙空中升级步骤 如前所述,Nordic SDK已经提供了DFU例子,下面我们一步一步给大家讲解如何通过Nordic SDK来实现无按键式蓝牙空中升级。欲实现空中升级,设备需要同时下载softdevice,应用程序,BootLoader程序,以及BootLoader settings page。其中BootLoader代码位于目录:SDK根目录\examples\dfu\secure_bootloader,然后在该目录下选择你对应的板子和工程。Application对应的目录:SDK根目录\examples\ble_peripheral\ble_app_buttonless_dfu,而softdevice所在目录:SDK根目录\components\softdevice。 下面我们以nRF52832/PCA10040和S132/SDK16为例阐述无按键式蓝牙空中升级实现步骤,其他芯片/softdevice/SDK原理与之类似,这里就不再赘述。当然,不同芯片不同softdevice不同SDK,他们的实现脚本还是会有一些细微差别,所以强烈建议大家去百度网盘下载跟大家相匹配的脚本,百度网盘里面各个脚本的命名规则请参考3.2节。 1)      安装PC版nrfutil。nrfutil安装有两种方式,一种是直接下载exe文件,一种是以Python的方式进行安装。nrfutil.exe直接下载链接为:https://github.com/NordicSemiconductor/pc-nrfutil/releases,记得把nrfutil.exe所在目录放在Windows环境变量中。Python方式安装nrfutil步骤如下所示: 安装Python2.7或者Python3.7,下载地址:https://www.python.org/downloads/,安装成功后请确保Windows环境变量包含Python目录 通过pip安装最新版的nrfutil,即打开Windows命令行工具CMD(管理员权限),输入如下命令:pip install nrfutil,即可以完成nrfutil的安装。 安装完成后,在Windows命令行工具输入:nrfutil version,如果可以正确显示版本信息,说明安装已经成功 对于Windows用户,nrfutil运行需要几个特殊的DLL库,而这几个库有些Windows机器是没有的,如此,可往:https://www.microsoft.com/en-us/download/details.aspx?id=40784下载 2)      通过nrfutil生成公私钥对。 私钥生成命令:nrfutil keys generate priv.pem (priv.pem就是私钥) 公钥生成命令:nrfutil keys display --key pk --format code priv.pem --out_file dfu_public_key.c (dfu_public_key.c就是公钥) 大家务必要保存好私钥priv.pem,以后每次升级新固件时,都会通过这个私钥对它进行签名,一旦priv.pem丢失或者被暴露,DFU将无法进行或者变得不安全 3)      请确保已按照“Nordic nRF51/nRF52开发环境搭建”把Nordic nRF5 SDK开发环境搭建成功 4)      生成micro-ecc算法库。由于micro-ecc是第三方算法库,需要用户自己去安装(这个是版权的要求,没办法直接编译放在SDK中)。请先确保电脑已安装了git和GCC编译器,然后直接点击SDK如下目录的build_all脚本,就可以自动完成micro-ecc算法库的安装。为了方便一些开发者评估,我这里在自己电脑上生成了micro-ecc算法库,micro-ecc目录编排结构有两种:SDK14及以后版本是一种目录结构(百度云盘压缩包名称:micro_ecc_new.rar),SDK13和SDK12又是一种目录结构(百度云盘压缩包名称:micro_ecc_old.rar),这两个压缩包只是目录不一样,里面的算法库内容其实是一样的,这两个压缩包大家都可以在前面的百度云盘中找到,以供大家评估使用。大家下载下来后,直接覆盖同名目录即可。注意:百度云盘里面的micro-ecc库仅供大家评估使用,如要商用,请大家按照上面步骤去生成。 5)      编译bootloader代码。将刚才的dfu_public_key.c取代SDK根目录\examples\dfu下的同名文件,然后使用Keil编译如下目录中的工程: SDK根目录\examples\dfu\secure_bootloader\pca10040_ble\arm5_no_packs,或者nRF5SDK160098a08e2\examples\dfu\secure_bootloader\pca10040_s132_ble\arm5_no_packs ,将生成的hex文件改名为:bootloader.hex(注:本文所有项目都会采用Keil工程来讲解,如果你使用其他IDE,请选择其对应的工程文件进行编译,不管是Keil还是其他IDE,除了编译时候选择的工程文件不一样,其余都大同小异,大家可以举一反三完成其他IDE的相应工作) 6)      编译application代码。请编译工程: SDK根目录 \examples\ble_peripheral\ble_app_buttonless_dfu\pca10040\s132\arm5_no_packs,将生成的hex文件改名为:app.hex 7)      生成BootLoader settings page。Bootloader settings page存储在Flash最后一个page,如前所述,BootLoader settings page有2个版本,他们的生成脚本命令如下所示: 版本2生成命令: nrfutil settings generate --family NRF52 --application app.hex --application-version 1 --bootloader-version 1 --bl-settings-version 2 settings.hex 版本1生成命令: nrfutil settings generate --family NRF52 --application app.hex --application-version 1 --bootloader-version 1 --bl-settings-version 1 settings.hex 8)      烧写固件。将上文生成的3个hex文件和softdevice hex文件merge成一个文件,然后通过nrfjprog或者nRF Connect桌面版进行烧写,相关命令如下所示: 合并hex文件命令: mergehex --merge bootloader.hex settings.hex --output bl_temp.hex mergehex --merge bl_temp.hex app.hex s132_nrf52_7.0.1_softdevice.hex --output whole.hex 烧写hex文件命令(以nrfjprog为例): nrfjprog --eraseall -f NRF52 nrfjprog --program whole.hex --verify -f NRF52 nrfjprog --reset -f NRF52 9)      通过nrfutil生成新固件对应的zip包:new_app.zip。zip包包含新固件(新固件广播名改为:Nordic_New,其余跟老固件一模一样)和init包,zip包一般通过云端下发到手机app,手机app再通过蓝牙下载到设备中。生成zip包的命令如下所示: nrfutil pkg generate --application app_new.hex --application-version 2 --hw-version 52 --sd-req 0xCB --key-file priv.pem SDK160_app_s132.zip 其中,--application表示新固件hex文件。--hw-version表示板子版本,只要BootLoader里面的hw version和这里的hw version对应起来,大家可以改成任何自己想要的值。--key-file 表示签名用的私钥文件。--sd-req表示老固件运行在哪个版本softdevice上,这个值一定要跟自己的softdevice相匹配,否则无法升级,各个softdevice版本ID信息可以通过命令“nrfutil pkg generate --help”获得,如下为当前所有softdevice ID列表: 10)   将“new_app.zip”拷贝到手机上。安卓和苹果手机都可以通过微信的‘文件传输助手’拷过去,非常方便。请注意,手机nRF Connect和nRF Toolbox都支持DFU功能,苹果手机拷贝的时候可以随便选择其中一个app。 11)   通过手机版nRF Connect或者nRF Toolbox进行蓝牙空中升级,这里以nRF Connect为例阐述升级详细步骤,nRF Toolbox与此类似,就不再赘述 第8)步完成后,开发板就可以正常跑起来,并广播为Nordic_Buttonless 连接该设备,使能CCCD(这一步可选),然后选择“DFU”,如下所示: 选择“DFU”后,将跳出一个对话框,让你选择新固件对应的zip包。由于zip包放在了微信下面的download目录下,我们需要通过文件浏览器找到这个zip包,大家可以先用系统自带的文件浏览器打开这个zip包(如果打开失败,那么大家就要去下载一些第三方的文件浏览器了,比如es explorer),相关操作界面如下所示: 一旦zip包打开成功,升级过程开始,界面如下所示: 升级成功后,设备将运行新固件,即广播名字将变成:Nordic_New,如下所示: 如上以nRF52832/S132为例阐述了Nordic SDK实现无按键式签名式蓝牙空中升级的详细步骤,Nordic SDK有多个版本,从SDK13.0.0到现在SDK16.0.0,他们的升级步骤基本上一模一样,大家完全可以参考上述步骤来做。SDK12升级步骤也与上述步骤基本一样,唯一如下地方需要注意一下: 编译application代码的时候,把如下语句注掉,否则会造成BootLoader和application两者的hex文件相冲突 3.2节会按照上述步骤,对一些经典的安全式BLE OTA例子进行测试,并生成可直接运行的脚本,以供大家参考。 3.2 各种安全式蓝牙空中升级例子 3.1节是以升级nRF52832 application为例,详细阐述了安全式BLE OTA步骤。除了升级application,有的人还需要升级softdevice和BootLoader;除了52832,有的人还会用52840/52833/52811/52810/51822等;除了SDK16.0.0,有的人还会用SDK15.3/15.2/14.2/12.3等。为此我选了一些经典组合,将他们DFU用得的所有脚本都做好了,并进行了实际测试,有需要的可以去百度网盘下载。这些脚本在百度网盘的命名规则为:安全模式_固件传输接口_升级哪一部分固件_SDK版本号_芯片型号.rar,比如secure_ble_S132_app_SDK160_nRF52832.rar表示采用安全签名,固件通过BLE传输,BLE使用S132协议栈,升级的时候只升级application而不升级BootLoader和SoftDevice,基于SDK16.0.0和nRF52832。 目前百度网盘上传了如下安全式BLE OTA示例脚本(注:这些脚本都经过我的测试,全都可以直接运行): secure_ble_S132_app_SDK160_nRF52832.rar secure_ble_S140_app_sd_bl_SDK160_nRF52840.rar secure_ble_S132_app_SDK153_nRF52832.rar secure_ble_S132_app_SDK152_nRF52832.rar secure_ble_S132_app_SDK150_nRF52832.rar secure_ble_S140_app_SDK150_nRF52840.rar secure_ble_S132_app_SDK142_nRF52832.rar secure_ble_S132_app_SDK123_nRF52832.rar secure_ble_S130_app_SDK123_nRF51.rar 3.3 通过UART口进行安全式固件升级示例脚本 我们以nRF52810为例来阐述如何通过UART进行安全式固件升级步骤: 1)      请参考3.1节第1)到第4)步,完成nrfutil安装,mico-ecc算法库生成,以及公私钥生成 2)      编译bootloader代码。将刚才的dfu_public_key.c取代SDK根目录\examples\dfu下的同名文件,确保sdk_config.h中的NRF_BL_DFU_ENTER_METHOD_BUTTON为1,然后使用Keil编译如下目录中的工程: SDK根目录\ examples\dfu\secure_bootloader\pca10040e_uart\arm5_no_packs ,将生成的hex文件改名为:bootloader.hex 3)      编译application代码。3.1节讲述OTA的时候,我们选择的例子是ble_app_buttonless_dfu,因为我们是通过蓝牙给设备发送一条命令,从而让设备进入DFU模式。通过串口升级固件,如何进入DFU模式,取决于你的应用设计,你可以采用通过发送蓝牙命令让其进入DFU模式,也可以通过上电检测按键是否按下以决定是否进入DFU模式。如果想采用ble_app_buttonless_dfu作为application,那么你需要把该工程中的main函数如下语句删掉(这些语句是为蓝牙版BootLoader设计的,我们现在是UART版BootLoader,不支持这些语句): err_code = ble_dfu_buttonless_async_svci_init(); APP_ERROR_CHECK(err_code); 这里我们选择以上电检测按键的方式来决定是否进入DFU模式,并以ble_app_blinky作为应用例子,请直接编译如下工程: SDK根目录\examples\ble_peripheral\ble_app_blinky\pca10040e\s112\arm5_no_packs,将生成的hex文件改名为:app.hex 4)      生成BootLoader settings page并同时烧写老固件,双击“program.bat”即可完成,这个脚本是使用nrfjprog来完成固件烧写的。 5)      生成新固件zip包并进行UART DFU,双击“dfu.bat”即可完成,这个脚本是使用nrfutil作为UART主机,并将新固件通过电脑COM口传给设备的。请记得一定要修改脚本中的UART对应的电脑COM口,否则升级无法完成。 注:所有bat脚本都可通过右键选择Notepad++打开,然后查看里面包含的具体命令,并按照自己的需求进行修改。如需进一步理解脚本中的命令,请参考3.1节的说明。 上述所有操作步骤已打包并上传到百度网盘,请去网盘下载文件:secure_uart_app_SDK160_nRF52810.rar,这个文件已经过我的测试,大家可以直接使用。 3.4 通过USB口进行安全式固件升级示例脚本 我们以nRF52840为例来讲述如何通过USB进行安全式固件升级,其实通过USB口升级固件步骤与3.3节的操作几乎一模一样,唯一不同的是,选择如下目录的BootLoader工程进行编译: SDK根目录\ examples\dfu\secure_bootloader\pca10056_usb\arm5_no_packs 通过USB口进行安全式固件升级示例脚本已打包并上传到百度网盘,请去网盘下载文件: secure_usb_app_SDK160_nRF52840.rar,这个文件已经过我的测试,大家可以直接使用。 3.5 通过USB口进行开放式固件升级示例脚本 我们还是以nRF52840为例来讲述如何通过USB进行开放式固件升级,其升级步骤与3.3节的操作几乎一模一样,唯一不同的是,选择如下目录的BootLoader工程进行编译: SDK根目录\ examples\dfu\open_bootloader\pca10056_usb\arm5_no_packs 相关脚本已上传百度网盘,请下载: open_usb_app_SDK160_nRF52840.rar,这个文件已经过我的测试,大家可以直接使用。 3.6 开放式蓝牙空中升级(Legacy DFU)步骤 所谓开放式OTA,是指OTA过程中,不需要检验新固件的签名,也就是说BootLoader代码里面不包含公钥及相关密码算法库,升级的时候,只校验版本信息,版本校验通过,就可以开始升级流程。Nordic SDK目前支持两套开放式OTA方案,一套是SDK15和SDK16提供的,一套是SDK9/SDK10/SDK11提供的。SDK15/16提供的开放式OTA工作原理和流程,与安全式OTA基本上一样,只不过删掉了签名验签部分。SDK9/SDK10/SDK11提供的开放式OTA也叫legacy OTA DFU,它的工作流程与SDK15/16略有不同,下面将以nRF52832/S132为例,阐述如何在SDK11中实现无按键式开放式蓝牙空中升级,详细步骤如下所示: 1)         编译bootloader代码,请使用Keil编译目录“nRF5_SDK_11.0.0_89a8197\examples\dfu\bootloader\pca10040\dual_bank_ble_s132\arm5_no_packs”中的工程,将生成的hex文件改名为bootloader.hex 2)         编译application代码,请编译目录“nRF5_SDK_11.0.0_89a8197\examples\ble_peripheral\ble_app_hrs\pca10040\s132_with_dfu\arm5_no_packs”中的工程,将生成的hex文件改名为app.hex 3)         将softdevice,bootloader和app三个hex文件合成一个文件,命令如下所示: mergehex --merge s132_nrf52_2.0.1_softdevice.hex app.hex bootloader.hex –output whole.hex 4)         烧写固件到设备中,大家可以用nRF Connect桌面版烧写,也可以通过nrfjprog烧写,nrfjprog烧写命令如下所示: nrfjprog.exe --eraseall -f NRF52 nrfjprog --program whole.hex --verify -f NRF52 5)         另外我们还需要在Flash中写一个application有效标志位,从而上电后程序直接跑到application中去执行,而不是停留在bootloader中不出来,其对应的命令如下所示: nrfjprog --memwr 0x0007F000 --val 0x01 --verify -f NRF52 6)         用老版本的nrfutil生成新固件对应的zip包。该zip包除了包含新固件image,还包含一些配置信息。升级时,zip包会通过云端下发到手机端app,手机端app再把zip包传给蓝牙设备以进行固件升级。请使用老版本nrfutil(版本号0.3.0)来生成该zip包,老版本nrfutil跟随nRFgo studio一起安装的,只要你安装了nRFgo studio,老版本nrfutil就会自动安装好,并放在目录“C:\Program Files (x86)\Nordic Semiconductor\nRFgo Studio”中。生成zip包对应的命令如下所示: nrfutil dfu genpkg --application app_new.hex --application-version 1 SDK110_app_s132.zip 7)         把上述的‘SDK110_app_s132.zip’拷到手机中,安卓和苹果手机都可以通过微信的‘文件传输助手’拷过去,非常方便。注:手机nRF Connect和nRF Toolbox都支持DFU功能,苹果手机拷贝的时候可以随便选择其中一个app。 8)         使用nRF Connect或者nRF Toolbox来完成DFU过程。这里以nRF Connect为例来阐述整个升级过程。 成功执行完第5)步后,如果开发板运行正常,那么它将进行广播,广播名字为:Nordic_HRM 连接该设备,并使能CCCD,然后选择“DFU” 选择“DFU”后,将跳出一个对话框,让你选择新固件对应的zip包。由于zip包放在了微信下面的download目录下,我们需要通过文件浏览器找到这个zip包,大家可以先用系统自带的文件浏览器打开这个zip包(如果打开失败,那么大家就要去下载一些第三方的文件浏览器了,比如es explorer),相关操作界面如下所示: 一旦zip包打开成功,升级过程开始,界面如下所示: 升级成功,设备将自动启动,此时你会看到新固件已经在运行,广播名字也变成了:Nordic_HRM_new,如下所示: 目前百度网盘上传了如下开放式BLE OTA示例脚本(注:这些脚本都经过我的测试,全都可以直接运行): open_ble_S132_app_SDK110_nRF52832.rar open_ble_S130_app_SDK110_nRF51.rar 如果你的应用是基于SDK11开发的,并且需要集成DFU功能,请参考上述例子ble_app_hrs来移植DFU功能,主要工作包括两部分:一把BLE_DFU_APP_SUPPORT这个宏包括的所有代码拷到你的工程中,二如果你的设备支持bonding的话,还需把Device manager相关代码也拷到你的工程中,如此即可完成DFU功能的移植。 4. 详解如何移植DFU功能到ble_app_uart 为了让SDK14及以后版本的ble_app_uart具有DFU功能,有2种做法,一是把NUS服务移植到ble_app_buttonless_dfu中,这种方法相对来说更简单,大家可以自己去实践一下;二是把DFU服务移植到ble_app_uart中,这种移植方式挑战更大,但更有利于我们理解DFU的工作原理,我们现在就来阐述如何给ble_app_uart加上OTA功能。如前所述,OTA过程中,手机跟设备可以进行配对和bonding,也可以用明文进行蓝牙通信。配对bonding的时候,我们可以让BootLoader和application共享bonding信息,也可以只让application进行配对bonding,而BootLoader还是以明文方式进行蓝牙通信。 Nordic已经把DFU服务做成了一个模块,大家只要把这个模块加到自己的应用中,然后完成一些必须的配置,初始化以及回调函数的撰写,再加上把SVCI模块(SVCI模块主要用来修改BootLoader的一些配置参数)加入到应用中移植即可大功告成。在SDK中,DFU服务的名字是:BLE_DFU_SERVICE,这个服务放在文件ble_dfu.c中,而ble_dfu.c又有两个后端实现:ble_dfu_unbonded.c和ble_dfu_bonded.c,分别对应无bonding明文蓝牙连接和有bonding的蓝牙连接,下面也将分这两种情况详细阐述移植过程。 4.1 明文正常连接OTA(无bonding) 1)      用Keil打开如下工程:SDK根目录\examples\ble_peripheral\ble_app_uart\pca10040\s132\arm5_no_packs 2)      添加DFU服务有关的文件,目录和宏定义。首先添加如下DFU目录及相关文件: 在define中添加这些宏:DEBUG DFU_SUPPORT BL_SETTINGS_ACCESS_ONLY NRF_DFU_SVCI_ENABLED NRF_DFU_TRANSPORT_BLE=1,其中DEBUG宏只是为了调试方便而设置的,跟DFU本身无关。DFU_SUPPORT是我用来控制我添加的DFU代码的,删掉DFU_SUPPORT,将不编译所有DFU有关代码。其余的宏都是系统自带的,如果要支持DFU,就必须要添加。 然后包含如下目录: 3)      修改sdk_config.h文件。首先我们需要使能BLE_DFU模块,及选择OTA蓝牙连接方式,如下为使用明文进行蓝牙通信的配置: #define BLE_DFU_ENABLED 1 #define NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS 0 同时我们还需要修改softdevice配置。现在整个应用包括2个供应商自定义UUID:NUS和DFU(其实这两个UUID可以合成一个,但由于历史原因,DFU和NUS分别使用了两个不同的vs UUID),相应地ATT table size也要变大,然后应用程序RAM起始地址也需要跟着变,如下(注:这里的NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE 设置得稍稍偏大): #define NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE 1600 #define NRF_SDH_BLE_VS_UUID_COUNT 2 修改应用程序RAM起始地址,如下: 4)      修改main.c文件。首先添加如下头文件: #include "ble_dfu.h" #include "nrf_bootloader_info.h" #include "nrf_power.h" 然后在main函数的开始处,添加修改BootLoader广播名字的代码,由于iOS DFU的时候默认就会去改广播名字,为了兼容iOS,这一行代码是必须的: err_code = ble_dfu_buttonless_async_svci_init(); APP_ERROR_CHECK(err_code); 然后在services_init()中添加ble dfu服务 dfus_init.evt_handler = ble_dfu_evt_handler; err_code = ble_dfu_buttonless_init(&dfus_init); APP_ERROR_CHECK(err_code); ble_dfu_evt_handler回调函数的撰写,大家只要按照要求来,就没问题,如果应用只支持一个连接,那么ble_dfu_evt_handler可以直接为空。如果应用支持多个连接,可以参考ble_app_buttonless_dfu做法,这里就不贴代码了。 5)      在跳转到bootloader之前,如果你想做一些专门的代码处理,比如完成pending的Flash操作,比如关闭某些模块,那么你可以注册一个app_shutdown_handler来做这些工作。(注:这一步不是必须的,是可选的!) NRF_PWR_MGMT_HANDLER_REGISTER(app_shutdown_handler, 0); 6)      (这一步可选)之前的ble_app_uart是没有BootLoader的,所以启动起来非常快。现在加了BootLoader代码,为了加快system off唤醒的速度,可以定义如下语句, nrf_power_gpregret2_set(BOOTLOADER_DFU_SKIP_CRC); 然后先disable softdevice,然后再进入system off模式。这一步本身跟DFU没有什么关系,主要是为了加快程序启动速度而另加的。 7)      编译工程,并将生成的hex文件改名为“app.hex” 8)      然后按照3.1节的步骤一步一步完成后续的DFU过程。 4.2 bonding连接OTA 4.1节的工程已经移植了DFU功能,现在我们再把bonding功能移植到4.1节工程上,就可以让我们的应用同时支持DFU和bonding。Bonding功能是通过peer_manager模块来实现的,大家只要把peer_manager有关的文件添加进来,就可以实现bonding的目标。 1)      打开4.1节的工程 2)      添加如下文件: 3)      修改sdk_config.h文件,需要修改多个地方,如下: #define PEER_MANAGER_ENABLED 1 #define FDS_ENABLED 1 #define NRF_SDH_BLE_SERVICE_CHANGED 1 #define NRF_FSTORAGE_ENABLED 1 #define NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS 1 当NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS设为1时,表示application将与主机进行bonding,同时该bonding信息将共享给BootLoader,也就是说,进入bootloader模式后,主机将使用以前的bonding信息与设备进行加密连接。 4)      在main.c文件开头,包含如下头文件: #include "peer_manager.h" 5)      在main函数中添加peer_manager_init(),其定义如下所示: static void peer_manager_init() { ble_gap_sec_params_t sec_param; ret_code_t err_code; err_code = pm_init(); APP_ERROR_CHECK(err_code); memset(&sec_param, 0, sizeof(ble_gap_sec_params_t)); // Security parameters to be used for all security procedures. sec_param.bond = SEC_PARAM_BOND; sec_param.mitm = SEC_PARAM_MITM; sec_param.lesc = SEC_PARAM_LESC; sec_param.keypress = SEC_PARAM_KEYPRESS; sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; sec_param.oob = SEC_PARAM_OOB; sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; sec_param.kdist_own.enc = 1; sec_param.kdist_own.id = 1; sec_param.kdist_peer.enc = 1; sec_param.kdist_peer.id = 1; err_code = pm_sec_params_set(&sec_param); APP_ERROR_CHECK(err_code); err_code = pm_register(pm_evt_handler); APP_ERROR_CHECK(err_code); } 添加pm_evt_handler定义,代码如下所示: static void pm_evt_handler(pm_evt_t const * p_evt) { pm_handler_on_pm_evt(p_evt); pm_handler_flash_clean(p_evt); } 尤其要检查如下代码有没有添加,由于iOS DFU的时候默认就会去改广播名字,为了兼容iOS,这一行代码是必须的 err_code = ble_dfu_buttonless_async_svci_init(); APP_ERROR_CHECK(err_code); 6)      在ble_evt_handler中删除BLE_GAP_EVT_SEC_PARAMS_REQUEST分支,因为这个分支在peer_manager模块中已经进行处理了,这里再处理一次,会产生异常: // case BLE_GAP_EVT_SEC_PARAMS_REQUEST: // // Pairing not supported // err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); // APP_ERROR_CHECK(err_code); // break; 7)      修改advertising_start定义,增加删除bonding信息功能(如果你不需要这个功能,也可以不改) 8)      (此步可选)一般来说,如果用户在手机端把配对信息删掉了,为了安全起见,设备端也需要把相关配对信息清掉,然后才可以允许手机和设备再次进行配对和bonding。如何触发设备端bonding信息的删除操作?可以通过按键检测的方式来做,比如目前我们这个例子的做法。但是有很多设备没有按键,而且很多人希望这种二次配对的操作对用户来说无感,即哪怕用户删掉了手机端配对信息,如果用户想发起第二次配对请求,设备也能接受,而且操作过程跟用户第一次发起配对请求的过程一模一样。Nordic SDK其实是兼容这种操作的,用户只需在pm_evt_handler()中添加如下代码即可: if (p_evt->evt_id == PM_EVT_CONN_SEC_CONFIG_REQ) { pm_conn_sec_config_t cfg; cfg.allow_repairing = true; pm_conn_sec_config_reply(p_evt->conn_handle, &cfg); } 9)      上述所有代码都包括在“BONDING_SUPPORT”宏中。 10)   编译工程,将生成的hex文件改名为app.hex 11)   然后按照3.1节步骤来执行OTA过程,不过如下几点需要注意: 如果你在应用中把NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS设为1,那么bootloader代码就不能采用默认配置,请修改bootloader工程中的sdk_config.h文件中的如下宏定义,然后重新编译生成新的bootloader.hex。 #define NRF_DFU_BLE_REQUIRES_BONDS 1 #define NRF_SDH_BLE_SERVICE_CHANGED 1 在nRF Connect中勾选“keep bond information”选项,如下: 手机连接设备成功后,请手动使能CCCD,以让手机自动发起bonding请求 DFU升级成功后,设备将会与手机自动重连,此时需点击“Refresh services”,以获得设备最新服务列表,如下: 上述代码工程我已打包成:ble_app_uart_ota_SDK16_0_0.rar,并上传到百度网盘,大家下载下来解压缩到:SDK根目录\examples\ble_peripheral这个目录下,就可以直接编译和运行。DFU过程中用到的所有脚本我也帮大家做好了,大家可以直接下载下来使用,其中secure_ble_S132_uart_SDK160_nRF52832_Nobonding.rar对应明文蓝牙传输,secure_ble_S132_uart_SDK160_nRF52832_bonding.rar对应bonding蓝牙传输。 5 手机端DFU参考代码 Nordic不仅提供DFU设备端的参考代码,同时提供手机端的参考代码。Nordic分别开发了Android版和iOS版的DFU库,大家可以直接拿过来使用,集成到自己的移动端app中,这两个库都放在github上,链接如下所示: Android版DFU库:https://github.com/NordicSemiconductor/Android-DFU-Library iOS版DFU库:https://github.com/NordicSemiconductor/IOS-Pods-DFU-Library Nordic还提供了一个移动端app:nRF Toolbox,nRF Toolbox是代码开源的,里面也集成了上面提到的DFU库,大家可以参考nRF Toolbox来开发自己的移动端app。nRF Toolbox源码也可以在github上找到: Android版nRF Toolbox源代码及开发说明请参考:https://github.com/NordicSemiconductor/Android-nRF-Toolbox iOS版nRF Toolbox源代码及开发说明请参考:https://github.com/NordicSemiconductor/IOS-nRF-Toolbox nRF Toolbox软件界面如下所示:

    03-13 109浏览
  • 深入解析:车载以太网DOIP协议

    DoIP 不 用 做 独 立 的 应 用 层 协 议 , 被 ISO在ISO 13400系列文档中被标准化。该协议被视为TCP/IP与更高级别协议,如ISO 14229(UDS)之间的接口。

    01-30 102浏览
  • 物联网协议繁多,各具特色

    物联网协议是指在物联网环境中用于设备间通信和数据传输的协议。根据不同的作用,物联网协议可分为传输协议、通信协议和行业协议。 传输协议:一般负责子网内设备间的组网及通信。例如 Wi-Fi、Ethernet、NFC、 Zigbee、Bluetooth、GPRS、3G/4G/5G等。这些协议能够确保在网络上传输的数据的安全性和可靠性。 通讯协议:主要是运行在传统互联网TCP/IP协议之上的设备通讯协议,负责设备通过互联网进行数据交换及通信。例如 MQTT、CoAP、HTTP等。 行业协议:某个行业范围内统一的标准协议。例如车联网 JT/T808、视频GB/T 28181等。 01、传输协议 协议 协议描述和应用场景 Modbus 协议描述:Modbus协议是一项应用层报文传输协议,包括ASCII、RTU、TCP三种报文类型。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。 应用场景:在工业领域应用广泛。 OPC-UA 协议描述:全称为OPC Unified Architecture(OPC统一架构),是一项开源的、独立于平台的标准协议;通过此协议,使用不同系统的设备可以通过网络在客户端和服务器之间发送消息进行通信。OPC-UA更适用于远程访问。 应用场景:适用于现场设备,控制系统,制造执行系统和企业资源规划系统等应用领域的制造软件。 OPC-DA 协议描述:OPC-DA适用于单系统数据访问。OPC-DA为实时数据访问规范,定义了包括数据值,更新时间与数据品质信息的相关标准。 应用场景:适用于多个供应商设备和控制应用程序之间实现数据交换。 LoRa 协议描述:LoRa是基于Semtech公司开发的一种低功耗局域网无线标准,解决了在同样的功耗条件下比其他无线方式传播的距离更远的技术问题,实现了低功耗和远距离的统一。 应用场景:主要在智慧城市、智慧建筑、智能家居、智能农业、无线工业等各个领域。 ZigBee 协议描述:ZigBee是一种低速短距离传输的无线通信协议,是一种高可靠的无线数传网络,主要特色有低速、低耗电、低成本、支持大量网上节点、支持多种网上拓扑、低复杂度、快速、可靠、安全。ZigBee技术是一种新型技术,它最近出现,主要是依靠无线网络进行传输,它能够近距离的进行无线连接,属于无线网络通讯技术。 应用场景:在工业、农业、智能 家居等领域得到大规模的应用。 Bluetooth 协议描述:蓝牙技术是一种无线数据和语音通信开放的全球规范,它是基于低成本的近距离无线连接,为固定和移动设备建立通信环境的一种特殊的近距离无线技术连接。 应用场景:蓝牙能在包括移动电话、PDA、无线耳机、笔记本电脑、相关外设等众多设备之间进行无线信息交换。 蓝牙、WiFi、ZigBee协议比较 目前来说,WiFi的优势是应用广泛,已经普及到千家万户;ZigBee的优势是低功耗和自组网;UWB无载波无线通信技术的优势是传输速率;蓝牙的优势组网简单。然而,这3种技术,也都有各自的不足,没有一种技术能完全满足智能家居的全部要求。 蓝牙技术的出现使得短距离无线通信成为可能,但其协议较复杂、功耗高、成本高等特点不太适用于要求低成本、低功耗的工业控制和家庭网络。尤其蓝牙最大的障碍在于传输范围受限,一般有效的范围在10米左右,抗干扰能力不强、信息安全问题等问题也是制约其进一步发展和大规模应用的主要因素。 WiFi也是是一种短距离无线传输技术,可以随时接入无线信号,移动性强,比较适合在办公室及家庭的环境下应用。当然WiFi也存在一个致命缺点。由于WiFi采用的是射频技术,通过空气发送和接收数据,使用无线电波传输数据信号,比较容易受到外界的干扰。 ZigBee则是国际通行的无线通讯技术,它的每个网络端口可以最多接入6.5万多个端口,适合家居、工业、农业等多个领域使用,而蓝牙和WiFi网端只能接入10个端口,显然不能适应家庭需要。ZigBee还具有低功耗和低成本优势。 02、通讯协议 协议 协议描述和应用场景 MQT 协议描述:MQTT是基于TCP/IP协议的一种轻量级的发布、订阅信息传输协议,特点报文紧凑、轻量可靠、支持QoS等。 应用场景:为物联网行业推荐协议之一,广泛应用于智能硬件、车联网、能源、电力等场景。 HTTPS 协议描述:HTTP协议超文本传输协议,基于请求/响应模型进行数据传输。 应用场景:适用于对设备硬件和网络带宽充裕的场景。 CoAP 协议描述:CoAP(Constrained Application Protocol)是一种在物联网世界的类web协议,使用了请求/响应交互模型。协议设计精炼, 采用 UDP 协议进行数据传输,适用在资源受限的低功耗设备上,尤其是NB-IoT的设备使用。 应用场景:在水表、电表等资源受限的低功耗设备上应用广泛。 TCP 协议描述:厂商内部发展和采用的标准。私有协议具有灵活性,它往往会在某个公司或者组织内部使用,按需定制,升级方便,灵活性好。具体实现需要客户手动部署。 UDP 协议描述:UDP(用户数据报协议)是一种无连接的协议,它不提供数据传输的可靠性和流控制,但具有较低的时延和较少的开销。 应用场景:主要应用于实时数据传输和设备之间的快速通信,包括实时视频和音频流传输、传感器数据采集和控制信号发送、广播和组播等。由于UDP协议具有低时延、少开销、无需建立连接等特点,能够满足物联网中对快速传输和实时性要求高的应用场景。 MQTT、CoAP协议比较 MQTT是多对多通讯协议用于在不同客户端之间通过中间代理传送消息,解耦生产者与消费者,通过使得客户端发布,让代理决定路由并且拷贝消息。虽然MQTT支持一些持久化,最好还是作为实时数据通讯总线。 CoAP主要是一个点对点协议,用于在客户端与服务器之间传输状态信息。虽然支持观察资源,CoAP最好适合状态传输模型,不是完全基于事件。 MQTT客户端建立长连接TCP,这通常表示没有问题,CoAP客户端与服务器都发送与接收UDP数据包,在NAT环境中,隧道或者端口转发可以用于允许CoAP,或者像LWM2M,设备也许会先初始化前端连接。 MQTT不提供支持消息打类型标记或者其他元数据帮助客户端理解,MQTT消息可用于任何目的,但是所有的客户端必须知道向上的数据格式以允许通讯,CoAP,相反地,提供内置支持内容协商与发现,允许设备相互探测以找到交换数据的方式。 03 行业协议 协议 协议描述和应用场景 GB/T28181 协议描述:国家标准GB/T 28181—2016《公共安全视频监控联网系统信息传输、交换、控制技术要求》,是视频监控领域的国家标准。 应用场景:视频联网传输和设备控制。 JT/T808 协议描述:《道路运输车辆卫星定位系统终端通信协议及数据格式》,主要用于“两客一危”车辆。 应用场景:交通行业应用。 GB3761 协议描述:是一种国标电表协议插件,采用新型的数据采集技术,将电能表的实时工况数据转换成电信号,提供给计量系统,并能进行电能的实时记录、统计、抄表和结算等。 应用场景:电表。 DL/T645 协议描述:DL/T 645是多功能电能表与数据终端设备进行数据交换式的物理连接和协议的规范和标准,本设备依据协议采用中国电力企业联合会提出的DL/T 645-2007《多功能电能表》标准规约,实现设备与多功能电能表的信息通信。 应用场景:电表。 IEC104 协议描述:IEC104规约由国际电工委员会制定。IEC104规约把IEC101的应用服务数据单元(ASDU)用网络规约TCP/IP进行传输的标准,该标准为远动信息的网络传输提供了通信规约依据。采用104规约组合101规约的ASDU的方式后,可很好的保证规约的标准化和通信的可靠性。 应用场景:电力、城市轨道交通。 HJ212 协议描述:《污染物在线监控(监测)系统数据传输标准》环保行业中使用的数据传输标准协议。 应用场景:环保行业。 SL651 协议描述:《水文监测数据通信规约》,水文监测等设备需要遵循该规范。 应用场景:水文监测。

    01-22 115浏览
  • 示波器在以太网传输机制分析中的应用

    本文以双绞线以太网为分析对象,以混合信号示波器为分析工具,深入探秘了两类常见的双绞线以太网的编码,且实地查看并验证了以太网在物理层的信号传输情况。 最后,通过一个实战例子对比了实际网络中软件接收的数据和示波器捕获信号之间的一致性。 本文打通软硬件之间的隔阂,从物理层揭示了以太网数据传输的机制,也充分发挥了现代化混合信号示波器的总线解码能力。 1、以太网概述 以太网(Ethernet)是一种常见的计算机组网技术,其技术标准在IEEE 802.3中规定 [1]。 目前广泛使用的以太网通过双绞线(俗称网线)交换信息,其技术标准主要在TIA/EIA-568中规定 [2]。 本文以最常见的以太网标准为例,利用混合信号示波器的协议解码功能,揭秘以太网上的信号是如何传输的。 通常对于网络数据的分析都在软件上进行,例如著名的Wireshark工具可以对指定网卡上传输的数据进行捕获并解析 [3]。 但这样的操作屏蔽了物理层的差异,本文将更进一步揭秘物理层上数据具体是如何转变成电信号并传输的。 以太网(10 Base-T)和快速以太网(100 Base-TX)可以使用同一种双绞线进行数据传输,其引脚定义如图1所示。 图1. 网线的引脚定义 [1] 以T568B为例,其中用到了4根线,构成2个差分对(TX和RX)。不失一般性,我们取其中一对(TX)作为分析对象。因此需要引出Pin 1和Pin 2,用于连接示波器探头来抓取信号。这里剪开一根网线,在Pin 1和2上分别引出一根导线,做成分析用的专用跳线,如图2所示。 图2. 在双绞线的Pin 1和2上分别引出一根导线 这一对线上传输的是差分信号,因此最好用差分探头(例如TDP1500)。当然这里用到的跳线比较短,用普通的无源探头也可以,只是信号质量会受到一定的影响。 2、10 Base-T以太网 10 Base-T的传输速率是10Mbps,使用曼彻斯特编码(相位编码)数据。“0”用下降沿表示,“1”用上升沿表示。如图3所示,这是一段由示波器抓取到的差分波形。在确认最小脉宽后,可以通过判断周期性的边沿方向来辨识“0”或“1”。 图3. 10 Base-T的曼彻斯特编码解析 接下来,需要将二进制序列组装成数据帧,由于包含多个协议的堆叠(MAC、IP、TCP等),手动解码会比较复杂,可以直接使用示波器的总线解码工具进行解码并显示。如图4所示,将总线设为“Ethernet”,速度设为“10 Base-T”,信号类型设为“差分”,其它选项根据实际情况选择或保持默认就可以了。 图4. 10 Base-T解码设置 解码结果如图5所示,可以看到这是一个IPv4的数据帧,放大后可以看到MAC地址等数据包内的具体内容。 图5. 10 Base-T解码结果 3、100 Base-TX以太网 相比10 Base-T,100 Base-TX带来了10倍的速度提升,达到100Mbps。它的编码协议也变得复杂得多,主要涉及3个关键词:4B5B、MLT-3和NRZ-I。 3.1 4B5B 4B5B表示使用5位二进制编码来表示1组4 bits数据 [4]。这样做的原因是使得传输线上有足够多的跳变用来恢复时钟。4B5B的编码规则是预先定义的,如果仅仅用来解码,只需要查表即可,如图6所示。 举例:“0000”或“1111”如果直接传输,会带来4个一样的编码,很有可能引入较强的直流分量,但经过4B5B编码后,分别变成了“11110”和“11101”,就缓解这个问题了。4B5B的缺点是,需要增加额外的25%传输带宽,因此100 Base-TX虽然数据传输率是100MBps,却需要125Mhz的时钟频率。 图6. 4B5B对应关系表 3.2 MLT-3 MLT-3表示“Multi-Level Transmit”,即使用多个电压级别来传输数据 [5]。MLT-3使用3个电压,在差分传输线上,3个电压可以归一化记为“-1”、“0”和“+1”。 MLT-3通过切换电压来实现跳变,顺序遵循两个规则:一是,如果跳变前电压是-1或+1,则跳变后电压是0;二是,如果跳变前电压是0,则跳变后电压与上一个非0值的电压相反。 因此可简单总结跳变顺序为:-1 → 0 → +1,或+1 → 0 → -1。 3.3 NRZ-I MLT-3描述了电压跳变的规则,但没有说明电压跳变与数据“0”、“1”的关系。NRZ-I为“Non-Return-to-Zero Inverted”的缩写,即不归零反转码。这种编码规定数据“0”不跳变,数据“1”跳变。 3.4 示例 综合前面三个关键词,可以简单概括100 Base-TX的电信号变化规律如下: 100 Base-TX首先通过4B5B编码将每4位数据编码成5位二进制编码;接着使用3种电压传输数据,如果数据为“0”,电压不跳变,如果数据为“1”,电压跳变1次,且总是往历史电平相反的方向跳变,例如-1 → 0 → +1,或+1 → 0 → -1。 最后,100 Base-TX并不直接传输信号本身,而是传输信号与扰码的异或结果,如图7所示。截取的信号首先通过MLT-3的规则解码,每5位一组,用绿色字体标识。接下来,找到解扰码(scrambler key)序列。 扰码不是加密,只是用来改善电磁特性。因此,加扰和解扰都只需做异或(XOR)操作,使用同一个序列。 100 Base-TX使用一个11位的线性反馈移位寄存器(LFSR)来生成2047位长的伪随机数序列。这对于手动找到同步的位置带来了非常大的困难,但是如果是程序自动同步,就非常容易了。 解扰后的数据是5 bits一组,反查4B5B的编码表,就可以得到4 bits一组的数据。图7中展示了3个字节的编码分析结果。 图7. 100 Base-TX的编码解析 虽然100 Base-TX手动解码非常困难,但是借助示波器的总线解码工具,可以非常快速方便地完成解码。示波器的设置,如图8所示。 由于是标准协议,并没有太多选项,将总线设为“Ethernet”,速度设为“100 Base-TX”,信号类型设为“差分”,其它选项根据实际情况选择或保持默认就可以了。 图8. 100 Base-TX解码设置 解码结果,如图9所示。 图9. 100 Base-TX解码结果 100 Base -TX的解码流程复杂,数据量大,检索不方便,通常需要协议分析软件辅助才可以进一步分析。现在混合信号示波器中已经集成了解码和分析功能,只需要一根特制的网线,就可以完成全部分析工作,彻底将以太网的传输机制展示在屏幕上。 3.5 实战 我们通过2台计算机组成一个小局域网,在局域网之间进行ping操作的实战验证。通过Wireshark捕获,我们可以看到在网口上已经有了若干ping request和reply数据包,如图10所示。在TX差分对上,我们理应找到发出去的ping request数据包,源地址是192.168.0.2,目标地址是192.168.0.1。 在示波器上,我们设置好Ethernet总线解码,并将触发设置为指定的IP。如图11所示,触发位置选为“IP标头”,源地址设为“192.168.0.2”,这样当出现指定源地址的数据包后,示波器就会被触发。 如图12所示,是通过上述设置后示波器捕获并解码的数据包,经过对比,和Wireshark上软件捕获的数据相一致。 图10. Wireshark捕获的ping request和reply数据包 图11. 触发设置为指定IP 图12. 示波器捕获并解码的ping request数据包 4、总结 软件和硬件总是存在一些隔阂。例如在以太网分析上,传统的计算机网络领域主要从软件层面介绍逻辑链路层及更高层的设计和实现,对于物理层的介绍比较简单。 而传统的硬件领域对于数字信号往往只介绍简单的串行总线,并不会拿比较复杂的以太网作为例子。 本文深入分析了两类常见的双绞线以太网的编码,并利用混合信号示波器的总线解码功能,查看并验证了以太网在物理层的信号传输情况。 最后,通过一个实战例子对比了实际网络中软件接收的数据和示波器捕获信号之间的一致性,从物理层揭示了以太网数据传输的机制。 参考文献 [1] https://en.wikipedia.org/wiki/Ethernet [2] https://en.wikipedia.org/wiki/ANSI/TIA-568 [3] https://www.wireshark.org [4] https://en.wikipedia.org/wiki/4B5B [5] https://en.wikipedia.org/wiki/MLT-3_encoding 来源:硬件十万个为什么 文章来源于网络,版权归原作者所有,如有侵权,请联系删除。

    01-18 106浏览
  • WCDMA基站:一种新的综合测试方案

    新技术的出现和发展,必然带动测试技术的进步。在测试业界,当新技术出现初期,由于相关技术尚未定型,这个阶段必然是以通用仪表技术为主体完成相关的测试任务。然而新技术发展到一定阶段,技术相对稳定,相关的测试

    01-10 108浏览
  • MEMS交换机的工作原理和规范介绍

    对于MEMS,小编在往期文章中,已经带来了诸多介绍,如MEMS加速度计、MEMS陀螺仪、MEMS振荡器等.为增进大家对MEMS的认识,本文将对MEMS交换机、MEMS交换机的原理、MEMS规范予以介绍.如果你对MEMS具有兴趣,不妨和小编一起...

    01-09 95浏览
  • 汽车智能蓝牙技术安全性探讨:解密连接性与隐私保护的关键问题

      蓝牙低功耗(Bluetoothlowenergy)技术是一种低成本、可互操作性强、适合短距离操作的无线技术,其可以在免许可的2.4GHzISM射频频段工作。

    2023-12-20 116浏览
  • 物联传感物联网智能家居解决方案:打造舒适、便捷、智能的家居生活

      物联网智能家居,让你无论身处何地,都可以及时洞悉家中的风吹草动,它可以将你的风险降到最低,舒适升到最佳,效率达到最优。从此不必担心外出后忘记了关灯、关门,不

    2023-12-19 164浏览
  • ZigBee引领物联网设备大步向前

      ZigBee引领物联网设备大步向前  ZigBee基于IEEE802.15.4标准的低功耗局域网协议,是一个开放的无线网络状网络技术。与传统星型、点对点、网

    2023-12-19 129浏览
  • ZLG致远电子推动ZigBee在智能LED灯具的应用:打造高效、智能的照明解决方案

      ZigBee技术的应用十分广泛,商业大楼自动化,家庭自动化控制(新建安装)与仪表控制为重点。商业大楼可以利用ZigBee完成自动控制,管理员可以有效地管理空

    2023-12-19 111浏览
正在努力加载更多...
广告