嵌入式應用開發第四階段-基於rk3399的視頻監控系統


一、需求分析

伴隨着嵌入式技術、圖像處理技術和無線網絡傳輸技術的發展,傳統模擬視頻監控系統和基於PC的遠程視頻監控系統由於自身的不足,已經無法滿足現代社會應用中不斷涌現出來的新需求,於是基於嵌入式技術的無線網絡數字視頻監控系統就應因而生了。例如遠程監控、遠程教學、遠程醫療診斷、遠程購物、遠程探視、電視電話會議等應用都迫切需要高質量的網絡視頻傳輸的支持。考慮到了所用的硬件設備大部分都已經具備和我們所學到的知識及本身的能力有限,選擇基於rk3399的視頻監控系統作為我們本次的課程設計題目是比較實際而且比較容易掌握嵌入式開發的基本方法

設計實現功能要求

1)   利用USB攝像頭進行采集圖像數據的采集;

2)   利用rk3399對所采集到圖像數據進行解碼

3)   將解碼后的圖像顯示在LCD屏上。

設計用到的設備

1)   PC機

2)   RK3399開發板

3)   USB攝像頭

4)   type-c usb線

5)   CH340串口線

 

 

一、產品的系統構成

系統的工作原理

系統可以分為4 個模塊:圖像采集模塊、圖像存儲模塊、圖像處理模塊、圖像顯示模塊。系統在RK3399 的控制下從USB 攝像頭采集圖像數據,然后經過DMA 方式將圖像數據傳輸到內存緩沖區中,由軟件將圖像數據讀出並對圖像數據進行壓縮和打包處理后存入Flash 中, 最后圖像在LCD屏上。本系統的設計難點是如何保證內存中圖像數據的讀取與USB 攝像頭的同步以及圖像數據的實時處理。系統采用RK339作為嵌入式處理器,完全可以完成圖像數據的實時處理需求,比一般采用添加圖像硬件處理模塊減少了系統的成本.

 

二、軟硬件協同設計與程序建模

在開始應用編程之前,需要先准備好驅動,在LCD上顯示攝像頭圖像,至少需要三個驅動:LCD驅動、背光驅動、UVC驅動。

以前都是使用的insmod xx.ko進行動態加載驅動,每次開發板上電后,都需要手動/腳本里加載驅動,有點麻煩。

反觀內核自帶的驅動,使用make menuconfig進入圖形配置界面里,找到對應的驅動,可以設置為Y(編譯到內核)、M(編譯成模塊)、N(不編譯)。當設置為Y后,進入系統后,就自帶了該驅動,不再需要手動加載。

 

四,嵌入式產品的設計與開發

1.1 LCD 顯示原理

液晶顯示的原理基於液晶的透光率隨其所施電壓大小而變化的特性。當光通過上偏振片后,變成線性偏振光,偏振方向與偏振片振動方向一致,與上下玻璃基板上面液晶分子排列順序一致。當光通過液晶層時,由於受液晶折射,線性偏振光被分解為兩束光。又由於這兩束光傳播速度不同(相位相同),因而當兩束光合成后,必然使振光的振動方向發生變化。通過液晶層的光,則被逐漸扭曲。當光達到下偏振片時,其光軸振動方向被扭曲了90度,且與下偏振片的振動方向保持一致。這樣,光線通過下偏振片形成亮場。加上電壓以后,液晶在電場作用下取向,扭曲消失。這時,通過上偏振片的線性偏振光,在液晶層不再旋轉,無法通過下偏振片而形成暗場。可見液晶本身不發光,在外光源的調制下,才能顯示,在整個顯示過程中,液晶起到一個電壓控制的光閥作用。TFT-LCD的工作原理則可簡述為:當柵極正向電壓大於施加電壓時,漏源電極導通,當柵極正向電壓等於0或負電壓時,漏源電極斷開。漏電極與ITO象素電極連結,源電極與源線(列電極)連結,柵極與柵線(行電極)連結。這就是TFT-LCD的簡單工作原理

1.2 lcd示例

1)打開lcd設備:

   linux系統所有lcd設備名稱是統一是 /dev/fbX ,X是0~31 .

   RK3399 開發平台lcd設備情況:

   [root@edu118 ~]# ls /dev/fb*

   /dev/fb0

2)操作lcd設備

   a.獲得lcd屏的工作參數:可變參數和固定參數

   b.使用 mmap 函數把lcd的顯存映射到進程空間中 -- 得到一個顯存首地址

   c.通過映射得到的地址往顯存寫顏色數據。

   第一步:

   第二步:顯存首地址偏移+目標點偏移量 ---> 目標點在內存中的絕對地址

   第三步:根據 BPP 合成顏色寫入到目標點內存中

3)關閉 lcd設備,取消映射(munmap)

 

2 Linux系統下攝像圖像采集

172.16.14.208

1. Linux系統下標准的攝像頭框架V4L2

2. V4L2框架不局限應用在攝像頭,還有其他類設備

3. 攝像頭設備文件:

   /dev/videoX   X是一個整數從0開始。  

4. 攝像頭編程流程

Linux下一切都是文件!

1)打開攝像頭設備對應文件

int  video_device_open(const char*dev)

{

    fd_vd = open(dev, O_RDWR);  //阻塞方式打開

    if (-1 == fd_vd) {

        fprintf(stderr, "Cannot open '%s': %d, %s\n", dev_name, errno, strerror(errno));

        return -1;

    }

    return fd_vd;

}

 

2)各種操作

a. 查詢設備功能:

   因為打開的設備不一定就是攝像頭設備,不一定支持捕獲功能。

b. 根據上一步查詢結果來判斷是否支持捕獲功能

c. 查詢攝像頭支持的數據格式:

   因為不同型號的攝像頭支持不一樣格式,格式數量也不一樣。

  

d. 從支持格式選擇一種可以處理的數據格式 設置到硬件中。

e. 申請緩沖

f. 查詢緩沖信息:得到內存偏移量和長度

g. 使用 mmap 進行映射到進程空間中

h. 添加到采集隊列中

i. 啟動圖像采集

j. 取出一幀數據進行處理:實際把最早一幀數據從采集隊列取下來,需要自己去復制數據。

k. 把緩沖區重新添加到采集隊列

循環:j, k 兩步

l. 停止采集

m. 取消映射,關閉設備

3)關閉

 

2. 示例代碼

04-lcd-v4l2

 

3. 測試

1)編譯

編譯前根據自己的文件系統路徑修改 Makefile                                    

DEST := /home/edu118/work/nanopc-t4/rootfs/home

 

查看當前路徑

edu118@localhost:code$ pwd

/mnt/hgfs/OceanUniversity/2.示例代碼/04-lcd-v4l2/code

 

清上次編譯信息

edu118@localhost:code$ make clean

 

重新編譯

edu118@localhost:code$ make

'./app-lcd-v4l2' -> '/home/edu118/work/nanopc-t4/rootfs/home/app-lcd-v4l2'

自動復制 生成的  app-lcd-v4l2 到根文件系統的 /home/ 目錄中

 

2)開發板測試

a. 插上攝像頭

b. 啟動測試

 

3.LCD顯示框架

①:首先從攝像頭獲取數據放入video_buf,數據的格式(YUV、MJPEG、RGB)和分辨率可能有多種;

②:RK3399的LCD僅支持RGB格式,因此需要數據格式轉換;

③:RK3399的LCD分辨率是800X480,因此可能需要大小縮放;

④:根據LCD顯示流程,必須要將顯示數據寫入顯存(FrameBuffer);

⑤:最后LCD控制器會將顯存數據自動搬運到LCD/VGA等顯示設備上;

 

 

 

 

在應用編程中,要習慣面向對象編程(Object Oriented Programming),也就是把對象作為程序的基本單元,一個對象包含了數據和操作數據的函數,在C語言中常常用結構體(struct)來實現。

 

關於Linux內核C語言中的面向對象的實現,可以參考這篇博客,介紹了如何C語言實現面向對象,也通過這個能稍微理解Linux驅動中的操作函數的原理。

 

這里,模仿內核的編程框架,為每個模塊實現一個管理鏈表,模塊對應加入鏈表,再調用對應的操作函數,框架如下:

 

 

簡單說明下這個框架,主要有四個模塊:

video用於攝像頭數據采集,convert用於格式轉換、process用於縮放等操作、dispaly用於顯示。

以convert為例,有一個manager管理每個子模塊,將每個子模塊放入鏈表,向上提供統一的操作接口,調用對應文件的操作函數。

 

 

五.嵌入式系統移植

建立交叉編譯環境

搭建交叉編譯環境是嵌入式開發的第一步,也是必備的一步。搭建交叉環境的方法很多,不同的體系結構、不同的操作內容甚至是不同版本的內核,都會用到不用的交叉編譯器,選擇合適的交叉編譯器對於嵌入式開發是非常重要的。由於我們本次用到的是linux 2.6.32.2內核,故我們選擇了編譯器arm-linux-gcc-4.3.2[3]。以下安裝交叉編譯器的步驟:

1、下載交叉編譯器arm-linux-gcc-4.3.2,下載地址:http://www.handhelds.org/download/projects/toolchain/arm-linux-gcc-4.3.2.tar.bz2

2、復制arm-linux-gcc-4.3.2.tar.bz2到目錄 tmp/下並解壓:

# cd /tmp

# tar xvzf arm-linux-gcc-4.3.2.tar.bz2

3、把編譯器路徑加入系統環境變量,運行命令

#gedit /root/.bashrc

編輯/root/.bashrc 文件,在最后一行設置:

export PATH=$PATH:/usr/local/arm/4.3.2/bin

3.2.3解壓安裝源代碼和工具

1、下載linux 2.6.32.2內核源代碼

下載地址:http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.32.2.tar.gz

2、復制內核代碼至目錄/tmp/linux 並解壓

# tar –xvzf linux-2.6.32.2.tar.gz

3、解壓目標文件系統

這里我們使用現有的根文件系統資源root_qtopia-20100108.tgz,將它復制至目錄/usr/src 並解壓

# tar –xvzf root_qtopia-20100108.tgz

4、安裝目標文件系統映象制作工具mkyaffs2image

要把上一步中的root_qtopia 目錄燒寫入目標板中使用, 就需要使用相應的mkyaffs2image 工具,它是一個命令行的程序,使用它可以把主機上的目標文件系統目錄制作成一個映象文件,以燒寫到開發板中[4]

#tar xvzf /tmp/linux/mkyaffs2image.tgz –C /

3.2.4配置網絡文件系統NFS服務

1、設置共享目錄

運行命令 #gedit /etc/exports

編輯 nfs 服務的配置文件,添加以下內容:

/opt/FriendlyARM/mini2440/root_qtopia *(rw,sync,no_root_squash)

其中:/opt/FriendlyARM/mini2440/root_qtopia 表示nfs 共享目錄,它可以作為開發板的根文件系統通過nfs 掛接;* 表示所有的客戶機都可以掛接此目錄rw 表示掛接此目錄的客戶機對該目錄有讀寫的權力;no_root_squash 表示允許掛接此目錄的客戶機享有該主機的root 身份[5]

2、啟動NFS 服務

在命令行下運行:

#/etc/init.d/nfs start

3.3 定制Linux內核

Linux 內核是一個社區共同開發的作品,具備一個現代操作系統的所有功能,並能對絕大多數硬件提供支持。然而,我們本次設計有很多功能都沒有用到的,為了盡可能減少編譯出來的內核體積,在配置內核時,只需要配置需要用到的模塊。常用的配置內核的方法有make config ,make menuconfig和make xconfig這里我們使用最廣泛的make menuconfig[6]。執行“make menuconfig”,可進入配置內核界面:

 

 

 

配置萬能驅動USB攝像頭

在Device Drivers 菜單里面,選擇 Multimedia devices,回車進入,選擇如圖“*”號選項,並選擇Video capture adapters 進入

 

 

出現如圖菜單,找到如圖選項並進入

 

 

出現如圖菜單,選擇如圖“*”號選項,再選GSPCA based webcams 進入

 

 

這里我們選擇所有類型USB 攝像頭的支持

 

 

1)   配置網卡驅動

要配置網卡驅動,首先要配置網絡協議支持.在主菜單中,選擇 Netwoking support,回車進入子菜單, 選擇 Networking options 並進入下一級菜單,如圖配置選項

 

 

選擇完畢,一直退回到主菜單,並選擇進入 Device Drivers 菜單。找到 Network device support,選擇進入下一級菜單, 找到並進入 Ethernet (10 or 100Mbit) 選項[8], 選中:

<*> Generic Media Independent Interface device support

<*> DM9000 support

 

 

2)   配置串口驅動

在 Character devices 菜單中,選擇進入Serial drivers - - ->,選擇如圖選項,來配置串口驅動

 

 

3)   配置yaff2s文件系統的支持

要使用 yaffs2 文件系統,需要先配置nand flash 驅動支持,在Device drivers 菜單中選擇MTD 選項,按回車進入,找到 NAND Device Support 選項並進入,如圖選擇 Nand Flash 驅動支持

 

 

返回到內核配置主菜單,找到 File systems 選項進入,然后找到選項 Miscellaneous filesystems 並進入,再找到 YAFFS2 支持選項,如圖選擇

 

 

4)   配置NFS文件系統

在 File System 菜單中,選擇Network File Systems 文件系統的支持且進入, 選擇如圖選項,這樣配置編譯出的內核就可以通過 NFS 啟動系統了。

 

 

完成內核的配置並保存好,接着執行命令:

#make dep       ;生成依賴文件

#make zImage    ;生成壓縮的內核影象文件

3.4 制作目標文件系統映象

3.5 移植bootloader

(1) 打開DNW 程序,接上USB 電纜,根據菜單選擇功能號[v]開始下載supervivi

 

 

(2)點擊“USB Port->Transmit/Restore”選項,並選擇打開文件supervivi開始下載。

(3)下載完畢,BIOS 會自動燒寫supervivi 到Nand Flash 分區中,並返回到主菜單。

3.6 移植Linux內核

(1)在BIOS 主菜單中選擇功能號[k],開始下載linux 內核zImage

 

 

(2) 點擊“USB Port->Transmit”選項,並選擇打開相應的內核文件zImage開始下載.

(3) 下載完畢,BIOS 會自動燒寫內核到Nand Flash 分區中,並返回到主菜單

3.7移植根文件系統

(1)在BIOS 主菜單中選擇功能號[y],開始下載yaffs 根文件系統映象文件

 

(2) 點擊“ USB Port->Transmit/Restore ” 選項, 並選擇打開相應的文件系統映象文件

(3)下載完畢,BIOS 會自動燒寫內核到Nand Flash 分區中,並返回到主菜單

 

六.設計心得

本次設計參考了眾多書籍及網絡上的理論知識,在理解的基礎上結合思考及老師給我們做的項目演示,根據現有的硬件設備,對完整的內核代碼進行了相應的裁減,配置出適合我們所設計的系統的內核。整個過程看似有點按部就班,但真正操作起來並沒有那么簡單,很多時候都會出現一些莫名其妙的錯誤,以致無法進行下一步的操作。這時就需要回歸到理論方面的知識中去,經過多次嘗試才能得以解決。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM