zoukankan      html  css  js  c++  java
  • S03_CH11_基于TCP的QSPI Flash bin文件网络烧写

    S03_CH11_基于TCP的QSPI Flash bin文件网络烧写

    11.1概述

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

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

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

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

    11.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文件的更新。

    11.3 Bin文件

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

    wps9A56.tmp

    11.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。

    wps9A57.tmp

    以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以内。

    11.5驱动程序

    所有的驱动程序文件均包含在c_driver文件夹中的tcp文件夹。

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

    l 关闭Data Cache,避免bin文件在DDR拷贝过程中维护Cache一致性造成的麻烦

    l 配置QSPI接口及QSPI Flash

    l 配置Timer及其中断

    l 初始化中断控制器及系统中断

    l 初始化LWIP协议栈

    l 建立TCP Server,启动Timer

    l 持续从LWIP协议栈接收数据

    11.5.1建立TCP Server

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

    11.5.2 lwip库设置

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

    wps9A67.tmp

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

    wps9A68.tmp

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

    wps9A69.tmp

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

    wps9A7A.tmp

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

    wps9A7B.tmp

    其余选项的参数默认即可,不用修改。

    11.5.3程序解析

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

    Ø tcp_recv_init函数:

    l 调用tcp_new函数建立1个建立TCP连接所需的结构体。

    l 调用tcp_bind函数绑定TCP Server的本地IP地址和TCP端口号。

    l 调用tcp_listen函数启动监听外部任何TCP Client向TCP Server发送的TCP连接请求。

    l 调用tcp_accept函数指定当TCP Server与外部TCP Client建立TCP连接后的回调函数为connect_accept_callback。

    Ø connect_accept_callback函数:

    l 当ARM中建立的TCP Server与外部TCP Client建立连接后,connect_accept_callback函数将会被调用。

    l 调用tcp_recv函数指定当TCP Server接收来自TCP Client所发送数据包的回调函数为tcp_recv_callback。

    l 调用tcp_sent函数指定当TCP Server向TCP Client发送数据包时的回调函数为tcp_sent_callback,在例程tcp_sent_callback为空函数,无实际作用。

    11.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区域分开,不能重合。

    11.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函数:

    l 将TCP Server接收的bin文件数据拷贝至写缓存中起始地址为WRITE_BASE_ADDR + 4的区域中,增加4字节的地址偏移是由于在FlashWrite函数中,写缓存的前4字节将被用于填充命令和写入地址字段。

    l 调用FlashErase函数将bin文件数据所对应数量的扇区擦除。

    l 调用FlashWrite将bin文件数据以页为单位依次全部写入Flash中。

    l 调用FlashRead函数将刚才写入Flash的bin文件全部读出存入读缓存中。

    l 将读出的bin文件数据与TCP Server接收的原始bin文件数据进行一一比对验证烧写的正确性。

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

    11.5.6 TCP调试信息输出

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

    在本例程中使用该函数存在一个问题,即在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协议研究也不多,限于时间和精力未作深究。

    11.6网络调试助手操作方法

    11.6.1发送bin文件

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

    wps9A7C.tmp

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

    wps9A8D.tmp

    11.6.7发送启动Flash烧写命令

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

    wps9A8E.tmp

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

    wps9A8F.tmp

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

    wps9A9F.tmp

    11.7 Bin文件更新验证

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

    wps9AA0.tmp

    11.8待改进之处

    l tcp_printf函数在flash烧写过程中无法及时发送数据的问题有待解决。

    l 无校验差错重新写入功能。当将bin文件写入Flash之后再读出校验时,若出现错误,则需将错误的Page重新写入。

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

  • 相关阅读:
    Pascal's Triangle II
    Pascal's Triangle
    Best Time to Buy and Sell Stock II
    Best Time to Buy and Sell Stock
    Populating Next Right Pointers in Each Node
    path sum II
    Path Sum
    [转载]小波时频图
    [转载]小波时频图
    [转载]Hilbert变换及谱分析
  • 原文地址:https://www.cnblogs.com/milinker/p/6484393.html
Copyright © 2011-2022 走看看