ZYNQ EBAZ4205+HDMI擴(kuò)展板 顯示Linux桌面播放視頻

之前的文章介紹了如何生成EBAZ4205礦板的u-boot和Linux內(nèi)核,使用的硬件只有改完SD卡啟動的EBAZ4205裸板,只能通過串口與板子通信彤守。這次嘗試啟動桌面并播放視頻(由于EBAZ4205沒有引出USB董习,仍然通過串口控制)。原板子是沒有顯示接口的让蕾,需要自己做一塊HDMI擴(kuò)展板浪规。

ZYNQ的FPGA部分使用的是Artix-7,網(wǎng)上有不少Artix-7輸出HDMI的教程探孝,大多使用Digilent DVI IP笋婿,F(xiàn)PGA部分可以通過這個IP直接輸出TMDS編碼的數(shù)據(jù),這樣就不用專用的RGB2HDMI的IC了顿颅。Digilent DVI IP將RGB888 1080P時序的并口數(shù)據(jù)編碼成10bit一組的串行數(shù)據(jù)輸出到pin上缸濒,1080P的像素時鐘是148.5Mhz,F(xiàn)PGA內(nèi)部最高時鐘是148.5的5倍粱腻,采用雙邊延輸出庇配。Digilent DVI IP不支持將音頻編碼進(jìn)TMDS流,想要輸出音頻必須在FPGA上搭建I2S IP绍些,或者使用PDM的方式輸出捞慌。

EBAZEXT-V2擴(kuò)展板

EBAZEXT-V2 KiCad 6.0工程托管在 GitHub,Elrori/EBAZ4205遵守GPL柬批。

古早之前就畫過一板VGA的擴(kuò)展板啸澡,后來沒測過。VGA接口已過時氮帐,因此畫了一板HDMI嗅虏。板子中DDC/I2C部分不使用,可能有設(shè)計上的bug上沐。沒有DDC接口皮服,Linux將獲取不到顯示器分辨率,可以設(shè)置設(shè)備樹讓VDMA強(qiáng)制輸出1920x1080P60的畫面参咙。
接口資源:

  • USB-C供電龄广,EBAZ4205不用再接電源
  • CMOS/GPIO 接ov攝像頭或通用IO
  • 1.3寸LCD/GPIO 接SPI屏幕(1.3寸 240x240 SPI st7789方案)
  • USB轉(zhuǎn)串口
  • HDMI-A 1080P60
  • PDM音頻輸出
  • 按鍵x2、LEDx2

這次測試只用到了HDMI接口昂勒。


在這里插入圖片描述
在這里插入圖片描述

VIVADO 2019.1硬件搭建

為了輸出畫面蜀细,F(xiàn)PGA部分要將圖像數(shù)據(jù)從DDR搬運到DVI IP,該工作由XILINX VDMA完成戈盈。XILINX VDMA輸入AXI4-MM奠衔,輸出AXI4-Stream接口數(shù)據(jù),需要XILINX AXI4S-VID-OUT IP轉(zhuǎn)換為視頻時序塘娶。時序由XILINX VTC產(chǎn)生归斤。整個硬件架構(gòu)參考原子《領(lǐng)航者 ZYNQ 之嵌入式 SDK開發(fā)指南 V1.3》中的第20章,硬件搭完后必須先裸機(jī)測試下SD卡的圖片能不能顯示刁岸≡嗬铮可以直接復(fù)制原子的設(shè)計,但要修改內(nèi)存大小虹曙、增加concat_2和中斷迫横、增加MII接口和4bit concat番舆。硬件架構(gòu)下圖。圖中以太網(wǎng)使用的是GMII接口矾踱,125MHz x 8bit恨狈。4205板子使用MII的PHY芯片,GMII兼容MII呛讲,當(dāng)GMII工作在25MHz x 4bit時就是MII(高4位不用)禾怠。PHY芯片自動偵測鏈路速率,給FPGA 25MHz或2.5MHz時鐘贝搁。25MHz x 4bit=100Mbps吗氏,考慮到96clk幀間隔和包頭,實際速率大約90幾雷逆。

在這里插入圖片描述

圖中的中斷concat_2必須接上弦讽,否則petalinux報錯。綜合編譯導(dǎo)出硬件設(shè)計后產(chǎn)生以下文件備用:

to_pl.bit
fsbl.elf 
xxx.hdf (實際上xxx.hdf文件就足以可以產(chǎn)生fsbl.elf 和to_pl.bit了关面,petalinux-build之后就有了)

在ubuntu16.04環(huán)境編譯 u-boot & Linux

以下過程參考自CSDN文章

全部采用18.3版本坦袍。也可以用最新版本,但版本必須一致等太。如果選擇petalinux19.1之后版本,建議直接在ubuntu安裝 Vitis

下載:

去XILINX官網(wǎng)下載 petalinux-v2018.3-final-installer.run
https://github.com/Xilinx/linux-xlnx/releases/tag/xlnx_rebase_v4.14_2018.3
https://github.com/Xilinx/u-boot-xlnx/releases/tag/xilinx-v2018.3
https://github.com/Digilent/linux-digilent/blob/master/drivers/clk/clk-dglnt-dynclk.c
https://github.com/Digilent/linux-digilent/blob/master/drivers/gpu/drm/xilinx/digilent_encoder.c

執(zhí)行過程:

# 安裝petalinux
petalinux-v2018.3-final-installer.run ./petalinux
unzip u-boot和linux壓縮包到當(dāng)前目錄
# 載入petalinux環(huán)境
source ./petalinux/settings.sh
# 建立petalinux工程
petalinux-create --type project --template zynq --name proj
# 拷貝vivado export hardware 中生成的 hdf文件到當(dāng)前目錄
cp x.hdf ./
# 配置hdf到petalinux工程
cd proj
petalinux-config --get-hw-description=../
# 出現(xiàn)選擇框(我們選擇外部linux源碼編譯工程蛮放,因為我們需要在Linux中添加內(nèi)核模塊缩抡,兩個.c文件)
1. Image Packaging Configuration -> Root filesystem type 選項中選擇 SD card
2. Linux Components Selection -> linux-kernel選擇ext-local-src。新增的External linux-kernel local source settings選項內(nèi)填入你的剛解壓linux源碼完整路徑 保存退出包颁。
# 進(jìn)入之前解壓后的xilinx linux目錄
cd ../linux-xlnx-xlnx_rebase_v4.14_2018.3
#------------------------------------------------------------------------------------------
# 增加內(nèi)核驅(qū)動
# 打開
vi ./drivers/clk/Kconfig
# 加入以下內(nèi)容:
config COMMON_CLK_DGLNT_DYNCLK
    tristate "Digilent axi_dynclk Driver"
    depends on ARCH_ZYNQ || MICROBLAZE
    help
    ---help---
      Support for the Digilent AXI Dynamic Clock core for Xilinx
      FPGAs.
# 打開
vi ./drivers/clk/Makefile
# 加入以下內(nèi)容:
obj-$(CONFIG_COMMON_CLK_DGLNT_DYNCLK)   += clk-dglnt-dynclk.o
# 打開
vi ./drivers/gpu/drm/xilinx/Kconfig
# 加入以下內(nèi)容:
config DRM_DIGILENT_ENCODER
    tristate "Digilent VGA/HDMI DRM Encoder Driver"
    depends on DRM_XILINX
    help
      DRM slave encoder for Video-out on Digilent boards.
# 打開
vi ./drivers/gpu/drm/xilinx/Makefile
# 加入以下內(nèi)容:
obj-$(CONFIG_DRM_DIGILENT_ENCODER) += digilent_encoder.o

# 加入剛下載的.c文件
cp clk-dglnt-dynclk.c ./drivers/clk/
cp digilent_encoder.c ./drivers/gpu/drm/xilinx/

cd ../proj
# 配置linux內(nèi)核
petalinux-config -c kernel
1. 在 Device Drivers -> Graphics support瞻想,選擇 Digilent VGA/HDMI DRM Encoder Driver 按 y
2. 在 Device Drivers -> Common Clock Framework 選項中選擇 Digilent axi_dynclk Driver 按 y
3. 保存退出,要修改默認(rèn)的保存文件名
#------------------------------------------------------------------------------------------

以上過程就是在Linux中增加新內(nèi)核模塊/驅(qū)動的方法娩嚼,這個是編譯進(jìn)內(nèi)核而不是編譯成.ko驅(qū)動文件蘑险。可以參考原子《領(lǐng)航者 ZYNQ 之嵌入式Linux 開發(fā)指南 V1.5.2》第四篇驅(qū)動開發(fā)岳悟,講的很詳細(xì)佃迄。

  • 在對應(yīng)目錄加入.c文件
  • 修改對應(yīng)目錄內(nèi)的Makefile、Kconfig贵少。使之出現(xiàn)在make menuconfig菜單中

# 進(jìn)入petalinux工程編輯設(shè)備樹
vi project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi

【EBAZ4205+EBAZEXTV2】的設(shè)備樹內(nèi)容如下(EBAZEXTV2的LED/KEY外設(shè)未添加)呵俏。這東西在build之前看不到system-conf.dtsi的內(nèi)容,否則就可以不依賴petalinux了滔灶。
筆者不清楚pinctrl0部分的作用普碎,一般而言,在fsbl配置好FPGA后录平,MIO的多路選擇器已經(jīng)選到正確的引腳麻车,自帶的pinctrl驅(qū)動看似是多余的缀皱。ebaz-4205設(shè)備樹已經(jīng)出現(xiàn)在最新Linux內(nèi)核中,該設(shè)備樹可能是假定你沒有使用fsbl時編寫的动猬,比較完備啤斗。

以下內(nèi)容部分參考Linux內(nèi)核中的設(shè)備樹。與顯示相關(guān)的是最后三個端點枣察。

/include/ "system-conf.dtsi"
/ {
    model = "EBAZ4205 board";
    compatible = "xlnx,zynq-EBAZ4205", "xlnx,zynq-7000";

    aliases {
        ethernet0 = &gem0;
        serial0 = &uart1;
        mmc0 = &sdhci0;
    };

    memory@0 {
        device_type = "memory";
        reg = <0x0 0x10000000>;
    };

    chosen {
        bootargs = "";
        stdout-path = "serial0:115200n8";
    };

    ebaz-keys {
     compatible = "gpio-keys";
     autorepeat;
     s2 {
           label = "s2";
           gpios = <&gpio0 20 0>;
           /*KEY_POWER*/
           linux,code = <116>;
           wakeup-source;
           autorepeat;
     };

     s3 {
           label = "s3";
           gpios = <&gpio0 32 0>;
           /*KEY_HOME*/
           linux,code = <102>;
           wakeup-source;
           autorepeat;
     };
    };
    ebaz-leds {
        compatible = "gpio-leds";

        led-green {
            label = "green";
            gpios = <&gpio0 54 1>;
            default-state = "on";
        };
            led-red {
            label = "red";
            gpios = <&gpio0 55 1>;
            default-state = "on";
        };
    };
};

&clkc {
    ps-clk-frequency = <33333333>;
};

&gem0 {
   status = "okay";
   phy-mode = "mii";
   phy-handle = <&phy>;

   /* PHY clock */
   assigned-clocks = <&clkc 18>;
   assigned-clock-rates = <25000000>;

   phy: ethernet-phy@0 {
      reg = <0>;
   };
};

&smcc {
    status = "okay";
};
/**/
&nand0 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_nand0_default>;

    partition@0 {
        label = "nand-fsbl-uboot";
        reg = <0x0 0x8000000>;
    };
};

&pinctrl0 {
    pinctrl_nand0_default: nand0-default {
        mux {
            groups = "smc0_nand8_grp";
            function = "smc0_nand";
        };

        conf {
            groups = "smc0_nand8_grp";
            bias-pull-up;
        };
    };

    pinctrl_uart1_default: uart1-default {
        mux {
            groups = "uart1_4_grp";
            function = "uart1";
        };

        conf {
            groups = "uart1_4_grp";
            slew-rate = <0>;
            io-standard = <3>;
        };
    };
};

&sdhci0 {
    u-boot,dm-pre-reloc;
    status = "okay";
};

&uart1 {
    u-boot,dm-pre-reloc;
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_uart1_default>;
};


&amba_pl {
 
    hdmi_encoder_0:hdmi_encoder {
        compatible = "digilent,drm-encoder";
        //digilent,edid-i2c = <&i2c0>;//我沒有使用DDC/I2C接口因此把這段注釋争占,強(qiáng)制使用以下分辨率
        digilent,hpref = <1920>;
        digilent,vpref = <1080>;
    };
 
    xilinx_drm {
        compatible = "xlnx,drm";
        xlnx,vtc = <&v_tc_0>;
        xlnx,connector-type = "HDMIA";
        xlnx,encoder-slave = <&hdmi_encoder_0>;
        clocks = <&axi_dynclk_0>;
        dglnt,edid-i2c = <&i2c0>;
        planes {
            xlnx,pixel-format = "rgb888";
            plane0 {
                dmas = <&axi_vdma_0 0>;
                dma-names = "dma";
            };
        };
    };
};
&axi_dynclk_0 {
    compatible = "digilent,axi-dynclk";
    #clock-cells = <0>;
    clocks = <&clkc 15>;
};
&v_tc_0 {
    compatible = "xlnx,v-tc-5.01.a";
};

執(zhí)行:

petalinux-build
# 由zimage產(chǎn)生uImage:
petalinux-package --image -c kernel --format uImage
# 將設(shè)備樹名字改為devicetree.dtb
mv xxxx.dtb devicetree.dtb
# 如果更改了設(shè)備樹dts,不用再petalinux-build 序目,編譯設(shè)備樹:
petalinux-build -b device-tree

產(chǎn)生uboot臂痕、內(nèi)核(uImage)、根文件系統(tǒng)猿涨、設(shè)備樹(devicetree.dtb)握童、zynq_fsbl.elf、xx.bit叛赚。這里只用設(shè)備樹(devicetree.dtb)內(nèi)核(uImage)

uImage
devicetree.dtb

petalinux-build默認(rèn)會產(chǎn)生image.ub和zImage鏡像澡绩。image.ub是由zImage .dtb .cpio.gz 構(gòu)成。.cpio.gz 是內(nèi)存盤俺附。我習(xí)慣用uboot的bootm啟動uImage和加載設(shè)備樹肥卡,所以將zImage轉(zhuǎn)成uImage。用bootz啟動zImage也可以事镣。
內(nèi)存中的存放地址如下:

  • 0x0 devicetree_image
  • 0x8000 kernel_image
  • 0x1000000 ramdisk_image 如果使用內(nèi)存盤就放到這個位置步鉴,本文使用SD卡上的ext4根目錄,所以沒用到

進(jìn)入u-boot源碼璃哟。參考之前文章(EBAZ4205 ZYNQ 7Z010 u-boot & Linux 生成方法記錄)的4氛琢、5、6随闪、7阳似、8、9铐伴、10步生成 BOOT.bindevicetree.dtb撮奏,注意第10步使用的是新的硬件bit和fsbl.elf(這兩個文件可以從vivado&XILINX SDK生成也可以直接用上面petalinux-build產(chǎn)生的)。注意這里u-boot產(chǎn)生的devicetree.dtb是不需要的盛杰,用petalinux-build產(chǎn)生的挽荡。

參照之前文章第12步編寫uEnv.txt。

BOOT.bin
uEnv.txt

BOOT.bin uEnv.txt uImage devicetree.dtb放入SD卡fat32分區(qū)即供,分區(qū)大小設(shè)置為100M左右定拟。大部分進(jìn)入U-BOOT但啟動不了Linux的原因是U-BOOT的bootcmd變量設(shè)置不對。在運行bootcmd變量之前,U-BOOT會載入uEnv.txt內(nèi)的環(huán)境變量青自,可以在環(huán)境變量內(nèi)做一些操作跳過自動bootcmd株依。在uEnv.txt內(nèi)修改bootcmd或者加入類似于uenvcmd=run bootm...的命令來指定啟動過程。


根文件系統(tǒng)

可以直接使用的根文件系統(tǒng):linaro-precise-ubuntu-desktop-20120723305.tar.gz(https://releases.linaro.org/archive/12.07/ubuntu/precise-images/ubuntu-desktop/)

建議在命令行解壓到SD卡ext4分區(qū):

sudo tar --strip-components=3 -C /media/xxx/rootfs -xzpf linaro-precise-ubuntu-desktop-20120723-305.tar.gz binary/boot/filesystem.dir

分區(qū)工具用ubuntu自帶的圖形disk工具或者用 DiskGenius


啟動

啟動后在ebaz4205的自帶串口登錄延窜,執(zhí)行一些必要的修改:

vi /etc/apt/sources.list
# 源改為以下內(nèi)容
deb http://mirrors.ustc.edu.cn/ubuntu-old-releases/ubuntu/ precise main universe
deb-src http://mirrors.ustc.edu.cn/ubuntu-old-releases/ubuntu/ precise main universe
deb http://mirrors.ustc.edu.cn/ubuntu-old-releases/ubuntu/ precise-security main universe
deb-src http://mirrors.ustc.edu.cn/ubuntu-old-releases/ubuntu/ precise-security main universe
deb http://mirrors.ustc.edu.cn/ubuntu-old-releases/ubuntu/ precise-updates main universe
deb-src http://mirrors.ustc.edu.cn/ubuntu-old-releases/ubuntu/ precise-updates main universe
# 安裝
apt-get update
apt-get install openssh-server mplayer fbi jfbterm

該Linux內(nèi)核已經(jīng)支持HDMI上的 FrameBuffer 所有對顯存的操作都是針對/dev/fb0文件的恋腕。FrameBuffer學(xué)習(xí)參考

http://bbs.chinaunix.net/thread-1932291-1-1.html

https://zhouyuqian.com/2020/05/11/ZYNQ-%E7%A7%BB%E6%A4%8D-Linux-Frame-Buffer/

https://blog.yangl1996.com/post/ba-tu-pian-zhi-jie-xie-ru-framebuffer/
framebuffer的c語言操作一般是這樣的:

    // 完整的程序參見附錄,該程序引用自原子《領(lǐng)航者 ZYNQ 之嵌入式Linux 開發(fā)指南 V1.5.2》逆瑞。
    fd = open("/dev/fb0", O_RDWR);
    /* 獲取framebuffer設(shè)備的參數(shù)信息 */
    ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
    ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);
    screensize = fb_var.yres * fb_fix.line_length;
    // 用戶內(nèi)存到內(nèi)核地址的映射
    // 如果不做映射荠藤,就相當(dāng)于讀寫文件,讀寫文件函數(shù)會進(jìn)入內(nèi)核態(tài)運行获高,將數(shù)據(jù)拷貝到用戶內(nèi)存哈肖。多一次拷貝。
    // mmap在八股文中經(jīng)常出現(xiàn)念秧,總算是碰到實際應(yīng)用了
    base = (unsigned char *)mmap(NULL, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    memset(base, 0x00, screensize);         // 顯存清零

打開桌面:

# lightdm上電初期存在順序bug淤井,顯示不正常,需要先關(guān)閉lightdm上電啟動摊趾。
echo  "manual" | sudo tee -a /etc/init/lightdm.override
kill -9 <lightdm的pid>
# 重新啟動lightdm桌面
startx &

嘗試播放視頻

一币狠、圖片文件與pdf文件瀏覽:

fbi -T 1 1.JPG
fbgs -c 1.pdf
在這里插入圖片描述

二、視頻播放砾层,可以用mplayer:

mplayer -lavdopts threads=2 -vo fbdev:/dev/fb0 -nosound /root/Videos/1080p1.mp4

-vo fbdev:/dev/fb0 指定framebuffer文件漩绵。
當(dāng)采用兩個線程時,幀數(shù)少許提高肛炮,cpu占用率為90%渐行。幀數(shù)仍然很低。但是铸董,能放1080P視頻已經(jīng)是意料之外了。


ebaz1-4.gif

三肴沫、中文顯示(HDMI屏幕顯示終端粟害,串口輸入按鍵):

jfbterm
在這里插入圖片描述

以上備忘
有些地方仍有不足,實際復(fù)現(xiàn)時可能會遇到其他困難颤芬,如有疑問歡迎討論學(xué)習(xí)

附錄

/***************************************************************
 Copyright ? ALIENTEK Co., Ltd. 1998-2029. All rights reserved.
 文件名    : lcdTest.c
 作者      : 鄧濤
 版本      : V1.0
 描述      : LCD應(yīng)用層測試程序
 其他      : 無
 論壇      : www.openedv.com
 日志      : 初版V1.0 2020/7/23 鄧濤創(chuàng)建
 ***************************************************************/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>

static void display_demo_1 (unsigned char *frame, unsigned int width, unsigned int height, unsigned int stride)
{
        unsigned int xcoi, ycoi;
        unsigned char wRed, wBlue, wGreen;
        unsigned int iPixelAddr = 0;

        for(ycoi = 0; ycoi < height; ycoi++) {

                for(xcoi = 0; xcoi < (width * 3); xcoi += 3) {

                        if (((xcoi / 4) & 0x20) ^ (ycoi & 0x20)) {
                                wRed = 255;
                                wGreen = 255;
                                wBlue = 255;
                        } else {
                                wRed = 0;
                                wGreen = 0;
                                wBlue = 0;
                        }

                        frame[xcoi + iPixelAddr + 0] = wRed;
                        frame[xcoi + iPixelAddr + 1] = wGreen;
                        frame[xcoi + iPixelAddr + 2] = wBlue;
                }

                iPixelAddr += stride;
        }
}

static void display_demo_2 (unsigned char *frame, unsigned int width, unsigned int height, unsigned int stride)
{
        unsigned int xcoi, ycoi;
        unsigned int iPixelAddr = 0;
        unsigned char wRed, wBlue, wGreen;
        unsigned int xInt;

        xInt = width * 3 / 8;
        for(ycoi = 0; ycoi < height; ycoi++) {

                for(xcoi = 0; xcoi < (width*3); xcoi+=3) {

                        if (xcoi < xInt) {                                   //White color
                                wRed = 255;
                                wGreen = 255;
                                wBlue = 255;
                        }
                        else if ((xcoi >= xInt) && (xcoi < xInt*2)) {         //YELLOW color
                                wRed = 255;
                                wGreen = 255;
                                wBlue = 0;
                        }
                        else if ((xcoi >= xInt * 2) && (xcoi < xInt * 3)) {        //CYAN color
                                wRed = 0;
                                wGreen = 255;
                                wBlue = 255;
                        }
                        else if ((xcoi >= xInt * 3) && (xcoi < xInt * 4)) {        //GREEN color
                                wRed = 0;
                                wGreen = 255;
                                wBlue = 0;
                        }
                        else if ((xcoi >= xInt * 4) && (xcoi < xInt * 5)) {        //MAGENTA color
                                wRed = 255;
                                wGreen = 0;
                                wBlue = 255;
                        }
                        else if ((xcoi >= xInt * 5) && (xcoi < xInt * 6)) {        //RED color
                                wRed = 255;
                                wGreen = 0;
                                wBlue = 0;
                        }
                        else if ((xcoi >= xInt * 6) && (xcoi < xInt * 7)) {        //BLUE color
                                wRed = 0;
                                wGreen = 0;
                                wBlue = 255;
                        }
                        else {                                                //BLACK color
                                wRed = 0;
                                wGreen = 0;
                                wBlue = 0;
                        }

                        frame[xcoi+iPixelAddr + 0] = wRed;
                        frame[xcoi+iPixelAddr + 1] = wGreen;
                        frame[xcoi+iPixelAddr + 2] = wBlue;
                }

                iPixelAddr += stride;
        }
}

int main (int argc, char **argv)
{
        struct fb_var_screeninfo fb_var = {0};
        struct fb_fix_screeninfo fb_fix = {0};
        unsigned int screensize;
        unsigned char *base;
        int fd;

        /* 打開LCD */
        fd = open("/dev/fb0", O_RDWR);

        if (fd < 0) {
                printf("Error: Failed to open /dev/fb0 device.\n");
                return fd;
        }

        /* 獲取framebuffer設(shè)備的參數(shù)信息 */
        ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
        ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);

        /* mmap映射 */
        screensize = fb_var.yres * fb_fix.line_length;
        base = (unsigned char *)mmap(NULL, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        if ((unsigned char *)-1 == base) {
                close(fd);
                return -1;
        }

        memset(base, 0x00, screensize);         // 顯存清零

        /* 循環(huán)顯示不同顏色 */
        for ( ; ; ) {

                display_demo_1(base, fb_var.xres, fb_var.yres, fb_fix.line_length);
                sleep(2);

                display_demo_2(base, fb_var.xres, fb_var.yres, fb_fix.line_length);
                sleep(2);
        }

        /* 關(guān)閉設(shè)備 釋放內(nèi)存 */
        memset(base, 0x00, screensize);
        munmap(base, screensize);
        close(fd);
        return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末悲幅,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子站蝠,更是在濱河造成了極大的恐慌汰具,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件菱魔,死亡現(xiàn)場離奇詭異留荔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)澜倦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門聚蝶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杰妓,“玉大人,你說我怎么就攤上這事碘勉∠锘樱” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵验靡,是天一觀的道長倍宾。 經(jīng)常有香客問我,道長胜嗓,這世上最難降的妖魔是什么高职? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮兼蕊,結(jié)果婚禮上初厚,老公的妹妹穿的比我還像新娘。我一直安慰自己孙技,他們只是感情好产禾,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著牵啦,像睡著了一般亚情。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哈雏,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天楞件,我揣著相機(jī)與錄音,去河邊找鬼裳瘪。 笑死土浸,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的彭羹。 我是一名探鬼主播黄伊,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼派殷!你這毒婦竟也來了还最?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤毡惜,失蹤者是張志新(化名)和其女友劉穎拓轻,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體经伙,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡扶叉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辜梳。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡粱甫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出作瞄,到底是詐尸還是另有隱情茶宵,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布宗挥,位于F島的核電站乌庶,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏契耿。R本人自食惡果不足惜瞒大,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望搪桂。 院中可真熱鬧透敌,春花似錦、人聲如沸踢械。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽内列。三九已至撵术,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間话瞧,已是汗流浹背嫩与。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留交排,地道東北人划滋。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像埃篓,于是被迫代替她去往敵國和親古毛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容