基于串口的QuickBoot远程升级
前言
注:需要本工程源码或者有任何问题可以联系我!
系统架构
-
串口转换芯片为 Silicon Labs CP2102GM,最大支持 1Mbps 传输速率,本实验使用 750000bps 波特率进行设计;
-
FPGA 芯片使用 AMD 7系列 xc7a35tfgg484-2,Bitstream 大小为 17,536,096 bits;
-
Flash 芯片使用 Numonyx 的 QSPI Flash N25Q128,接口时钟最大支持 108MHz,最小擦除单位 Subsector 为 4KB,Sector 为 64KB,本实验使用 QSPI 模式,接口速率 25MHz。
名称 | 典型值 | 最大值 | 单位 |
---|---|---|---|
页编程时间 | int(byte/8)*0.015,向上取整(256 Bytes 时间为 0.48) | 5 | s |
Subsector 擦除时间 | 0.2 | 2 | s |
Sector 擦除时间 | 0.7 | 3 | s |
串口传输 1 Byte(包含校验位) | 11/750000 ≈ 14.67 | us | |
串口传输 256 Bytes 升级数据(实际需传输 264 Bytes) | 264*11/750000 ≈ 3.872 | ms | |
总擦除时间(1 个 Subsector + 34 个 Sectors) | 24 | s |
Flash 大小计算
- 由于本实验 Flash 结构为 uniform 不能使用子扇区擦除指令(SSE),所以最小擦除单位为 1 个扇区(64KB)
名称 | 大小 |
---|---|
QuickBoot header,part 1 | 64KB |
QuickBoot header,part 2 | 256 bits |
Golden Image | 17,536,096 bits |
总计 | 17,569,120 bits |
换算成 Sector 个数 | 35 Sectors = 17.5Mb |
所以最小 Flash 大小为 | 17.5Mb + 34 Sectors = 34.5 Mb(update区域少去 part1 一个扇区大小) |
Flash 地址分配
串口通信协议
升级起始帧
偏移地址 | 字节数 | 定义 | 内容 |
---|---|---|---|
0 | 2 | 帧头 | 0xBCBD |
2 | 2 | 帧长度 | 单位 byte,不包括帧头、帧长度和帧类型 |
4 | 1 | 帧类型 | 0x01 |
5 | 4 | update 起始地址 | MSB 在前 |
9 | 4 | update 程序大小 | 单位 byte |
升级数据帧
偏移地址 | 字节数 | 定义 | 内容 |
---|---|---|---|
0 | 2 | 帧头 | 0xBCBD |
2 | 2 | 帧长度 | 单位 byte,不包括帧头、帧长度和帧类型 |
4 | 1 | 帧类型 | 0x02 |
5 | 3 | 包序号 | 从 1 开始 |
8 | 1-256 | 写入数据 |
升级状态帧
偏移地址 | 字节数 | 定义 | 内容 |
---|---|---|---|
0 | 2 | 帧头 | 0xBCBD |
2 | 2 | 帧长度 | 单位 byte,不包括帧头、帧长度和帧类型 |
4 | 1 | 帧类型 | 0x03 |
5 | 1 | 操作状态 | bit7:校验成功(1);bit6:回读校验完成(1);bit5:页编程完成(1);bit4:擦除完成(1);bit3:回读校验中(1);bit2:页编程中(1);bit1:扇区擦除中(1);bit0:子扇区擦除中(1) |
QuickBoot 远程升级步骤
生成出厂文件
远程升级
- FPGA 通过串口接收升级起始帧,FPGA 解析 update 起始地址 和 update 程序大小;
- FPGA 进行 Subsector 擦除操作(地址 0x00),即修改 critical switch word 值为 OFF;
- FPGA 进行 Sector 擦除操作(地址为 update 起始地址);
- 擦除完成后,等待写入数据缓存 FIFO 足够 256 Bytes(页大小)时进行一次页编程;
- 完成编程后,重复步骤 3-5;
- 完成 update 程序烧写后,回读 update 程序进行 CRC 校验;
- 若 CRC 校验正确则修改 critical switch word 值为 ON,否则上报 CRC校验错误状态。
注:golden 和 QuickBoot hear 的第二部分内容 (warm boot jump sequence) 都不允许更改。
QSPI 设计
QSPI 操作流程
- 接收到升级开始标志;
- 默认上电 Flash 为 单线 SPI 模式,需要写 VECR 寄存器使能四线模式(也可以写 NVCR 寄存器,但是NVCR 寄存器更改后下次上电才生效,但更改后除非重新写 NVCR 寄存器才能更改配置;而 VECR 只有每次写后才生效,断电重启后会恢复为 NVCR 的配置);
- 执行 SSE 指令;
- 执行 RFSR 指令获取 Flash 状态直至 Flash 为空闲状态;
- 执行 SE 指令;
- 执行 RFSR 指令获取 Flash 状态直至 Flash 为空闲状态;
- 等待写入数据缓存 FIFO 足够 256 Bytes(页大小)时执行 QCPP 指令;
- 执行 RFSR 指令获取 Flash 状态直至 Flash 为空闲状态;
- 重复 5-8 步骤,直至烧写完 update 数据;
- 执行 QCFR 指令,回读 update 数据进行 CRC 校验;
- 校验完成且结果正确,则执行 QCPP 指令,写 0xFFFC 地址写入 0xAA995566 同步字;
- 写 VECR 寄存器改为单线模式,否则 jtag 无法固化程序;
- Flash 操作完成。
Flash 时序
Extend SPI 指令
WREN
WRVECR
QIO-SPI 指令
QCFR
- 指令 0Bh, 6Bh, EBh 的结果都一样
WREN
- 手册该指令时序图错误,还是上升沿采数,下降沿传输
QCPP
- 需要先执行 WREN 指令
SSE
- 需要先执行 WREN 指令
- 手册该指令时序图错误,还是上升沿采数,下降沿传输
SE
- 需要先执行 WREN 指令
- 手册该指令时序图错误,还是上升沿采数,下降沿传输
RFSR
WRVECR
寄存器定义
Volatile Enhanced Configuration Register
Flag Status Register
- bit7:1(空闲),0(忙)
- bit6:1(擦除暂停)
- bit5:1(擦除失败)
- bit4:1(烧写失败)
- bit0:1(擦除或者烧写的空间为受保护区域,报错)
CRC32
- CRC32模型
-
回读校验(本工程使用方式一)
-
方式一:
对比回读计算出来的 CRC32 值和升级程序里写入的 CRC32 值是否一致,一致则表示校验成功
-
方式二:
将回读回来的所有 upgrade 数据(包括 CRC32 值)都进行 CRC32 计算,将计算的 32bits 结果进行反转继续输入进行 CRC 计算,计算结果若为常数 0xC704DD7B 则表示校验成功
-
-
CRC32 模块接口真值表
- 时序
STARTUPE2 原语
默认无法直接配置 CCLK,所以若要读写程序 FLASH,需使用 STARTUPE2原语才能控制 CCLK 引脚。
STARTUPE2 #(
.PROG_USR("FALSE"), // Activate program event security feature. Requires encrypted bitstreams.
.SIM_CCLK_FREQ(0.0) // Set the Configuration Clock Frequency(ns) for simulation.
)
STARTUPE2_inst (
.CFGCLK(), // 1-bit output: Configuration main clock output
.CFGMCLK(), // 1-bit output: Configuration internal oscillator clock output
.EOS(), // 1-bit output: Active high output signal indicating the End Of Startup.
.PREQ(), // 1-bit output: PROGRAM request to fabric output
.CLK(0), // 1-bit input: User start-up clock input
.GSR(0), // 1-bit input: Global Set/Reset input (GSR cannot be used for the port name)
.GTS(0), // 1-bit input: Global 3-state input (GTS cannot be used for the port name)
.KEYCLEARB(1), // 1-bit input: Clear AES Decrypter Key input from Battery-Backed RAM (BBRAM)
.PACK(1), // 1-bit input: PROGRAM acknowledge input
.USRCCLKO(qspi_clk), // 1-bit input: User CCLK input
// For Zynq-7000 devices, this input must be tied to GND
.USRCCLKTS(0), // 1-bit input: User CCLK 3-state enable input
// For Zynq-7000 devices, this input must be tied to VCC
.USRDONEO(1), // 1-bit input: User DONE pin output control
.USRDONETS(0) // 1-bit input: User DONE 3-state enable output
);
- CFGCLK:Master 模式下一直使能/连接,但除了配置的时候存在时钟,其他时候为无效的高电平;在配置了 USRCCLK 时,在 FPGA 配置结束后三个 clk 该时钟将切换到 USRCCLK。Configuration mode 是根据 M[2:0] 管脚配置的,最常用的是 M[2:0]=001 对应的 Master SPI 配置模式,Master 模式下 CCLK 由 FPGA 输出给 FLASH 的 SCLK;
- EOS:End Of Start,指示 FPGA 配置的结束,EOS 信号上电后一瞬即由低变高,指示配置完成,因此可用作 FPGA 启动的判断依据;
- CFGMCLK:配置内部振荡器时钟,是从内部的一个锁相环输出的 65MHz 时钟(不是很准),输出到 GPIO 的信号极其微弱,但 ILA 可以正常捕获,因此此时钟可用于 FPGA 内部逻辑,但不可直接输出(其驱动 I/O 的能力太弱了);
- USRDONEO:输出到 FPGA 的 DONE_0 管脚。一般而言,在硬件设计中会在这个管脚挂一个 LED 灯,以指示 FPGA 完成配置开始运行;
- USRDONETS:控制 DONE 管脚的三态门,1 将设置为高阻,0 将会把用户输入的 USRDONEO 输出到 DONE_0 管脚;
- USRCCLKO:在配置完成后,驱动 CCLK_0 管脚的用户自定义时钟。在配置完成后,前三个时钟周期用于切换时钟源,且不会被输出,但如果使用了 EMCCLK 管脚,则 EMCCLK 信号会出现在 CCLK 管脚上,直到过渡到用户自定义时钟;
- USRCCLKTS:控制 USRCCLKO 的三态门;
- GTS:全局三态门使能,要用户自定义 CCLK/DONE 等,此管脚必须置低。
其他信号详见官方手册说明,默认启动设置下,配置期间的时序图如下
IOBUF-IOSTANDARD
默认 IOSTANDARD 为 LVCMOS18,CVGBVS 决定 bank0 I/O支持的电压值,以及配置区间 bank14、bank15 的 I/O 所支持的电压值;
上位机设计
使用 pyqt5 进行设计,上位机界面如下:
IP 例化界面
上板验证
- 测试升级一次时间为 1 分钟
调试总结
-
Flash 结构为 uniform 不能使用子扇区擦除指令(SSE),只有 Top 和 Bottom 结构可以使用
-
Flash 的片选信号需要进行控制,不能一上来就一直是低电平
-
操作 Flash 之前要先产生时钟信号,用于 STARTUPE2 原语切换时钟源
-
使用 AX7035 开发板进行测试,SPI 时钟跑 50MHz 时,会出现采集错误,25MHz 没有问题
-
jtag 固化默认使用的是 spix1 模式,若当前 spi 模式操作模式不一致会导致固化失败