基于RISC-V处理器的固件更新系统设计

2022-03-02 08:32虞致国洪广伟顾晓峰
计算机工程与应用 2022年4期
关键词:固件中断内存

郭 俊,虞致国,洪广伟,顾晓峰

江南大学 电子工程系 物联网技术应用教育部工程研究中心,江苏 无锡214122

RISC-V是由美国加州大学伯克利分校(UCB)设计并公布的一种基于精简指令集计算(reduced instruction set computing,RISC)原理的指令集架构,其目标是成为一种完全开放、适合硬件实现且稳定的标准指令集架构[1-2]。相比当前发展相对成熟的商业架构,RISC-V 指令集架构具有支持模块化可配置的指令子集、极强的扩展性、指令数目少、低功耗及低成本等突出优点[3-4]。近年来,其凭借自身优势,已经引起学术界的广泛关注[5]。

通常,在嵌入式开发人员开发RISC-V处理器(如蜂鸟E200、Rocket Core 处理器等)的过程中,若需对处理器的固件进行更新升级,只能通过JTAG(joint test action group)调试器来烧录新的固件程序[6]。JTAG 调试器信号线种类繁多且配置流程复杂,给开发人员带来了很多不必要的麻烦。随着嵌入式系统的飞速发展,在应用中编程(in-application programming,IAP)技术在RISC 指令集架构处理器中已经得到广泛的应用,其能通过已有的通信接口对存储在Flash中的数据进行重新烧写[7],从而简化嵌入式开发人员更新固件的操作流程。文献[8-10]分别根据各自的应用场景为ARM处理器实现了IAP设计,但是都只能在Flash 中运行IAP 程序,与在RAM 中运行的速度相比,处理器每次都需从Flash中取指令,取指时间较长,影响了整个系统级芯片(system on chip,SoC)的启动速度。文献[11]为其自主设计研发的RISC DSP实现了固件更新系统设计,但是其实现的方法需要将固件更新代码全部固化在BootROM中。若本文采用此种设计方法,则会占用更多的ROM资源,导致无法为RISC-V处理器设计出更多种可供开发人员灵活选择的启动模式。

针对IAP 技术的应用需求和上述问题,本文为RISC-V 指令集架构处理器设计了一个易操作、高效且稳定的固件更新系统。此系统主要设计成两个启动阶段:第一阶段在BootROM 中进行,主要执行BootROM中固化的代码以完成RISC-V 处理器内核初始化,以及第二阶段所需启动程序(例如,在固件更新系统中为IAP 程序)的参数再配置以及加载等;第二阶段在主内存(DDR3/4 SDRAM)中进行,主要执行IAP 程序以完成对片外Flash中固件的更新、片外Flash到主内存的固件加载以及跳转运行新固件等。

1 RISC-V SoC

1.1 系统架构

图1为本文所采用的RISC-V处理器及其SoC架构。从图中可看出,该系统由64位的RISC-V处理器(Rocket Core)、系统总线(System Bus)、设备总线(Device Bus)、存储总线(Memory Bus)、AXI 总线以及各总线的相应挂载模块组成。其中,完成固件更新所需的BootROM模块挂载在系统总线上,通用异步收发传输器(universal asynchronous receiver/transmitter,UART)和串行外设接口(serial peripheral interface,SPI)模块挂载在设备总线上,DDR3/4控制器模块挂载在存储总线上。

图1 RISC-V处理器及其SoC架构Fig.1 Frame diagram of RISC-V processor and SoC

1.2 Rocket Core

目前,公开发布的开源RISC-V处理器主要有BOOM Core、Rocket Core、蜂鸟E200 Core、PicoRV32 Core、SCR1 Core 及ORCA Core 等[6]。由于后三种处理器没有与其配套的开源SoC平台,不具备完成固件更新系统设计的条件;同时综合考虑前三种处理器的性能、面积以及课题需求,最终选择性能与面积都折中的Rocket Core作为固件更新系统的开发平台。

Rocket Core 是UCB 推出RISC-V 指令集架构时同期发布的一款64 位的开源处理器,可用SoC 生成器(Generator)Rocket-Chip 生成[12-13],其源代码采用Chisel语言开发[14]。Rocket Core具有如下特点:支持多种RISC-V指令集扩展组合,配备单发射顺序执行的五级流水线、无阻塞缓存、返回地址堆栈、分支预测机制、可扩展指令接口以及内存管理单元,集成浮点运算单元(float point unit,FPU)等[15]。UCB 团队在5 年内使用Rocket Core完成11次流片,并在其芯片原型上成功运行了Linux操作系统[16]。

2 固件更新系统

2.1 硬件结构

固件更新系统的硬件结构如图2 所示。首先为RISC-V SoC设计了一种BootROM引导方式,完成片外Flash 到主内存的程序加载,并将程序指针跳转到内存中;之后,根据IAP 原理,采用UART 接口接收从PC 机发送过来的固件更新文件(采用Ymodem协议发送),采用SPI接口完成RISC-V处理器对片外Flash固件地址段的重新烧写,以实现对系统固件的更新。

图2 固件更新系统硬件结构Fig.2 Hardware structure of firmware update system

2.2 Flash存储空间规划

为了更好地管理Flash空间及考虑到后续对IAP设计的升级优化,需要对片外Flash 的存储空间进行合理规划[10]。

在固件更新系统中,片外Flash 的存储空间主要被分为两个相互独立的模块,分别用来存储IAP程序和固件程序。本设计所采用的片外Flash是华邦(WINBOND)公司的W25Q128JV,此Flash为Block 0(64 KB)分别提供了4 KB、8 KB、16 KB 和32 KB 的写保护设置。为给IAP 程序设置写保护功能,以防止用户误擦除,本设计给IAP 程序预留了16 KB 的存储空间,即Block 0 内的Sector 0~Sector 3,其余空间预留给固件使用。

2.3 主内存地址空间映射

在固件更新过程中,完成了片外Flash 与主内存(DDR3/4)之间的程序流交互。为了匹配上述Flash 存储空间的规划,以及得到IAP 和固件程序的跳转地址,需要确定片外Flash中的IAP和固件程序在主内存中的地址映射关系。本设计的地址映射关系如图3所示,片外Flash中的IAP程序在主内存中所映射的地址范围为0x80000000~0x80003FFF,固件程序在主内存中所映射的地址范围为0x80004000~0x80FFFFFF。

图3 主内存的地址空间映射Fig.3 Address space mapping of main memory

2.4 BootROM引导流程设计

BootROM是挂载在RISC-V处理器系统总线上的一小块片内掩膜ROM[11],配置的容量大小为8 KB。Rocket Core的复位PC值为0x10000,指向BootROM的基地址,因此在RISC-V处理器上电后,首先会从BootROM中取出指令执行[17]。为保证整个系统的启动速度,本设计在BootROM内只进行一些简单的内核初始化配置和为下一阶段启动做好准备,共占用7.08 KB 的BootROM 资源,为总容量的88.5%。

设计的BootROM引导流程如图4所示。

图4 BootROM引导流程Fig.4 Flow chart of BootROM boot

在处理器内核初始化完成后,系统会根据第一类启动引脚状态完成第一阶段启动参数的再配置,如第二阶段所需启动程序(在固件更新系统中为IAP 程序)的内存分配、进程数、源地址、目标地址以及代码量等参数的再配置,从而达到兼容多种启动模式(如SRAM启动、主内存启动)的目的。在固件更新系统中,选用主内存启动模式。在此模式下,处理器完成启动参数的再配置后,会执行BootROM 中已固化的一段加载指令和跳转指令,可通过SPI控制器将片外Flash中存储的IAP程序段加载到主内存中;之后,程序指针跳转到内存的相应地址处运行IAP程序,进行第二阶段启动。

为了对BootROM 设计进行功能仿真验证,本系统采用WINBOND 公司提供的W25Q32JV Flash 仿真模型。图5展示了在主内存启动模式下从片外Flash中读出的第一条需要被加载的指令0x04c0006f(对应的汇编代码为j 8000004c,即跳转到固件程序的复位向量地址处),以及在BootROM 中固化的跳转指令0x00048067(对应的汇编代码为jr s1,即跳转到主内存中的IAP 程序基地址0x80000000 处)。从仿真结果可证明此种启动模式工作正常。

图5 主内存启动模式的仿真波形Fig.5 Simulation waveforms of main memory boot mode

2.5 IAP设计

2.5.1 IAP程序设计

IAP 设计采用Ymodem 通信协议传输固件文件。此协议是Xmodem 的改进版,每包数据可高达1 024 字节,已广泛应用于串口通信中[18]。在文件传输过程中,其凭借完善的握手机制和出错管理机制,具有高效、稳定及一次支持传输多个文件等优点[9]。

IAP程序的功能是先通过UART接收从上位机发送来的二进制固件文件,再通过SPI控制器对存储在片外Flash中的固件进行重新烧写,最后待更新固件成功后,完成从IAP程序到固件的指针跳转。在设计好IAP程序后,只需将其通过JTAG调试器烧写到片外Flash一次即可。

设计的IAP程序流程如图6所示。在程序运行过程中,难免会遇到一些诸如异常复位、掉电或传输出错等情况而导致系统崩溃[8]。为了保证系统运行的稳定性,本设计采用软硬件联合控制机制完成对固件程序的更新,若在程序运行中出现上述异常情况,则系统会自动根据启动引脚状态重新进行本次更新,直到更新完成。在第一阶段启动完成后,程序指针会从BootROM 跳转到主内存中,之后再通过第二类启动引脚状态进行第二阶段启动模式的选择,包括UPDATE模式和WORK模式。

图6 IAP程序流程Fig.6 Flow chart of IAP program

UPDATE 模式的流程:(1)关闭所有中断;(2)对UART和SPI模块进行配置;(3)根据用户通过串行交互软件(如超级终端)发送过来的指令完成对固件的更新或擦除,若超级终端界面上提示片外Flash 中的固件程序地址段被设置成写保护,则必须先输入指令“diswp”,关闭其写保护,否则无法将接收到的新固件正确烧写至Flash;(4)接收新固件文件并对其进行CRC16 校验,将校验通过的数据烧写到片外Flash中;(5)待固件更新成功后,在超级终端界面上会显示传输文件的名称和大小等信息。

WORK模式的流程:(1)完成固件程序从片外Flash到主内存的加载;(2)判断固件是否加载成功,若成功,则程序指针跳转到内存的固件程序地址段,运行新固件,若失败,则提示用户固件的加载出现错误,并重新加载固件。

2.5.2 IAP实现要点

(1)关闭所有中断

在IAP程序执行过程中不需要产生任何中断,应在IAP程序起始部分关闭所有中断,否则当系统产生某种中断时,例如计时器中断、UART 中断、SPI 中断、GPIO中断、I2C中断和DMA中断等,程序指针会跳转到中断服务系统定义的“弱(weak)属性”中断服务程序:

这是一个无限循环函数,当发生某种中断时,程序指针将无法正常返回到IAP程序中,从而导致固件更新失败。

(2)IAP跳转的实现

IAP 程序跳转到固件程序的设计是通过GCC 内联汇编的方式实现的:

当固件加载完成后会执行这段汇编程序,将主内存中固件程序的地址存储在寄存器s1中,使用无条件跳转指令jr实现程序指针的跳转,去执行固件程序。

(3)设计CRC校验算法

在实际的应用中,使用IAP技术处理的文件是要被RISC-V 处理器运行的固件程序,因此任何细微的错误传输都将导致固件无法正常运行,可能会造成无法预估的损失。为了保证数据传输的可靠性,在IAP程序中设计了CRC校验算法:

式(1)中T为n比特的传输帧,D为k比特的数据,F为(n-k)比特的冗余位;式(2)中P为预先设定的(n-k+1)比特的整数,mod 为模2除法(即按位异或)[19]。只有通过校验(即式(2)的运算结果为0)的数据才会被烧写至Flash中。

3 FPGA原型验证

本设计使用Xilinx公司的Kintex®-7 FPGA KC705开发板进行固件更新系统的原型验证,具体的操作流程如下。

(1)将设计好的第一阶段启动代码编译成二进制码,固化于BootROM 中,并在KC705 开发板上实现RISC-V处理器的硬件设计。

(2)通过JTAG 将事先编译好的IAP 代码文件下载到片外Flash的IAP地址段。

(3)选择UPDATE模式并启动系统。

(4)通过超级终端输入更新指令“update”,此时在超级终端界面上可发现下位机一直向上位机发送字符“C”,以请求数据包。

(5)在超级终端界面上选用Ymodem 通信协议传输.bin格式的固件文件。

(6)待固件更新成功后,选择WORK 模式,重启系统即可运行更新后的固件程序。

嵌入式开发人员在更新RISC-V 处理器的固件时,需要执行的步骤只有(3)~(6)。

图7 展示了使用Ymodem 通信协议传输固件文件的过程。从图中可看出,在UART波特率为115 200 bit/s时,1 s内即可完成约10 KB固件的更新,固件更新速率为10 KB/s。在文献[10]中,UART 波特率为9 600 bit/s,在最理想情况下对其波特率进行转换计算,固件更新速率为7.5 KB/s。本设计方法与文献[10]相比,固件更新速率提高了约1.33倍。

图7 固件传输的过程Fig.7 Process of firmware transfer

图8是成功传输固件文件的结果,从串口打印出的信息可看出,系统运行正常,且经过连续20次重复实验验证,无系统异常情况发生,验证了此固件更新系统设计的可行性与稳定性。此固件更新系统现已用于接下来的基于FPGA的RISC-V处理器应用开发课题中。

图8 固件传输的结果Fig.8 Results of firmware transfer

4 结束语

RISC-V处理器的固件更新系统设计能给嵌入式开发人员的使用带来极大的便利。本文通过启动参数再配置的方法,为以Rocket Core为核心的RISC-VSoC设计了一种高效、灵活的BootROM引导流程,以及基于此种引导流程的IAP实现方法。经过多次实验验证,此固件更新系统具有操作简单、运行稳定等优点。未来可对IAP技术的实现方法进行优化,进一步提高系统固件的更新效率。

猜你喜欢
固件中断内存
“单片机中断概述”微课教学设计
一种考虑GPS信号中断的导航滤波算法
笔记本内存已经在涨价了,但幅度不大,升级扩容无须等待
“春夏秋冬”的内存
Linux中断线程化分析及中断延时测试
跟踪导练(二)(5)
基于SHA1的SCADA系统PLC固件完整性验证方法
基于固件的远程身份认证
内存搭配DDR4、DDR3L还是DDR3?
英特尔发布免费固件引擎