基于Smart ZYNQ (SP/SP2/SL 版) 的PS实验 二十二 5寸RGB屏实验: 用VDMA模块来缓存图像并在LCD上显示(二)显示TF卡上的BMP格式图片

本节作为前一节的补充,将TF卡上的图片通过VDMA的方式显示在RGB LCD屏幕上,作为VDMA的实战演练

因为本文内容和前一节有大量的重复雷同工作,所以本节只介绍关键的几个地方,需要看详细工程创建的请看 前一节的内容

  • 此章节内容适用于Smart ZYNQ SP SP2和 SL 版的板子 ( 不包含Smart ZYNQ 标准版 ),如是标准版或本站其他板子请看对应板子目录
  • 本文在 vivado2018.3版本上演示

本次实验需要外接本站的5寸IPS 屏幕模块,有关本次实验的 RGB屏的原理图手册以及其他例程资料可以参看下面汇总贴:5寸IPS 800X480 RGB接口LCD屏幕模块

一、VIVADO工程的修改(只增加SD使能功能,前一节已经操作)

vivado 在blockdesign里 使能SD功能,(之前工程其实已经做了这一步)

二、SDK部分的修改

1)接下来SDK部分我们作如下修改, 因为我们要加载TF卡,而TF卡的格式是FAT32的,所以这里我们需要加载FatFs库,xilinx已经帮我们集成了这部分库的功能,我们只需要使能功能就好,操作如下

2)添加 XILFFS 库

3)接下来需要使能 文件名称的功能 默认是关闭的

4)代码的编写

复制以下代码到main.c中

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xil_types.h"
#include "xil_cache.h"
#include "xparameters.h"
#include "xaxivdma.h"
#include "xaxivdma_i.h"
#include "sleep.h"
#include "ff.h"

#define WIDTH 800
#define HEIGHT 480

#define VDMA_BASEADDR XPAR_AXI_VDMA_0_BASEADDR

#define VIDEO_BASEADDR0 0x01000000
#define VIDEO_BASEADDR1 VIDEO_BASEADDR0+WIDTH*HEIGHT*3


void load_sd_bmp(u8 *frame,unsigned char mode)
{
static FATFS fatfs;
FIL fil;
u8 bmp_head[54];
UINT *bmp_width,*bmp_height;
UINT br;
int i;

f_mount(&fatfs,"",1);

if(mode==0)f_open(&fil,"A.bmp",FA_READ);
else f_open(&fil,"B.bmp",FA_READ);

f_lseek(&fil,0);
f_read(&fil,bmp_head,54,&br);

bmp_width = (UINT *)(bmp_head + 0x12);
bmp_height = (UINT *)(bmp_head + 0x16);

for(i=*bmp_height-1;i>=0;i--){
f_read(&fil,frame+i*(*bmp_width)*3,(*bmp_width)*3,&br);
}


f_close(&fil);

Xil_DCacheFlush();
}

void VDMA_init(){
Xil_Out32((VDMA_BASEADDR + 0x000), 0x00000001);
Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0);
Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR1);
Xil_Out32((VDMA_BASEADDR + 0x058), (WIDTH*3));
Xil_Out32((VDMA_BASEADDR + 0x054), (WIDTH*3));
Xil_Out32((VDMA_BASEADDR + 0x050), HEIGHT);
Xil_Out32((VDMA_BASEADDR + 0x028), 0X00000000);
}

int main(void) {

load_sd_bmp((u8*)VIDEO_BASEADDR0,0);
load_sd_bmp((u8*)VIDEO_BASEADDR1,1);
VDMA_init();

while(1){
Xil_Out32((VDMA_BASEADDR + 0x028), 0x00000000);
sleep(1);
Xil_Out32((VDMA_BASEADDR + 0x028), 0x00000001);
sleep(1);
}
}

代码非常好理解,load_sd_bmp 实现的功能是挂载TF卡,并且根据mode的值来读取TF卡中对应名称的图片,并将图片的内容存入对应的DDR地址内。(mode 是我自己加入的,通过mode的值的大小分别载入两张不同的图片,最终在主函数里实现两张图片显示的动态切换)

VIDEO_BASEADDR0,和VIDEO_BASEADDR1分别对应两帧的缓存地址(只要两个帧之间的地址相差的位置可以调整,只要不要彼此相互有交集产生内存相互影响就可以了)

#define VIDEO_BASEADDR0 0x01000000
#define VIDEO_BASEADDR1 VIDEO_BASEADDR0+WIDTH*HEIGHT*3

本文中我们的VDMA 并没有用库函数来进行配置,而是用更简洁的Xil_Out32方式来进行初始化和控制,我们在BLOCK DESIGN 中定义了VDMA的缓存有3个,这里我们只用两个缓存来进行演示。

主程序里 加载两张照片分别到VIDEO_BASEADDR0内存区域,和VIDEO_BASEADDR1内存区域,并完成VDMA初始化

		load_sd_bmp((u8*)VIDEO_BASEADDR0,0);
		load_sd_bmp((u8*)VIDEO_BASEADDR1,1);
		VDMA_init();

主循环很容易理解,前面我们已经对缓存帧0和缓存帧1分别填了不同的图像(这些地址在之前已存入TF图片信息),这里我们通过配置028h的4-0bit来让vdma停留在我们指定的缓存帧上(前文中已将vdma 配置在非循环状态下,Park Mode)

while(1){
Xil_Out32((VDMA_BASEADDR + 0x028), 0x00000000);
sleep(1);
Xil_Out32((VDMA_BASEADDR + 0x028), 0x00000001);
sleep(1);
}

结合while(1)以及sleep,最终我们实现了让屏幕在缓存帧1和缓存帧0中以1秒为间隔来回切换最终在LCD上显示了。

备注 本节中,我们的 VDMA仍然让他工作在指定帧显示的模式下。

三、上机调试

1)之后在电脑上插入FAT32格式的TF卡,并将下列文件下载并解压并存入TF卡的根目录(切记 TF卡必须为fat32格式) HDMI 测试图片 image下载

其中A,B是800X480的两张测试图

2)将TF卡从电脑正常退出,并插入到我们主板的 TF卡卡槽中

3) 回到SDK界面,对程序进行正常编译,并debug,没问题的话,应该可以看到两张800X480的图片在循环播放的。

写在实验后:

1)如果要更换其他屏幕不同分辨率的屏幕的话,只需要对VTC的分辨率,以及Clock时钟,以及main函数分辨率对应位置进行修改即可。

2)配置VDMA的方法除了可以用直接读写寄存器的方式外,也可以调用SDK VDMADEMO中的库函数来做,这里不再

  • 本文的完整工程下载:22_VDMA_5INCH_LCD_TF_IMAGE
  • 需放在TF卡下的测试图片在压缩包的文件中TEST_IMAGE_800X480文件夹中
  • VIVADO的版本:2018.3
  • 工程创建目录:E:\Smart_ZYNQ_SP_SL\SDK\22_VDMA_5INCH_LCD_TF_IMAGE
  • 工程适用主板: Smart ZYNQ (SP / SP2 / SL) (不适用于Smart ZYNQ 标准版 

“基于Smart ZYNQ (SP/SP2/SL 版) 的PS实验 二十二 5寸RGB屏实验: 用VDMA模块来缓存图像并在LCD上显示(二)显示TF卡上的BMP格式图片”的3个回复

  1. 博主你好!我在debug->build过程中,arm-none-eabi-gcc在链接步骤时,出现了如下报错:
    arm-none-eabi-gcc -L”D:\Projects\prj\AMD\bad_apple_7020_lcd\workspace\zynq_7020_badapple_lcd\ps7_cortexa9_0\standalone_domain\bsp\ps7_cortexa9_0\libsrc\xilffs_v5_3\src\include” -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -Wl,-build-id=none -specs=Xilinx.spec -Wl,-T -Wl,../src/lscript.ld -LD:/Projects/prj/AMD/lcd_7020/zynq_7020_lcd/workspace/zynq7_lcd/export/zynq7_lcd/sw/zynq7_lcd/standalone_domain/bsplib/lib -o “app_zynq7_lcd.elf” ./src/main.o -lxilffs -Wl,–start-group,-lxil,-lgcc,-lc,–end-group -Wl,–start-group,-lxilffs,-lxil,-lgcc,-lc,–end-group
    D:/AMD/Vitis/2024.2/gnu/aarch32/nt/gcc-arm-none-eabi/x86_64-oesdk-mingw32/usr/bin/arm-xilinx-eabi/../../libexec/arm-xilinx-eabi/gcc/arm-xilinx-eabi/13.3.0/ld.exe: ./src/main.o: in function `load_sd_bmp’:
    D:\Projects\prj\AMD\bad_apple_7020_lcd\workspace\app_zynq7_lcd\Debug/../src/main.c:29:(.text+0x40): undefined reference to `f_mount’
    D:/AMD/Vitis/2024.2/gnu/aarch32/nt/gcc-arm-none-eabi/x86_64-oesdk-mingw32/usr/bin/arm-xilinx-eabi/../../libexec/arm-xilinx-eabi/gcc/arm-xilinx-eabi/13.3.0/ld.exe: D:\Projects\prj\AMD\bad_apple_7020_lcd\workspace\app_zynq7_lcd\Debug/../src/main.c:31:(.text+0x60): undefined reference to `f_open’
    D:/AMD/Vitis/2024.2/gnu/aarch32/nt/gcc-arm-none-eabi/x86_64-oesdk-mingw32/usr/bin/arm-xilinx-eabi/../../libexec/arm-xilinx-eabi/gcc/arm-xilinx-eabi/13.3.0/ld.exe: D:\Projects\prj\AMD\bad_apple_7020_lcd\workspace\app_zynq7_lcd\Debug/../src/main.c:32:(.text+0x78): undefined reference to `f_open’
    D:/AMD/Vitis/2024.2/gnu/aarch32/nt/gcc-arm-none-eabi/x86_64-oesdk-mingw32/usr/bin/arm-xilinx-eabi/../../libexec/arm-xilinx-eabi/gcc/arm-xilinx-eabi/13.3.0/ld.exe: D:\Projects\prj\AMD\bad_apple_7020_lcd\workspace\app_zynq7_lcd\Debug/../src/main.c:34:(.text+0x84): undefined reference to `f_lseek’
    D:/AMD/Vitis/2024.2/gnu/aarch32/nt/gcc-arm-none-eabi/x86_64-oesdk-mingw32/usr/bin/arm-xilinx-eabi/../../libexec/arm-xilinx-eabi/gcc/arm-xilinx-eabi/13.3.0/ld.exe: D:\Projects\prj\AMD\bad_apple_7020_lcd\workspace\app_zynq7_lcd\Debug/../src/main.c:35:(.text+0x98): undefined reference to `f_read’
    D:/AMD/Vitis/2024.2/gnu/aarch32/nt/gcc-arm-none-eabi/x86_64-oesdk-mingw32/usr/bin/arm-xilinx-eabi/../../libexec/arm-xilinx-eabi/gcc/arm-xilinx-eabi/13.3.0/ld.exe: D:\Projects\prj\AMD\bad_apple_7020_lcd\workspace\app_zynq7_lcd\Debug/../src/main.c:41:(.text+0x108): undefined reference to `f_read’
    D:/AMD/Vitis/2024.2/gnu/aarch32/nt/gcc-arm-none-eabi/x86_64-oesdk-mingw32/usr/bin/arm-xilinx-eabi/../../libexec/arm-xilinx-eabi/gcc/arm-xilinx-eabi/13.3.0/ld.exe: D:\Projects\prj\AMD\bad_apple_7020_lcd\workspace\app_zynq7_lcd\Debug/../src/main.c:45:(.text+0x128): undefined reference to `f_close’
    collect2.exe: error: ld returned 1 exit status
    make[1]: *** [makefile:43: app_zynq7_lcd.elf] Error 1
    make: *** [makefile:34: all] Error 2
    我的vitis使用了2022.2和2024.2,均报告该错误。系统环境是Win10.
    我按照网上搜到的办法,在app project->properties/setting->ARM v7 gcc linker下添加了xilffs库,依旧报错,请问该如何解决?

    1. 看起来仍然是 xilffs的库没添加成功的问题 ,你在BSP 中直接修改勾选可以的吗? 另外我用chatgpt查了下说后续版本可能会有变化,对一下这些库中是否仍然存在f_read等函数

      1. 感谢您的回复,我把整个工程移植到了Ubuntu上的Vitis中,问题解决了。我猜测可能是Windows路径导致的。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注