米联客 ZYNQ/SOC 精品教程 S02-CH29 基于TCP的QSPI Flash bin文件网络烧写

软件版本:VIVADO2017.4

操作系统:WIN10 64bit

硬件平台:适用米联客 ZYNQ系列开发板

米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!!

29.1 概述

      在之前的应用中,ZYNQ将BOOT.bin文件烧写至QSPI Flash基本都是通过USB Cable连接PC,通过JTAG接口连接开发板,在SDK软件中使用“Program Flash”功能进行现场在线烧写。这种常规方法存在两个缺点。

      1、速度慢。Flash的擦除(Erase)、写入(Program)、校验(Verify)3个过程所费的时间总和通常都需要若干分钟。

      2、无法脱离JTAG口。对于某些产品而言,当产品量产上市后,进入维护升级阶段,若需修改、更新Flash中的bin文件,则需对产品进行拆解才可进行。

      本例程实现了一种基于TCP协议的Flash bin文件更新方法。一方面,在较大程度上提高了bin文件的烧写速度(4MB大小bin文件可缩短至20秒左右);另一方面,提供了一种远程更新Flash的方法,可脱离JTAG接口,同时避免固件升级时对产品进行拆解。

29.2 基本原理

      首先,在ZYNQ的ARM中基于LWIP库建立一个TCP Server,板卡通过网线与电脑连接。在电脑中通过网络调试助手以TCP Client模式与ZYNQ中的TCP Server建立TCP连接。然后,通过网络调试助手将BOOT.bin文件以二进制形式发送至TCP Server,并存储在ZYNQ所连接的DDR中。最后,当TCP Server接收完bin文件所有的数据后,网络调试助手发送烧写启动命令,将bin文件的数据按顺序一一连续写入QSPI Flash中,随后再全部读出与所接收的bin文件进行一一比对检验。断电重启板卡,便可验证bin文件的更新。

29.3 Bin文件

      在SDK中所生成的BOOT.bin文件为普通二进制文件,通过UltraEdit或Binary Viewer软件可打开并查看bin文件的内容。将bin文件中所有的数据按顺序一一连续写入QSPI Flash中,即可完成bin文件的烧写,也就是说Flash中的数据与bin文件中的数据完全是一一对应的。由此可见,烧写bin文件的原理并不复杂,不存在类似编码、解码的过程,且与SDK中的“Program Flash”的所完成的功能相同。使用Binary Viewer软件打开查看bin文件的效果如下图所示。

米联客 ZYNQ/SOC 精品教程 S02-CH29 基于TCP的QSPI Flash bin文件网络烧写_第1张图片

29.4 QSPI Flash

      Flash在写入数据之前必须先进行擦除(Erase),擦除过程以扇区(Sector)为单位。然后以页(Page)为单位,依次将数据写入Flash中连续的各页。

      以米联ZYNQ开发板所使用的QSPI Flash:S25FL256S为例。Sector的大小为64KB,Page的大小为256B。另外,还存在两个重要参数:单位Sector擦除时间和单位Page写入时间,这决定了Flash的烧写速度。S25FL256S所对应的单位Sector擦除时间为130ms,单位Page写入时间250μs。如下图最右侧的两栏所示。具体可参考芯片datasheet。

70f64a65ccac7c0e7c48e13870d24364768.jpg

     以4MB大小的BOOT.bin文件为例,写入之前需要擦除4096/64 = 64个Sector,最短需耗时64×130ms = 8.32s。接着,需要写入4096×1024/256 = 16384个Page,最短需耗时16384×250μs = 4.096s。加上ARM中应用程序的软件开销,QSPI Flash的擦除、写入时间总和不超过15s。若需读出进行校验,则再额外增加读出时间、比对时间。QSPI Flash的读出速度很快,读出整个bin文件耗时小于1s,ARM中应用程序的比对时间通常也很短,1至2s即可完成。因此,对于4MB大小的bin文件,QSPI Flash的擦除(Erase)、写入(Program)、校验(Verify)3个过程所耗费的时间总和可以控制在20s以内。

29.5 驱动程序

驱动程序请参考提供例程的SDK工程的源文件。

main函数的完成的功能如下:

  1. 关闭Data Cache,避免bin文件在DDR拷贝过程中维护Cache一致性造成的麻烦
  2. 配置QSPI接口及QSPI Flash
  3. 配置Timer及其中断
  4. 初始化中断控制器及系统中断
  5. 初始化LWIP协议栈
  6. 建立TCP Server,启动Timer
  7. 持续从LWIP协议栈接收数据

29.5.1 建立TCP Server

     基于LWIP库在ARM中建立一个TCP Server,IP地址为192.168.1.10,端口号为5010。

29.5.2 lwip库设置

   本例程使用RAW API,即函数调用不依赖操作系统。传输效率也比SOCKET API高,(具体可参考xapp1026)。将use_axieth_on_zynq和use_emaclite_on_zynq设为0。如下图所示。

米联客 ZYNQ/SOC 精品教程 S02-CH29 基于TCP的QSPI Flash bin文件网络烧写_第2张图片

      修改lwip_memory_options设置,将mem_size,memp_n_pbuf,mem_n_tcp_pcb,memp_n_tcp_seg这4个参数值设大,这样会提高TCP传输效率。如下图所示。

米联客 ZYNQ/SOC 精品教程 S02-CH29 基于TCP的QSPI Flash bin文件网络烧写_第3张图片

      修改pbuf_options设置,将pbuf_pool_size设大,增加可用的pbuf数量,这样同样会提高TCP传输效率。如下图所示。

9f9cf0f4778b6c908d67bfa5adff727313d.jpg

      修改tcp_options设置,将tcp_snd_buf,tcp_wnd参数设大,这样同样会提高TCP传输效率。如下图所示。

米联客 ZYNQ/SOC 精品教程 S02-CH29 基于TCP的QSPI Flash bin文件网络烧写_第4张图片

     修改temac_adapter_options设置,将n_rx_descriptors和n_tx_descriptors参数设大。这样可以提高zynq内部emac dma的数据搬移效率,同样能提高TCP传输效率。如下图所示。

米联客 ZYNQ/SOC 精品教程 S02-CH29 基于TCP的QSPI Flash bin文件网络烧写_第5张图片

       MZ7X工业级开发板板载网口芯片是RTL8211FDI,由于默认的驱动不支持RTL8211FDI 的寄存器配置,所以无法支持自动适应速度 (通过自己修改库可以实现自动适应但是工作量大,考虑到投入时间和产出比,这里就不修改了)。所以需要手动修改 LWIP 库让网口芯片工作于1000Mbps。米联客 ZYNQ/SOC 精品教程 S02-CH29 基于TCP的QSPI Flash bin文件网络烧写_第6张图片

29.5.3 程序解析

TCP Server建立由tcp_transmission.c文件中的tcp_recv_init和connect_accept_callback函数完成。

  • tcp_recv_init函数:
  1. 调用tcp_new函数建立1个建立TCP连接所需的结构体。
  2. 调用tcp_bind函数绑定TCP Server的本地IP地址和TCP端口号。
  3. 调用tcp_listen函数启动监听外部任何TCP Client向TCP Server发送的TCP连接请求。
  4. 调用tcp_accept函数指定当TCP Server与外部TCP Client建立TCP连接后的回调函数为connect_accept_callback。
  • connect_accept_callback函数:
  1. 当ARM中建立的TCP Server与外部TCP Client建立连接后,connect_accept_callback函数将会被调用。
  2. 调用tcp_recv函数指定当TCP Server接收来自TCP Client所发送数据包的回调函数为tcp_recv_callback。
  3. 调用tcp_sent函数指定当TCP Server向TCP Client发送数据包时的回调函数为tcp_sent_callback,在例程tcp_sent_callback为空函数,无实际作用。

29.5.4 接收保存BOOT.bin文件

       接收BOOT.bin文件通过tcp_transmission.c中的tcp_recv_callback函数完成,该函数为TCP Server接收数据包的回调函数,每当接收到TCP Client的数据包时该函数都会被调用。该函数将TCP Server所接收到的bin文件的各数据包依次拷贝至DDR中首地址为FILE_BASE_ADDR的区域中,FILE_BASE_ADDR为宏定义。

#define FILE_BASE_ADDR 0x10000000

        可根据具体要求定义其地址,注意要与lscript.ld中的DDR区域分开,不能重合。

29.5.5 烧写QSPI Flash

       烧写QSPI Flash由qspi_g128_flash.c文件中的update_flash、FlashErase、FlashWrite、FlashRead等函数完成,可支持Micron、Spansion等多个厂商,128Mb以上多种容量的QSPI Flash。qspi_g128_flash.c是根据SDK中QSPI接口的example:xqspips_g128_flash_example.c修改而成。

       当接收完整个bin文件后,在网络调试助手中输入“start update”,含空格一共12个字符。tcp_recv_callback函数接收到该命令之后便调用update_flash函数启动bin文件至QSPI Flash的烧写。该函数需要1个读缓存和1个写缓存,分别存放从flash中读出的bin文件数据和需要写入flash中的bin文件数据。读缓存和写缓存的地址分别由READ_BASE_ADDR和WRITE_BASE_ADDR宏定义指定。可根据具体要求定义其地址,同样需要注意要与lscript.ld中的DDR区域分开,不能重合。

      #define READ_BASE_ADDR 0x11000000

      #define WRITE_BASE_ADDR 0x12000000

update_flash函数:

  1. 将TCP Server接收的bin文件数据拷贝至写缓存中起始地址为WRITE_BASE_ADDR + 4的区域中,增加4字节的地址偏移是由于在FlashWrite函数中,写缓存的前4字节将被用于填充命令和写入地址字段。
  2. 调用FlashErase函数将bin文件数据所对应数量的扇区擦除。
  3. 调用FlashWrite将bin文件数据以页为单位依次全部写入Flash中。
  4. 调用FlashRead函数将刚才写入Flash的bin文件全部读出存入读缓存中。
  5. 将读出的bin文件数据与TCP Server接收的原始bin文件数据进行一一比对验证烧写的正确性。

     FlashErase、FlashWrite、FlashRead函数均源自于SDK中QSPI接口的example code。可参考相应的example具体分析函数功能。

29.5.6 TCP调试信息输出

      例程中设计了一个tcp_printf函数,用于向网络调试助手输出字符串调试信息。该函数暂时只支持字符串以“\n”结尾。

      在本例程中使用该函数存在一个问题,即在Flash烧写开始直至结束前所有通过tcp_printf输出的调试信息,将无法及时发送,在烧写结束后应用程序回到main函数中包含xemacif_input(netif)函数的while循环中时,同时全部通过TCP发送至网络调试助手。

      笔者尝试过几种方法均未能解决这个问题,例如通过tcp_nagle_disable()函数关闭nagle算法功能。笔者认为,一方面,可能跟LWIP库TCP部分函数的设计原理有关,另一方面,由于flash烧写部分应用程序将长时间占用ARM,使得xemacif_input(netif)函数长时间无法被调用,而ZYNQ中的LWIP协议栈所有的数据接收都需要依靠应用程序调用xemacif_input()函数而实现。因此在这段时间中,可能由于长时间无法调用该函数而对TCP部分函数的运行造成某些影响,使数据发送产生阻塞或者延迟。由于LWIP中TCP部分库函数结构较复杂,笔者对于TCP协议研究也不多,限于时间和精力未作深究。

29.6 网络调试助手操作方法

29.6.1 发送bin文件

       在SDK中下载程序至ZYNQ中。打开网络调试助手,选择TCP Client方式,输入ARM中定义的TCP Server的IP地址和端口号,然后点击连接按键,建立TCP连接。SDK串口终端打印信息如下图所示。

米联客 ZYNQ/SOC 精品教程 S02-CH29 基于TCP的QSPI Flash bin文件网络烧写_第7张图片

       在网络调试助手发送区设置里选择“启用文件数据源”,选择需要发送的BOOT.bin文件,然后点击发送。如下图所示。

米联客 ZYNQ/SOC 精品教程 S02-CH29 基于TCP的QSPI Flash bin文件网络烧写_第8张图片

29.6.2 发送启动Flash烧写命令

      然后输入烧写启动命令“start update”,不要选择“按十六进制发送”,本例程中需要以ASCII码形式发送,含空格一共12个字符(不要在末尾加回车),千万不要输错,否则需要全部重新再来一遍。如下图所示。

米联客 ZYNQ/SOC 精品教程 S02-CH29 基于TCP的QSPI Flash bin文件网络烧写_第9张图片

启动烧写后,SDK串口终端打印信息如下图所示。当提示“verify done!”表示整个烧写过程成功完成。

米联客 ZYNQ/SOC 精品教程 S02-CH29 基于TCP的QSPI Flash bin文件网络烧写_第10张图片

网络调试助手接收tcp_printf函数的输出的信息如下图所示。

米联客 ZYNQ/SOC 精品教程 S02-CH29 基于TCP的QSPI Flash bin文件网络烧写_第11张图片

29.7 Bin文件更新验证

      烧写完成后,此时可断电重启验证更新的BOOT.bin文件。本例程作为演示,烧入的bin文件为hello world工程。重启开发板,SDK串口终端打印信息如下图所示,代表bin文件更新成功。

02d986160e2efe50492cab2af915ae9abf2.jpg

29.8 待改进之处

  1. tcp_printf函数在flash烧写过程中无法及时发送数据的问题有待解决。
  2. 无校验差错重新写入功能。当将bin文件写入Flash之后再读出校验时,若出现错误,则需将错误的Page重新写入。
  3. 由于例程中使用网络调试助手作为传输BOOT.bin文件的工具,仅使用了TCP协议,无法在TCP协议之上设计自定义协议来规范并完善bin文件的传输过程,用户可控性较差。例如,启动命令“start update”一旦输入错误并发送至ZYNQ,则板卡将需断电重启,整个过程需从头重来一遍。理想情况下,用户应根据实际需求在TCP之上设计相应的bin文件传输协议(例如给每一个bin文件数据包加上含有协议信息的包头、包尾等)来提高传输的可靠性和可控性。另外,用户还需设计与之相对应的上位机软件进行bin文件的发送,以及与ZYNQ的通信。

转载于:https://my.oschina.net/msxbo/blog/3102761

你可能感兴趣的:(米联客 ZYNQ/SOC 精品教程 S02-CH29 基于TCP的QSPI Flash bin文件网络烧写)