特殊环境下FPGA 代码在线升级功能的实现

2021-12-07 07:45陈召全
电子设计工程 2021年23期
关键词:主程序寄存器命令

陈召全

(中航华东光电有限公司特种显示技术国家工程实验室,安徽芜湖 241002)

目前主流的FPGA 均是基于SRAM 编程的,当系统掉电后,编程信息全部丢失[1-2]。所以,需要在FPGA 的外围采用非易失性器件Flash、EEPROM 来存储代码,在系统上电的时候,将编程信息读入FPGA 内部,形成特定功能的电路。在FPGA 调试过程中可以采用JTAG 方式下载程序,系统调试完成,在产品出厂前需要下载配置代码到非易失性器件中。在产品联试或者使用中出现问题,或者用户功能升级时,都需要重新升级非易失性器件中的代码[3]。此时就需要打开产品的外壳,如果产品是作为部件安装在用户的系统中,就需要将用户的相关设备先拆除。这种操作还会带来一系列的问题,尤其是特种设备,其使用环境特殊,要么人员不能靠近,要么拆卸困难,要么保密的原因不能开箱。在这些情况下,就要通过在线的方式将代码烧写进非易失性器件,避免开箱操作。文中为了解决此问题,提出了一种FPGA 在线升级解决方案,同时考虑到加载过程中可能断电,或者其他原因引起加载中断。如果不加以保护的话,会导致原始数据丢失,FPGA 无法启动,就不得不开箱重新烧写,因此提出了双主程序分区的方法,能有效地解决这个问题,提升了可靠性。

1 在线升级系统组成及整体要求

文中在一款机载显示模块中实现FPGA 在线升级功能,以提升产品的维护性和可靠性。产品中采用Xilinx 的Artix-7 系列FPGA,采用主动SPI 方式对FPGA 进行配置,对应的SPI Flash 型号为N25Q064A。产品对外的通信方式为RS422[4-5],通过此接口接收主机信号,进行亮度调节、信号参数调整、发送系统工作状态等信息。为了减少产品的对外接口数量,复用此接口[6-7]。为了保存在线升级过程中的中间状态,以及控制FPGA 在上电过程中能够正确读取配置代码,需要EEPROM 来存储相应的参数。在线升级系统的主要组成框图如图1 所示。

图1 在线升级系统的主要功能框图

由于RS422 预定义的波特率为115 200,为了实现通用性,仍然应用此波特率,在原有的通信指令基础上增加一些特殊指令,来实现在线升级功能,以控制FPGA 实现对外围EEPROM 和Flash 的控制,同时为了避免用户误操作对系统配置代码造成破坏,这些在线升级指令是不对用户开放的,而且进行了一系列的保护措施,确保系统的安全性。考虑到在线升级操作过程中可能会出现加载过程被中断的问题,为了避免原始数据丢失FPGA 不能正常启动的问题,采用了双主程序分区的方式,进一步提升了系统的可靠性。

2 在线升级功能的实现

2.1 在线升级实现过程

利用Xilinx 系列FPGA 内部的ICAPE2 (Internal Configuration Access Port)原语,实现FPGA 程序的动态加载[8-9]。通过ICAPE2 原语可以触发IPROG (The internal PROGRAM_B)命令,实现FPGA 的热启动,能够根据设置好的启动地址,从该地址读取FPGA 的配置数据[10-11]。

通过ICAPE2 实现IPROG 命令的过程为:首先,通过ICAPE2 发送同步字;其次,配置热启动开始地址;最后,发送IPROG 指令。当配置逻辑接收到IPROG 指令后,FPGA 将开始热启动,将INIT_B 和DONE 管脚拉低,直到FPGA 内部所有逻辑被擦除,拉高INIT_B,并从WBSTAR 地址处读取配置数据,实现配置数据的重加载,动态地改变了FPGA 内部电路功能。

该文的在线升级涉及到主程序和引导程序,其中的主程序为正常工作状态对应的程序,引导程序为专门实现在线升级功能的程序。主程序和引导程序分别被放置到SPI Flash 的不同区域。引导程序所在的区域是固定的,且不能被改写,只有通过JTAG编程时才能被重新设置。主程序区域是可以被改写,当产品功能改变或者性能升级时,新的配置数据会被重新写入主程序区域。考虑到在线升级过程中可能会出现数据被破坏的情况,主程序区域被分为两个区,一个是当前工作的区域,另一个是新配置数据写入区。为了保证FPGA 加载到正确的配置程序,Flash 中仅留存一个主程序,一旦新的主程序被写入,并且验证正确,即将老的主程序擦除,并且改写进入主程序地址的寄存器数值,确保重新上电后,FPGA 加载新升级的配置数据。SPI Flash 内部的空间分布如图2 所示。

图2 SPI Flash内部空间分布图

2.2 主程序实现

主程序为实现产品各项功能所对应的程序,也是在线升级所更新的部分。在主程序的RS422 接收模块中增加在线升级对应的命令。主要有是否进入主程序判断寄存器(boot_main_select),因为在引导程序和主程序中都要对此寄存器进行控制,所以不能将其存在FPGA 内部,因为一旦重新加载程序,此寄存器就会被复位,所以只有存放到外部的非易失性存储器EEPROM 中;另一条命令为IPROG 启动命令(start_ICAP),实现从主程序回到引导程序,将引导程序配置数据加载到FPGA。主程序中与在线升级有关的部分的控制流程如图3 所示。

图3 主程序在线升级部分工作流程

当RS422 接收模块接收到在线升级命令后,首先改写boot_main_select 寄存器的数值,以便在跳转到引导程序后,程序不会接着跳转到主程序[12-13]。这样就可以在引导程序控制下进行在线升级操作。同时等待start_ICAP 指令,进行引导程序的加载[14]。通过ICAPE2发送的数据和命令如表1所示。

表1 ICAPE2发送的数据和命令表

2.3 引导程序实现

2.3.1 引导程序执行过程

引导程序放置在Flash 的00000000h 地址,当FPGA 上电后首先从此地址加载数据。引导程序加载完成后,首先要读取boot_main_select 寄存器的数值,以及主程序选择main _select 寄存器。如boot_main_select 寄存器对应的是主程序区,则进入main_select 指向的主程序;否则,停留在引导程序,等待相关的指令。在引导程序中,通过RS422 接收相关的控制命令和数据。主要的操作命令有:设置boot_main_select 寄存器;设置main_select 寄存器;控制SPI Flash 实现主程序区1 和主程序区2 中数据的读写和数据擦除;执行ICAPE2 跳转程序等。引导程序的具体执行过程如图4 所示。

图4 引导程序执行过程

2.3.2 Flash控制器的实现

在引导程序中,关键的操作是对外部的SPI Flash的控制,以实现新程序的写入和旧程序的擦除[15]。所以,Flash 控制器的有效性对在线升级功能的实现起到了关键的作用[16]。Flash 控制器主要有Flash控制模块,写入数据缓存FIFO,读出数据缓存FIFO组成。其中Flash 控制模块根据输入的控制命令和数据,控制Flash 的cs、sdi、sdo、sclk 信号完成相应的控制功能[17-19]。SPI Flash 控制器的总体架构如图5所示。

图5 SPI Flash控制器总体架构图

在图5 中,flash_se_en 表示的是flash 擦除使能信号,对flash_addr 对应的地址块的数据进行擦除操作。flash_pp_en 表示flash 编程使能信号,将data_in_fifo 中的数据写入到flash_addr 对应位置。flash_rd_en 表示flash 读使能信号,将flash_addr 对应位置的数据读出,并写入到data_out_fifo 中,以便后续串口通信模块将数据统一输出到上位机。各个功能模块的实现如下:

1)Flash 擦除控制

在执行Flash 擦除操作之前,先要执行WRITE ENABLE 命令,将Flash 内部写使能寄存器置“1”,负责Flash 忽略擦除操作。WRITE ENABLE 设置之后,发送Flash 擦除指令D8,以及24 位Flash 擦除地址。

在发生完擦除命令后Flash 内部开始对应的擦除操作,会存在一定的延时才能执行相应新的操作命令,所以要周期性地发送读状态寄存器命令来了解Flash 的状态,当状态寄存器的最低位为“1”时,说明Flash 在执行写状态寄存器、Flash 编程、Flash 擦除这几个命令之一;当状态寄存器的最低位为“0”时,Flash 进入空闲状态,可以进行其他操作。

2)Flash 读控制

Flash 读操作的效率非常高,一次能够将Flash中的数据全部读出,但是产品和上位机之间的通信方式为RS422,传输速率低,所以为了保证所有的数据均能够正确地输出,需要data_out_fifo 的配合。文中采用的操作方式为,一次读操作的长度为256 byte,完成一次读操作之后判断FIFO 中的数据状态,如果满足下一次读取的要求,则重新读256 byte 的数据,对应的flash 地址也要加256,直到地址达到flash 中某个区域的上限。对应的状态图如图6 所示。

图6 读flash逻辑状态图

在空闲状态下接收到flash_rd_en 使能命令,状态机开始跳转,进入Rd_StReg 状态,读状态寄存器判断flash 是否空闲,空闲进入下一状态,负责回到空闲状态,忽略本次操作。紧接着判断地址是否超出范围,在正常范围则进入发送读命令状态,接着发送地址状态,因为采用的是快速读模式,需要等待8 个时钟周期,然后进入接收数据状态,接收完256 个数据后,进入地址增加,载回到flash_addr_check 进行判断是否开始下一次读取操作。

3)Flash 写控制

Flash 写操作也需要通过data_in_fifo 来进行数据缓存,来平衡串口和Flash 写操作之间的速度,以免写入错误。由于不清楚外部写入数据的整长度,所以Flash 写入采用一次写入一个byte 的方式。操作方式与读操作类似,这里不在赘述,其对应的状态图如图7 所示。注意在操作之前需要单独执行对应区域的擦除操作。

图7 写flash逻辑状态图

3 系统功能测试

在产品正常工作下显示图像如图8 所示,通过串口发送指令,将boot_main_select 设置为00h,然后发送start_ICAP 命令进入引导程序。在引导程序下将main 程序区域2 擦除,并写入对应的数据,为了验证写入数据的有效性,在写入完成后,将main 区域2 中的数据读出和原始的数据进行比较,采用工具Beyond Compare 4 进行比较,左侧边没有标红显示,说明写入和读出的数据是一样的,则写入正常。将main 程序区域1 对应的数据擦除,并将main_select指向程序区域2。发送start_ICAP 命令,FPGA 加载main 程序区域2 对应的程序,此时显示的是灰阶画面,如图9 所示。通过以上操作验证了在线升级程序的有效性。

图8 正常显示图像

图9 在线加载后显示图像

4 结论

该文提出了一种通过RS422 在线对FPGA 进行加载的方法,通过将程序存储Flash 分为3 个区域,分别存放引导程序和主程序1、主程序2,在线升级完成后,主程序1 区域和主程序2 区域只有一个区域存放加载数据,另一区域被擦除。在正常工作模式下,通过设置boot_main_select 寄存器,和发送start_ICAP命令,使FPGA 加载引导程序,并停留在引导程序。在引导程序下将新的代码数据写入相应的flash 区域,并将main_select 寄存器指向此区域,确保在上电时,能准确加载对应的数据。由于采用了两个主程序区域,确保了在下载过程被中断的情况下,FPGA能够回到原始状态,提升了工作可靠性。该文方法在实际项目中得到了应用,验证了其有效性。

猜你喜欢
主程序寄存器命令
只听主人的命令
STM32和51单片机寄存器映射原理异同分析
Lite寄存器模型的设计与实现
浅谈数控铣削技术代码程序的嵌套方式研究
电控冰箱软件模块化设计
移防命令下达后
时光倒流 换回PotPlayer老图标
这是人民的命令
未经授权的第三方软件侵权问题研究
——以“腾讯与360之争”为视角*
高速数模转换器AD9779/AD9788的应用