2410開發(fā)板實驗參考書_第1頁
2410開發(fā)板實驗參考書_第2頁
2410開發(fā)板實驗參考書_第3頁
2410開發(fā)板實驗參考書_第4頁
2410開發(fā)板實驗參考書_第5頁
已閱讀5頁,還剩274頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

BeijingUniversalPioneeringTechnologyCo.,LTD.PAGE84TEL:010-82110740821107418211074282110743FAX:總機轉828TOC\o"1-2"\h\z\u第一章嵌入式Linux開發(fā)基礎知識 21.1嵌入式Linux簡介 21.2嵌入式Linux開發(fā)平臺簡介 41.3嵌入式Linux開發(fā)流程 91.4嵌入式Linux開發(fā)環(huán)境的建立 11第二章基礎實驗 232.1熟悉Linux開發(fā)環(huán)境 232.2多線程應用程序設計 272.3串行端口程序設計 402.4CAN總線通訊實驗 512.5簡單嵌入式WEB服務器實驗 64第三章圖形界面應用程序設計 793.1安裝與建立Qt桌面運行環(huán)境 793.2QtDesigner簡介以及Qt/E的交叉編譯 863.3建立本機Qtopia虛擬平臺 943.4Qtopia2.1.1在2410上的移植 99第四章內(nèi)核實驗 1034.1Linux內(nèi)核移植與編譯實驗 103第五章驅動模塊實驗 1305.1內(nèi)核驅動設計入門-模塊方式驅動實驗 1305.2內(nèi)核驅動設計實驗-觸摸屏驅動 1615.3SD卡使用實驗 1855.4IDE_硬盤讀寫實驗 2115.5音頻驅動及應用實驗 2245.6藍牙無線通訊實驗 240第六章附錄 2536.1常用LINUX命令的使用 2536.2VI簡介 2606.3GCC與GDB 2626.4GNU通用公共許可證(GPL1991.6第二版) 2656.5北京博創(chuàng)興業(yè)科技嵌入式系統(tǒng)培訓中心 271

第一章嵌入式Linux

開發(fā)基礎知識隨著后PC時代的到來,嵌入式系統(tǒng)技術已經(jīng)成為了一個萬眾矚目的焦點。目前已廣泛應用于信息家電、數(shù)據(jù)網(wǎng)絡、工業(yè)控制、醫(yī)療衛(wèi)生、航空航天等眾多領域。巨大的市場潛力,無窮的商機,吸引了各路英豪紛踵沓來。硬件方面,各大電子廠商相繼推出了自己的專用嵌入式芯片,漫天而至的是mp3,PDA,無線上網(wǎng)裝置,讓人們充分感受到了這股強勁之勢;軟件方面,在Vxworks、pSOS、Neculeus和WindowsCE等嵌入式操作系統(tǒng)引領下,也出現(xiàn)了空前繁榮的局面,但這些專用操作系統(tǒng)都是商業(yè)化產(chǎn)品,其高昂的價格使許多面向低端產(chǎn)品的小公司望而卻步,并且其源代碼的封閉性也大大限制了開發(fā)者的積極性。近兩年在我國登陸并蓬勃發(fā)展的Linux,也已廣泛應用于各類計算應用,不僅包括IBM的微型Linux腕表、手持設備(PDA和蜂窩電話)、因特網(wǎng)裝置、客戶機、防火墻、工業(yè)機器人和電話基礎設施設備,甚至還包括了基于集群的超級計算機。Linux在高端服務器的優(yōu)越表現(xiàn)及其天生具有的突出特點,就注定它必將在低端嵌入式系統(tǒng)中再次給人們以驚喜,而基于嵌入式Linux操作系統(tǒng)的應用,必定給我們未來的工作和生活帶來翻天覆地的變化。1.1嵌入式Linux簡介Linux正在嵌入式開發(fā)領域穩(wěn)步發(fā)展。Linux使用GPL,所有對特定開發(fā)板、PDA、掌上機、可攜帶設備等使用嵌入式Linux感興趣的人都可以從因特網(wǎng)上免費下載其內(nèi)核和應用程序,并開始移植和開發(fā)。許多Linux改良品種迎合了嵌入式市場,它們包括RTLinux(實時Linux)、uclinux(用于非MMU設備的Linux)、MontavistaLinux(用于ARM、MIPS、PPC的Linux分發(fā)版)、ARM-Linux(ARM上的Linux)和其它Linux系統(tǒng)。嵌入式Linux的發(fā)展比較迅速。NEC、索尼已經(jīng)在銷售個人視頻錄像機等基于Linux的消費類電子產(chǎn)品,摩托羅拉則計劃在其未來的大多數(shù)手機上使用Linux,IBM也制定了在手持機上運行Linux的計劃。數(shù)年來,“Linux標準庫”組織一直在從事對在服務器上運行的Linux進行標準化的工作,現(xiàn)在,嵌入式計算領域也開始了這一工作。嵌入式Linux標準吸引了“Linux標準庫”以及Unix組織中有益的元素。在嵌入式系統(tǒng)中使用Linux的優(yōu)點和缺點雖然大多數(shù)Linux系統(tǒng)運行在PC平臺上,但Linux也是嵌入式系統(tǒng)的可靠主力。Linux的安裝和管理比UNIX更加簡單靈活,這對于那些UNIX專家們來說又是一個優(yōu)點,因為Linux中有許多命令和編程接口同傳統(tǒng)的UNIX一樣。但是對于習慣于WINDOWS操作系統(tǒng)的人來說,需要記憶大量的命令行參數(shù)卻是一個缺點。隨著LINUX社團的不斷努力,linux的人機界面開發(fā)環(huán)境正在不斷完善。典型的Linux系統(tǒng)經(jīng)過打包,在擁有硬盤和大容量內(nèi)存的PC機上運行,嵌入式系統(tǒng)不需要這么高的配置。一個功能完備的Linux內(nèi)核要求大約1MB內(nèi)存。而Linux微內(nèi)核只占用其中很小一部分內(nèi)存,包括虛擬內(nèi)存和所有核心的操作系統(tǒng)功能在內(nèi),只需占用系統(tǒng)約100K內(nèi)存。只要有500K的內(nèi)存,一個有網(wǎng)絡棧和基本實用程序的完全的Linux系統(tǒng)就可以在一臺8位總線(SX)的Intel386微處理器上運行的很好了。由于內(nèi)存要求常常是需要的應用所決定的,比如Web服務器或者SNMP代理,Linux系統(tǒng)甚至可以僅使用256KBROM和512KBRAM進行工作。因此它是一個瞄準嵌入式市場的輕量級操作系統(tǒng)。與傳統(tǒng)的實時操作系統(tǒng)相比(RTOS),采用象嵌入式Linux這樣的開放源碼的操作系統(tǒng)的另外一個好處是Linux開發(fā)團體看來會比RTOS的供應商更快地支持新的IP協(xié)議和其它協(xié)議。例如,用于Linux的設備驅動程序要比用于商業(yè)操作系統(tǒng)的設備驅動程序多,如網(wǎng)絡接口卡(NIC)驅動程序以及并口和串口驅動程序。核心Linux操作系統(tǒng)本身的微內(nèi)核體系結構相當簡單。網(wǎng)絡和文件系統(tǒng)以模塊形式置于微內(nèi)核的上層。驅動程序和其它部件可在運行時作為可加載模塊編譯到或者是添加到內(nèi)核。這為構造定制的可嵌入系統(tǒng)提供了高度模塊化的構件方法。而在典型情況下該系統(tǒng)需結合定制的驅動程序和應用程序以提供附加功能。嵌入式系統(tǒng)也常常要求通用的功能,為了避免重復勞動,這些功能的實現(xiàn)運用了許多現(xiàn)成的程序和驅動程序,它們可以用于公共外設和應用。Linux可以在外設范圍廣泛的多數(shù)微處理器上運行,并早已經(jīng)有了現(xiàn)成的應用庫。Linux用于嵌入式的因特網(wǎng)設備也是很合適的,原因是它支持多處理器系統(tǒng),該特性使Linux具有了伸縮性。因而設計人員可以選擇在雙處理器系統(tǒng)上運行實時應用,提高整體的處理能力。例如,您可以在一個處理器運行GUI,同時在另一個處理器上運行Linux系統(tǒng)。在嵌入式系統(tǒng)上運行Linux的一個缺點是Linux體系提供實時性能需要添加實時軟件模塊。而這些模塊運行的內(nèi)核空間正是操作系統(tǒng)實現(xiàn)調(diào)度策略、硬件中斷異常和執(zhí)行程序的部分。由于這些實時軟件模塊是在內(nèi)核空間運行的,因此代碼錯誤可能會破壞操作系統(tǒng)從而影響整個系統(tǒng)的可靠性,這對于實時應用將是一個非常嚴重的弱點。已經(jīng)有許多嵌入式Linux系統(tǒng)的示例;可以有把握地說,某種形式的Linux能在幾乎任一臺執(zhí)行代碼的計算機上運行。1.2嵌入式Linux開發(fā)平臺簡介Linux價格低廉、功能強大,可以運行在X86,Alpha,Sparc,MIPS,PPC,MOTOROLA,NEC,ARM等硬件平臺上,而且開放源代碼,可以定制。我們所介紹的硬件平臺是基于ARM體系結構,由北京博創(chuàng)興業(yè)科技有限公司開發(fā)的UP-NetARM3000和UP-NetARM2410開發(fā)板。UP-NetARM3000的CPU為ARM7TDMI內(nèi)核的三星S3C44B0X01芯片,由于沒有MMU(內(nèi)存管理單元)只能運行uClinux,UP-NetARM2410開發(fā)板的CPU為ARM920T內(nèi)核的三星S3c2410芯片,由于有MMU可以運行標準的ARM-LINUX內(nèi)核。通過這兩個平臺,我們可以學習嵌入式LINUX中的針對有MMU和無MMU的不同開發(fā)過程。UP-NetARM3000及相關產(chǎn)品的資料可以訪問博創(chuàng)公司的網(wǎng)站獲得。本書以UP-NetARM2410開發(fā)板為例,詳細介紹嵌入式Linux的開發(fā)過程。UP-NetARM2410開發(fā)板實驗儀器介紹硬件配置UP-NetARM2410開發(fā)板的硬件配置如表1.2.1所示,實物如圖1配置名稱型號說明CPUARM920T結構芯片三星S3c2410X工作頻率203MHzFLASHSAMSUNGK9F120864MSDRAMHY57V561620AT-H32M×2=64MEtherNet網(wǎng)卡DM9000AEP10/100M自適應LCD(可選)一個32腳薄膜線插座觸摸屏(可選)一個8腳觸摸屏插座FM7843驅動LED兩個小數(shù)碼管和3個發(fā)光二極管USB接口1個HOST/1個DEVICEUART2個RS232從處理器的UART2引出AD由S3C2410芯片引出板載兩個分壓精密電位器AUDIOIIS總線,UDA1341芯片44.1KHz音頻擴展插座3個40PinEXPORT總線直接擴展IDE/CF卡接口IDE硬盤接口,CF(IDE模式)卡MMC和SD卡接口調(diào)試接口JTAG14針按鍵三個可產(chǎn)生中斷的按鍵2片IIC存儲器AT24C01CANBUS由MCP2510和TJA1050構成PWM和DA輸出MAX504兩路PWM輸出和DA電路DC5V電源輸入具備LDO產(chǎn)生3.3V和1.8V的電壓備有RESET、RTC電路表1.2.1UP-NetARM2410的硬件配置圖1.2.1UP-NetARM2410S3c2410芯片介紹S3c2410X芯片集成了大量的功能單元,包括:1.內(nèi)部1.8V,存儲器3.3V,外部IO3.3V,16KB數(shù)據(jù)CACH,16KB指令CACH,MMU;2.內(nèi)置外部存儲器控制器(SDRAM控制和芯片選擇邏輯);3.LCD控制器(最高4K色STN和256K彩色TFT),一個LCD專用DMA;4.4路帶外部請求線的DMA;5.三個通用異步串行端口(IrDA1.0,16-ByteTxFIFO,and16-ByteRxFIFO),2通道SPI;6.一個多主IIC總線,一個IIS總線控制器;7.SD主接口版本1.0和多媒體卡協(xié)議版本2.11兼容;8.2個USBHOST,一個USBDEVICE(VER1.1);9.4個PWM定時器和一個內(nèi)部定時器;10.看門狗定時器;11.117個通用IO;12.24個外部中斷;13.電源控制模式:標準、慢速、休眠、掉電;14.8通道10位ADC和觸摸屏接口;15.帶日歷功能的實時時鐘;16.芯片內(nèi)置PLL;17.設計用于手持設備和通用嵌入式系統(tǒng);18.16/32位RISC體系結構,使用ARM920TCPU核的強大指令集;19.ARM帶MMU的先進的體系結構支持WINCE、EPOC32、LINUX;20.指令緩存(cache)、數(shù)據(jù)緩存、寫緩沖和物理地址TAGRAM,減小了對主存儲器帶寬和性能的影響;21.ARM920TCPU核支持ARM調(diào)試的體系結構;22.內(nèi)部先進的位控制器總線(AMBA2.0,AHB/APB).其結構圖如圖1.2.圖1.2.2S3c2410系統(tǒng)管理:1.小端/大端支持;2.地址空間:每個BANK128MB(全部1G字節(jié));3.每個BANK可編程為8/16/32位數(shù)據(jù)總線;4.bank0到bank6為固定起始地址;5.bank7可編程BANK起始地址和大??;6.一共8個存儲器BANK;7.6個存儲器BANK用于ROM,SRAM和其他;8.2個存儲器BANK用于ROM,SRAM和同步DRAM;9.每個存儲器BANK可編程存取周期;10.支持等待信號用以擴展總線周期;11.支持SDRAM掉電模式下的自刷新;12.支持不同類型的ROM用于啟動NOR/NANDFlash,EEPROM和其他。芯片封裝:272-FBGA封裝圖如圖1.2.圖1.2.3272-FBGA封裝1.3嵌入式Linux開發(fā)流程嵌入式linux開發(fā),根據(jù)應用需求的不同有不同的配置開發(fā)方法,但是一般都要經(jīng)過以下過程:建立開發(fā)環(huán)境。操作系統(tǒng)一般使用REDHAT-LINUX,版本7到9都可以,選擇定制安裝或全部安裝,通過網(wǎng)絡下載相應的GCC交叉編譯器進行安裝(比如arm-linux-gcc、arm-uclibc-gcc),或者安裝產(chǎn)品廠家提供的交叉編譯器。配置開發(fā)主機。配置MINICOM,一般參數(shù)為波特率115200,數(shù)據(jù)位8位,停止位1,無奇偶校驗,軟硬件控制流設為無。在WINDOWS下的超級終端的配置也是這樣。MINICOM軟件的作用是作為調(diào)試嵌入式開發(fā)板信息輸出的監(jiān)視器和鍵盤輸入的工具;配置網(wǎng)絡,主要是配置NFS網(wǎng)絡文件系統(tǒng),需要關閉防火墻,簡化嵌入式網(wǎng)絡調(diào)試環(huán)境設置過程。建立引導裝載程序BOOTLOADER,從網(wǎng)絡上下載一些公開源代碼的BOOTLOADER,如U-BOOT、BLOB、VIVI、LILO、ARM-BOOT、RED-BOOT等,根據(jù)自己具體芯片進行移植修改。有些芯片沒有內(nèi)置引導裝載程序,比如三星的ARM7、ARM9系列芯片,這樣就需要編寫燒寫開發(fā)板上flash的燒寫程序,網(wǎng)絡上有免費下載的WINDOWS下通過JTAG并口簡易仿真器燒寫ARM外圍flash芯片的程序。也有LINUX下公開源代碼的J-FLASH程序。如果不能燒寫自己的開發(fā)板,就需要根據(jù)自己的具體電路進行源代碼修改。這是讓系統(tǒng)可以正常運行的第一步。如果你購買了廠家的仿真器當然比較容易燒寫flash了,但是其中的核心技術是無法了解的。這對于需要迅速開發(fā)應用的人來說可以極大地提高開發(fā)速度。下載別人已經(jīng)移植好的LINUX操作系統(tǒng),如UCLINUX、ARM-LINUX、PPC-LINUX等,如果有專門針對你所使用的CPU移植好的LINUX操作系統(tǒng)那是再好不過,下載后再添加自己的特定硬件的驅動程序,進行調(diào)試修改,對于帶MMU的CPU可以使用模塊方式調(diào)試驅動,對于UCLINUX這樣的系統(tǒng)好像只能編譯進內(nèi)核進行調(diào)試。建立根文件系統(tǒng),從下載使用BUSYBOX軟件進行功能裁減,產(chǎn)生一個最基本的根文件系統(tǒng),再根據(jù)自己的應用需要添加其他的程序。默認的啟動腳本一般都不會符合應用的需要,所以就要修改根文件系統(tǒng)中的啟動腳本,它的存放位置位于/etc目錄下,包括:/etc/init.d/rc.S、/etc/profile、/etc/.profile等,自動掛裝文件系統(tǒng)的配置文件/etc/fstab,具體情況會隨系統(tǒng)不同而不同。根文件系統(tǒng)在嵌入式系統(tǒng)中一般設為只讀,需要使用mkcramfs、genromfs等工具產(chǎn)生燒寫映象文件。建立應用程序的flash磁盤分區(qū),一般使用JFFS2或YAFFS文件系統(tǒng),這需要在內(nèi)核中提供這些文件系統(tǒng)的驅動,有的系統(tǒng)使用一個線性flash(NOR型)512K-32M,有的系統(tǒng)使用非線性flash(NAND型)8-512M,有的兩個同時使用,需要根據(jù)應用規(guī)劃flash的分區(qū)方案。開發(fā)應用程序,可以下載到根文件系統(tǒng)中,也可以放入YAFFS、JFFS2文件系統(tǒng)中,有的應用程序不使用根文件系統(tǒng),而是直接將應用程序和內(nèi)核設計在一起,這有點類似于UCOS-II的方式。燒寫內(nèi)核、根文件系統(tǒng)、應用程序。發(fā)布產(chǎn)品。1.4嵌入式Linux開發(fā)環(huán)境的建立嵌入式LINUX開發(fā)環(huán)境有幾個方案:1、基于PC機WINDOWS操作系統(tǒng)下的CYGWIN;2、在WINDOWS下安裝虛擬機后,再在虛擬機中安裝LINXUX操作系統(tǒng);3、直接安裝LINUX操作系統(tǒng)。基于WINDOWS的環(huán)境要么有兼容性問題,要么速度有影響,所以推薦大家使用純LINUX操作系統(tǒng)開發(fā)環(huán)境。我們實際的開發(fā)環(huán)境為REDHAT9,它已經(jīng)支持中文,并且包含了絕大部分的開發(fā)工具,不用擔心裝了LINUX就不能使用WINDOWS的問題。一般的情況都是用戶已經(jīng)有了WINDOWS操作系統(tǒng),再安裝LINUX,LINUX會自動安裝一個叫作GRUB的啟動引導軟件,可以選擇引導多個操作系統(tǒng)。預備知識絕大多數(shù)Linux軟件開發(fā)都是以native方式進行的,即本機(HOST)開發(fā)、調(diào)試,本機運行的方式。這種方式通常不適合于嵌入式系統(tǒng)的軟件開發(fā),因為對于嵌入式系統(tǒng)的開發(fā),沒有足夠的資源在本機(即板子上系統(tǒng))運行開發(fā)工具和調(diào)試工具。通常的嵌入式系統(tǒng)的軟件開發(fā)采用一種交叉編譯調(diào)試的方式。交叉編譯調(diào)試環(huán)境建立在宿主機(即一臺PC機)上,對應的開發(fā)板叫做目標板。運行Linux的PC【宿主機】開發(fā)時使用宿主機上的交叉編譯、匯編及連接工具形成可執(zhí)行的二進制代碼(這種可執(zhí)行代碼并不能在宿主機上執(zhí)行,而只能在目標板上執(zhí)行),然后把可執(zhí)行文件下載到目標機上運行。調(diào)試時的方法很多,可以使用串口,以太網(wǎng)口等,具體使用哪種調(diào)試方法可以根據(jù)目標機處理器提供的支持作出選擇。宿主機和目標板的處理器一般不相同,宿主機為Intel處理器,而目標板如UP-NetARM2410開發(fā)板為三星S3c2410.GNU編譯器提供這樣的功能,在編譯器編譯時可以選擇開發(fā)所需的宿主機和目標機從而建立開發(fā)環(huán)境。所以在進行嵌入式開發(fā)前第一步的工作就是要安裝一臺裝有指定操作系統(tǒng)的PC機作宿主開發(fā)機,對于嵌入式LINUX,宿主機上的操作系統(tǒng)一般要求為REDHATLINUX。嵌入式開發(fā)通常要求宿主機配置有網(wǎng)絡,支持NFS(為交叉開發(fā)時mount所用)。然后要在宿主機上建立交叉編譯調(diào)試的開發(fā)環(huán)境。環(huán)境的建立需要許多的軟件模塊協(xié)同工作,這將是一個比較繁雜的工作,但現(xiàn)在已通過博創(chuàng)嵌入式教學套件中光盤的安裝而自動完成了。對開發(fā)PC機的性能要求由于Redhat9.0安裝后占用空間約為2.4G-5G之間,還要安裝ARM-LINUX硬件要求:CPU:高于奔騰500M,推薦高于賽揚1.7G;內(nèi)存:大于128M,推薦256M;硬盤:大于10G,推薦高于40G。開發(fā)工具軟件的安裝與配置1.REDHATLINUX9.0的安裝在一臺PC上安裝RedHatLINUX9.0,選擇Custom定制安裝,在選擇軟件Package時最好將所有包都安裝,需要空間約2.7G,如果選擇最后一項:everything,即完全安裝,將安裝3張光盤的全部軟件,需要磁盤空間大約5G。因此建議提前為REDHATLINUX的安裝預留大約5-15G的空間,具體視用戶的硬盤空間大小來確定,在安裝完Redhat后還要安裝Linux的編譯器和開發(fā)庫以及ARM-Linux的所有源代碼,這些包安裝后的總共需要空間大約為800M。2.開發(fā)工具軟件的安裝將博創(chuàng)興業(yè)科技有限公司提供的附帶開發(fā)工具光盤插入CDROM,然后執(zhí)行以下命令:mount/dev/cdrom/mnt若系統(tǒng)不識別/dev/cdrom的話,可以用如下命令,假設CDROM為從盤,即為/dev/hdb,則:mount–tiso9660/dev/hdb/mnt安裝腳本程序將自動建立/arm2410s目錄,并將所有開發(fā)軟件包安裝到/arm2410s目錄下,同時自動配置編譯環(huán)境,建立合適的符號連接。注意:安裝完成后看一下主編譯器Armv4l-unknown-linux-gcc是否在/opt/host/armv4l/bin/,如果不是這個路徑,請使用vi修改/root/.bash_profile文件中PATH變量為PATH=$PATH:$HOME/bin:/opt/host/armv4l/bin/,存盤后執(zhí)行:source/root/.bash_profile,則以后armv4l-unknown-linux-gcc會自動搜索到,可以在終端上輸入armv,然后按tab鍵,會自動顯示armv4l-unknown-linux-3.開發(fā)環(huán)境配置配置網(wǎng)絡,包括配置IP地址、NFS服務、防火墻。網(wǎng)絡配置主要是要安裝好以太網(wǎng)卡,對于一般常見的RTL8139網(wǎng)卡,REDHAT9.0可以自動識別并自動安裝好,完全不要用戶參與,因此建議使用該網(wǎng)卡。然后配置宿主機IP為21。如果是在有多臺計算機使用的局域網(wǎng)環(huán)境使用此開發(fā)設備,IP地址可以根據(jù)具體情況設置。如圖1.4.1圖1.4.1雙擊設備eth0的藍色區(qū)域,進入以太網(wǎng)設置界面,如圖1.4.2,1.4.3圖1.4.2圖1.4.3對于REDHAT9.0,它默認的是打開了防火墻,因此對于外來的IP訪問它全部拒絕,這樣其它網(wǎng)絡設備根本無法訪問它,即無法用NFSmount它,許多網(wǎng)絡功能都將無法使用。因此網(wǎng)絡安裝完畢后,應立即關閉防火墻。操作如下:點擊紅帽子開始菜單,選擇安全級別設置,選中無防火墻。如圖1.4.4圖1.4.4在系統(tǒng)設置菜單中選擇服務器設置菜單,再選中服務菜單,將iptables服務的勾去掉,并確保nfs選項選中。配置NFS:點擊主菜單運行系統(tǒng)設置->服務器設置->NFS服務器(英文為:SETUP->SYSTEMSERVICE->NFS),點擊增加出現(xiàn)如下在界面,在目錄(Drictory):中填入需要共享的路徑,在主機(Hosts):中填入允許進行連接的主機IP地址。并選擇允許客戶對共享目錄的操作為只讀(Read-only)或讀寫(Read/write)。如圖1.4.5圖1.4.5NFS圖1.4.圖1.4.6當將遠程根用戶當作本地根用戶時,對于操作比較方便,但是安全性較差。最后退出時則完成NFS配置。配置好后,界面應顯示如圖1.4.圖1.4.7圖1.4.8我們也可以手工編寫/etc/exports文件,其格式如下:共享目錄可以連接的主機(讀寫權限,其他參數(shù))例如:/arm2410s192.168.0.*(rw,sync)表示將本機的/arm2410s目錄共享給ip地址為-54的所有計算機,可以讀取和寫入。配置完成后,可用如下辦法簡單測試一下NFS是否配置好了:在宿主機上自己mount自己,看是否成功就可以判斷NFS是否配好了。例如在宿主機/目錄下執(zhí)行:mount0:/arm2410s/mnt其中0應為主機的IP地址。然后到/mnt/目錄下看是否可以列出/arm2410s目錄下的所有文件和目錄,可以則說明mount成功,NFS配置成功。配置MINICOM:1.在linux操作系統(tǒng)Xwindow界面下建立終端(在桌面上點擊右鍵——>新建終端),在終端的命令行提示符后輸入minicom,圖1.4.9minicom啟動畫面2.minicom啟動后,先按Ctrl+A鍵,再按Z鍵(注意不是連續(xù)按,Ctrl+A松開后才按Z),進入主配置界面(見圖1.4.10)。圖1.4.10主配置界面按“O”進入配置界面,如圖1.4.11配置界面圖1.4.11按上下鍵選擇Serialportsetup,進入端口設置界面,這里有幾個重要選項改為如下值(見圖1.4.12):(在Changewhichsetting后按哪個字母就進入哪項的配置,如按A進行端口號配置。)A————SerialDevice:/dev/ttyS0(端口號使用串口1)E————BPS/par/bits:/1152008N1(波特率)F,E硬件流,軟件流都改為NO,若要使用PC機的串口2來接板子的串口1做監(jiān)控,改為:/dev/ttyS1即可。3.選好后按ESC鍵退出到圖1.4.11所示畫面,選擇Savesetupasdf1保存退出,以后只要啟動minicom就是該配置,無需再做改動。4.配置完成后,用串口線連接好pc機和2410開發(fā)板,啟動2410開發(fā)板,即可在minicom上看到啟動信息,并可以執(zhí)行操作控制。圖1.4.12端口設置界面

Linux開發(fā)軟件的安裝目錄結構表格1.4.1均以/arm2410s表1.4.1/arm2410s目錄名說明busybox-1.00-pre10Busybox-1.00源代碼docarm2410linux使用說明書QtQt應用程序和庫的源代碼insight-6.0Linux下源代碼查看器root2410平臺根文件系統(tǒng)kernel-2410s2410平臺linux內(nèi)核源代碼demos所有實驗演示程序imgvivi系統(tǒng)引導程序zImageARMLINUX-2.4內(nèi)核壓縮映象文件root.cramfs根文件系統(tǒng)映象文件yaffs.tar.bz2demos演示程序的壓縮文件exp實驗例程源碼shmount-dos.shlinux下掛裝windows的分區(qū)示例腳本 linux下掛裝windows的分區(qū)示例腳本。mnt_udisk.shMOUNTU盤mkroot.sh制作根文件系統(tǒng)的腳本編譯器安裝路徑說明如表1.4.2表1.4.2編譯器安裝目錄說明arm-elf-gcc-2.95.3/opt/host/armv4l應用開發(fā)庫和頭文件Armv4l-unknown-linux-gcc/opt/host/armv4l/bin主編譯器上述諸多程序的源代碼都在光盤中提供.在安裝完成LINUX后,就是對LINUX的網(wǎng)絡環(huán)境的配置,最主要是配置NFS服務器。第二章基礎實驗2.1熟悉Linux開發(fā)環(huán)境一、實驗目的熟悉Linux開發(fā)環(huán)境,學會基于S3C2410的Linux開發(fā)環(huán)境的配置和使用。使用Linux的armv4l-unknown-linux-gcc編譯,使用基于NFS方式的下載調(diào)試,了解嵌入式開發(fā)的基本過程。二、實驗內(nèi)容本次實驗使用RedhatLinux9.0操作系統(tǒng)環(huán)境,安裝ARM-Linux的開發(fā)庫及編譯器。創(chuàng)建一個新目錄,并在其中編寫hello.c和Makefile文件。學習在Linux下的編程和編譯過程,以及ARM開發(fā)板的使用和開發(fā)環(huán)境的設置。下載已經(jīng)編譯好的文件到目標開發(fā)板上運行。三、預備知識C語言的基礎知識、程序調(diào)試的基礎知識和方法,Linux的基本操作。四、實驗設備及工具(包括軟件調(diào)試工具)硬件:UP-NETARM2410嵌入式實驗平臺、PC機Pentium500以上,硬盤10G以上。軟件:PC機操作系統(tǒng)REDHATLINUX9.0+MINICOM+ARM-LINUX開發(fā)環(huán)境五、實驗步驟1、建立工作目錄[root@zxtsmile]#mkdirhello[root@zxtsmile]#cdhello2、編寫程序源代碼在Linux下的文本編輯器有許多,常用的是vim和Xwindow界面下的gedit等,我們在開發(fā)過程中推薦使用vim,用戶需要學習vim的操作方法,請參考相關書籍中的關于vim的操作指南。Kdevelope、anjuta軟件的界面與vc6.0類似,使用它們對于熟悉windows環(huán)境下開發(fā)的用戶更容易上手。實際的hello.c源代碼較簡單,如下:#include<stdio.h>main(){ printf(“helloworld\n”);}我們可以是用下面的命令來編寫hello.c的源代碼,進入hello目錄使用vi命令來編輯代碼:[root@zxthello]#vihello.c按“i”或者“a”進入編輯模式,將上面的代碼錄入進去,完成后按Esc鍵進入命令狀態(tài),再用命令“:wq”保存并退出。這樣我們便在當前目錄下建立了一個名為hello.c的文件。3、編寫Makefile要使上面的hello.c程序能夠運行,我們必須要編寫一個Makefile文件,Makefile文件定義了一系列的規(guī)則,它指明了哪些文件需要編譯,哪些文件需要先編譯,哪些文件需要重新編譯等等更為復雜的命令。使用它帶來的好處就是自動編譯,你只需要敲一個“make”命令整個工程就可以實現(xiàn)自動編譯,當然我們本次實驗只有一個文件,它還不能體現(xiàn)出使用Makefile的優(yōu)越性,但當工程比較大文件比較多時,不使用Makefile幾乎是不可能的。下面我們介紹本次實驗用到的Makefile文件。CC=armv4l-unknown-linux-gccEXEC=helloOBJS=hello.oCFLAGS+=LDFLAGS+=–staticall:$(EXEC)$(EXEC):$(OBJS) $(CC)$(LDFLAGS)-o$@$(OBJS)clean: -rm-f$(EXEC)*.elf*.gdb*.o下面我們來簡單介紹這個Makefile文件的幾個主要部分:CC指明編譯器EXEC表示編譯后生成的執(zhí)行文件名稱OBJS目標文件列表CFLAGS編譯參數(shù)LDFLAGS連接參數(shù)all:編譯主入口clean:清除編譯結果注意:“$(CC)$(LDFLAGS)-o$@$(OBJS)”和“-rm-f$(EXEC)*.elf*.gdb*.o”前空白由一個Tab制表符生成,不能單純由空格來代替。與上面編寫hello.c的過程類似,用vi來創(chuàng)建一個Makefile文件并將代碼錄入其中[root@zxthello]#viMakefile4、編譯應用程序在上面的步驟完成后,我們就可以在hello目錄下運行“make”來編譯我們的程序了。如果進行了修改,重新編譯則運行:[root@zxthello]#makeclean[root@zxthello]#make注意:編譯、修改程序都是在宿主機(本地PC機)上進行,不能在MINICOM下進行。5、下載調(diào)試在宿主PC計算機上啟動NFS服務,并設置好共享的目錄,具體配置請參照前面第一章第四節(jié)中關于嵌入式Linux環(huán)境開發(fā)環(huán)境的建立。在建立好NFS共享目錄以后,我們就可以進入MINICOM中建立開發(fā)板與宿主PC機之間的通訊了。[root@zxthello]#minicom[/mnt/yaffs]mount-tnfs-onolock6:/arm2410s/host注意:IP地址需要根據(jù)宿主PC機的實際情況修改成功掛接宿主機的arm2410s目錄后,在開發(fā)板上進入/host目錄便相應進入宿主機的/arm2410s目錄,我們已經(jīng)給出了編輯好的hello.c和Makefile文件,它們在/arm2410s/exp/basic/01_hello目錄下。用戶可以直接在宿主PC上編譯生成可執(zhí)行文件,并通過上面的命令掛載到開發(fā)板上,運行程序察看結果。如果不想使用我們提供的源碼的話,可以再建立一個NFS共享文件夾。如/root/share,我們把我們自己編譯生成的可執(zhí)行文件復制到該文件夾下,并通過MINICOM掛載到開發(fā)板上。[root@zxthello]#cphello/root/share[root@zxthello]#minicom[/mnt/yaffs]mount-tnfs-onolock6:/root/share/host再進入/host目錄運行剛剛編譯好的hello程序,查看運行結果。[/mnt/yaffs]cd/host[/host]./hellohelloworld注意:開發(fā)板掛接宿主計算機目錄只需要掛接一次便可,只要開發(fā)板沒有重起,就可以一直保持連接。這樣可以反復修改、編譯、調(diào)試,不需要下載到開發(fā)板。六、思考題1.Makefile是如何工作的?其中的宏定義分別是什么意思?

2.2多線程應用程序設計一、實驗目的了解多線程程序設計的基本原理。學習pthread庫函數(shù)的使用。二、實驗內(nèi)容讀懂pthread.c的源代碼,熟悉幾個重要的PTHREAD庫函數(shù)的使用。掌握共享鎖和信號量的使用方法。進入/arm2410s/exp/basic/02_pthread目錄,運行make產(chǎn)生pthread程序,使用NFS方式連接開發(fā)主機進行運行實驗。三、預備知識有C語言基礎掌握在Linux下常用編輯器的使用掌握Makefile的編寫和使用掌握Linux下的程序編譯與交叉編譯過程四、實驗設備及工具硬件:UP-NETARM2410嵌入式實驗平臺,PC機Pentium500以上,硬盤40G以上,內(nèi)存大于128M。軟件:PC機操作系統(tǒng)REDHATLINUX9.0+MINICOM+ARM-LINUX開發(fā)環(huán)境五、實驗原理及代碼分析1.多線程程序的優(yōu)缺點多線程程序作為一種多任務、并發(fā)的工作方式,有以下的優(yōu)點:1)提高應用程序響應。這對圖形界面的程序尤其有意義,當一個操作耗時很長時,整個系統(tǒng)都會等待這個操作,此時程序不會響應鍵盤、鼠標、菜單的操作,而使用多線程技術,將耗時長的操作(timeconsuming)置于一個新的線程,可以避免這種尷尬的情況。2)使多CPU系統(tǒng)更加有效。操作系統(tǒng)會保證當線程數(shù)不大于CPU數(shù)目時,不同的線程運行于不同的CPU上。3)改善程序結構。一個既長又復雜的進程可以考慮分為多個線程,成為幾個獨立或半獨立的運行部分,這樣的程序會利于理解和修改。LIBC中的pthread庫提供了大量的API函數(shù),為用戶編寫應用程序提供支持。2.實驗源代碼與結構流程圖本實驗為著名的生產(chǎn)者-消費者問題模型的實現(xiàn),主程序中分別啟動生產(chǎn)者線程和消費者線程。生產(chǎn)者線程不斷順序地將0到1000的數(shù)字寫入共享的循環(huán)緩沖區(qū),同時消費者線程不斷地從共享的循環(huán)緩沖區(qū)讀取數(shù)據(jù)。流程圖如圖2.2.1所示:圖2.2.1生產(chǎn)者-消費者實驗源代碼結構流程圖本實驗具體代碼如下:/************************************************* Theclassicproducer-consumerexample.* Illustratesmutexesandconditions.*byZoujianguo<ah_zou@>*2003-12-22*************************************************/#include<stdio.h>#include<stdlib.h>#include<time.h>#include"pthread.h"#defineBUFFER_SIZE16/*設置一個整數(shù)的圓形緩沖區(qū)*/structprodcons{intbuffer[BUFFER_SIZE];/*緩沖區(qū)數(shù)組*/pthread_mutex_tlock;/*互斥鎖*/intreadpos,writepos;/*讀寫的位置*/pthread_cond_tnotempty;/*緩沖區(qū)非空信號*/pthread_cond_tnotfull;/*緩沖區(qū)非滿信號*/};/**//*初始化緩沖區(qū)*/voidinit(structprodcons*b){pthread_mutex_init(&b->lock,NULL);pthread_cond_init(&b->notempty,NULL);pthread_cond_init(&b->notfull,NULL);b->readpos=0;b->writepos=0;}/**//*向緩沖區(qū)中寫入一個整數(shù)*/voidput(structprodcons*b,intdata){ pthread_mutex_lock(&b->lock); /*等待緩沖區(qū)非滿*/ while((b->writepos+1)%BUFFER_SIZE==b->readpos){ printf("waitfornotfull\n"); pthread_cond_wait(&b->notfull,&b->lock); }/*寫數(shù)據(jù)并且指針前移*/ b->buffer[b->writepos]=data; b->writepos++; if(b->writepos>=BUFFER_SIZE)b->writepos=0;/*設置緩沖區(qū)非空信號*/ pthread_cond_signal(&b->notempty); pthread_mutex_unlock(&b->lock);}/**//*從緩沖區(qū)中讀出一個整數(shù)*/intget(structprodcons*b){ intdata; pthread_mutex_lock(&b->lock); /*等待緩沖區(qū)非空*/ while(b->writepos==b->readpos){ printf("waitfornotempty\n"); pthread_cond_wait(&b->notempty,&b->lock); } /*讀數(shù)據(jù)并且指針前移*/ data=b->buffer[b->readpos]; b->readpos++; if(b->readpos>=BUFFER_SIZE)b->readpos=0; /*設置緩沖區(qū)非滿信號*/ pthread_cond_signal(&b->notfull); pthread_mutex_unlock(&b->lock); returndata;}/**/#defineOVER(-1)structprodconsbuffer;/**/void*producer(void*data){ intn; for(n=0;n<1000;n++){ printf("put-->%d\n",n); put(&buffer,n); }put(&buffer,OVER);printf("producerstopped!\n");returnNULL;}/**/void*consumer(void*data){intd;while(1){d=get(&buffer);if(d==OVER)break;printf("%d-->get\n",d);}printf("consumerstopped!\n");returnNULL;}/**/intmain(void){ pthread_tth_a,th_b; void*retval; init(&buffer); pthread_create(&th_a,NULL,producer,0); pthread_create(&th_b,NULL,consumer,0);/*等待生產(chǎn)者和消費者結束*/ pthread_join(th_a,&retval); pthread_join(th_b,&retval); return0;}3.主要函數(shù)分析:下面我們來看一下,生產(chǎn)者寫入緩沖區(qū)和消費者從緩沖區(qū)讀數(shù)的具體流程,生產(chǎn)者首先要獲得互斥鎖,并且判斷寫指針+1后是否等于讀指針,如果相等則進入等待狀態(tài),等候條件變量notfull;如果不等則向緩沖區(qū)中寫一個整數(shù),并且設置條件變量為notempty,最后釋放互斥鎖。消費者線程與生產(chǎn)者線程類似,這里就不再過多介紹了。流程圖如下:圖2.2.2生產(chǎn)消費流程圖生產(chǎn)者寫入共享的循環(huán)緩沖區(qū)函數(shù)PUTvoidput(structprodcons*b,intdata){ pthread_mutex_lock(&b->lock);//獲取互斥鎖 while((b->writepos+1)%BUFFER_SIZE==b->readpos){//如果讀寫位置相同 pthread_cond_wait(&b->notfull,&b->lock);//等待狀態(tài)變量b->notfull,不滿則跳出阻塞 } b->buffer[b->writepos]=data;//寫入數(shù)據(jù) b->writepos++; if(b->writepos>=BUFFER_SIZE)b->writepos=0; pthread_cond_signal(&b->notempty);//設置狀態(tài)變量 pthread_mutex_unlock(&b->lock);//釋放互斥鎖}消費者讀取共享的循環(huán)緩沖區(qū)函數(shù)GETintget(structprodcons*b){ intdata; pthread_mutex_lock(&b->lock);//獲取互斥鎖 while(b->writepos==b->readpos){//如果讀寫位置相同 pthread_cond_wait(&b->notempty,&b->lock);//等待狀態(tài)變量b->notempty,不空則跳出阻塞。否則無數(shù)據(jù)可讀。 } data=b->buffer[b->readpos];//讀取數(shù)據(jù) b->readpos++; if(b->readpos>=BUFFER_SIZE)b->readpos=0; pthread_cond_signal(&b->notfull);//設置狀態(tài)變量 pthread_mutex_unlock(&b->lock);//釋放互斥鎖 returndata;}4.主要的多線程API在本程序的代碼中大量的使用了線程函數(shù),如pthread_cond_signal、pthread_mutex_init、pthread_mutex_lock等等,這些函數(shù)的作用是什么,在哪里定義的,我們將在下面的內(nèi)容中為大家做一個簡單的介紹,并且為其中比較重要的函數(shù)做一些詳細的說明。線程創(chuàng)建函數(shù):intpthread_create(pthread_t*thread_id,__constpthread_attr_t*__attr, void*(*__start_routine)(void*),void*__restrict__arg)獲得父進程ID:pthread_tpthread_self(void)測試兩個線程號是否相同:intpthread_equal(pthread_t__thread1,pthread_t__thread2)線程退出:voidpthread_exit(void*__retval)等待指定的線程結束:intpthread_join(pthread_t__th,void**__thread_return)互斥量初始化:pthread_mutex_init(pthread_mutex_t*,__constpthread_mutexattr_t*)銷毀互斥量:intpthread_mutex_destroy(pthread_mutex_t*__mutex)再試一次獲得對互斥量的鎖定(非阻塞):intpthread_mutex_trylock(pthread_mutex_t*__mutex)鎖定互斥量(阻塞):intpthread_mutex_lock(pthread_mutex_t*__mutex)解鎖互斥量:intpthread_mutex_unlock(pthread_mutex_t*__mutex)條件變量初始化:intpthread_cond_init(pthread_cond_t*__restrict__cond,__constpthread_condattr_t*__restrict__cond_attr)銷毀條件變量COND:intpthread_cond_destroy(pthread_cond_t*__cond)喚醒線程等待條件變量:intpthread_cond_signal(pthread_cond_t*__cond)等待條件變量(阻塞):intpthread_cond_wait(pthread_cond_t*__restrict__cond,pthread_mutex_t*__restrict__mutex)在指定的時間到達前等待條件變量:intpthread_cond_timedwait(pthread_cond_t*__restrict__cond,pthread_mutex_t*__restrict__mutex,__conststructtimespec*__restrict__abstime)PTHREAD庫中還有大量的API函數(shù),用戶可以參考其他相關書籍。下面我們對幾個比較重要的函數(shù)做一下詳細的說明:pthread_create線程創(chuàng)建函數(shù)intpthread_create(pthread_t*thread_id,__constpthread_attr_t*__attr, void*(*__start_routine)(void*),void*__restrict__arg)線程創(chuàng)建函數(shù)第一個參數(shù)為指向線程標識符的指針,第二個參數(shù)用來設置線程屬性,第三個參數(shù)是線程運行函數(shù)的起始地址,最后一個參數(shù)是運行函數(shù)的參數(shù)。這里,我們的函數(shù)thread不需要參數(shù),所以最后一個參數(shù)設為空指針。第二個參數(shù)我們也設為空指針,這樣將生成默認屬性的線程。當創(chuàng)建線程成功時,函數(shù)返回0,若不為0則說明創(chuàng)建線程失敗,常見的錯誤返回代碼為EAGAIN和EINVAL。前者表示系統(tǒng)限制創(chuàng)建新的線程,例如線程數(shù)目過多了;后者表示第二個參數(shù)代表的線程屬性值非法。創(chuàng)建線程成功后,新創(chuàng)建的線程則運行參數(shù)三和參數(shù)四確定的函數(shù),原來的線程則繼續(xù)運行下一行代碼。pthread_join函數(shù)用來等待一個線程的結束。函數(shù)原型為:intpthread_join(pthread_t__th,void**__thread_return)第一個參數(shù)為被等待的線程標識符,第二個參數(shù)為一個用戶定義的指針,它可以用來存儲被等待線程的返回值。這個函數(shù)是一個線程阻塞的函數(shù),調(diào)用它的函數(shù)將一直等待到被等待的線程結束為止,當函數(shù)返回時,被等待線程的資源被收回。pthread_exit函數(shù)一個線程的結束有兩種途徑,一種是象我們上面的例子一樣,函數(shù)結束了,調(diào)用它的線程也就結束了;另一種方式是通過函數(shù)pthread_exit來實現(xiàn)。它的函數(shù)原型為:voidpthread_exit(void*__retval)唯一的參數(shù)是函數(shù)的返回代碼,只要pthread_join中的第二個參數(shù)thread_return不是NULL,這個值將被傳遞給thread_return。最后要說明的是,一個線程不能被多個線程等待,否則第一個接收到信號的線程成功返回,其余調(diào)用pthread_join的線程則返回錯誤代碼ESRCH。下面我們來介紹有關條件變量的內(nèi)容。使用互斥鎖來可實現(xiàn)線程間數(shù)據(jù)的共享和通信,互斥鎖一個明顯的缺點是它只有兩種狀態(tài):鎖定和非鎖定。而條件變量通過允許線程阻塞和等待另一個線程發(fā)送信號的方法彌補了互斥鎖的不足,它常和互斥鎖一起使用。使用時,條件變量被用來阻塞一個線程,當條件不滿足時,線程往往解開相應的互斥鎖并等待條件發(fā)生變化。一旦其它的某個線程改變了條件變量,它將通知相應的條件變量喚醒一個或多個正被此條件變量阻塞的線程。這些線程將重新鎖定互斥鎖并重新測試條件是否滿足。一般說來,條件變量被用來進行線線程間的同步。pthread_cond_init函數(shù)條件變量的結構為pthread_cond_t,函數(shù)pthread_cond_init()被用來初始化一個條件變量。它的原型為:intpthread_cond_init(pthread_cond_t*cond,__constpthread_condattr_t*cond_attr)其中cond是一個指向結構pthread_cond_t的指針,cond_attr是一個指向結構pthread_condattr_t的指針。結構pthread_condattr_t是條件變量的屬性結構,和互斥鎖一樣我們可以用它來設置條件變量是進程內(nèi)可用還是進程間可用,默認值是PTHREAD_PROCESS_PRIVATE,即此條件變量被同一進程內(nèi)的各個線程使用。注意初始化條件變量只有未被使用時才能重新初始化或被釋放。釋放一個條件變量的函數(shù)為pthread_cond_destroy(pthread_cond_tcond)。pthread_cond_wait函數(shù)使線程阻塞在一個條件變量上。它的函數(shù)原型為:externintpthread_cond_wait(pthread_cond_t*__restrict__cond,pthread_mutex_t*__restrict__mutex)線程解開mutex指向的鎖并被條件變量cond阻塞。線程可以被函數(shù)pthread_cond_signal和函數(shù)pthread_cond_broadcast喚醒,但是要注意的是,條件變量只是起阻塞和喚醒線程的作用,具體的判斷條件還需用戶給出,例如一個變量是否為0等等,這一點我們從后面的例子中可以看到。線程被喚醒后,它將重新檢查判斷條件是否滿足,如果還不滿足,一般說來線程應該仍阻塞在這里,被等待被下一次喚醒。這個過程一般用while語句實現(xiàn)。pthread_cond_timedwait函數(shù)另一個用來阻塞線程的函數(shù)是pthread_cond_timedwait(),它的原型為:externintpthread_cond_timedwait__P((pthread_cond_t*__cond,pthread_mutex_t*__mutex,__conststructtimespec*__abstime))它比函數(shù)pthread_cond_wait()多了一個時間參數(shù),經(jīng)歷abstime段時間后,即使條件變量不滿足,阻塞也被解除。pthread_cond_signal函數(shù)它的函數(shù)原型為:externintpthread_cond_signal(pthread_cond_t*__cond)它用來釋放被阻塞在條件變量cond上的一個線程。多個線程阻塞在此條件變量上時,哪一個線程被喚醒是由線程的調(diào)度策略所決定的。要注意的是,必須用保護條件變量的互斥鎖來保護這個函數(shù),否則條件滿足信號又可能在測試條件和調(diào)用pthread_cond_wait函數(shù)之間被發(fā)出,從而造成無限制的等待。六、實驗步驟1、閱讀源代及編譯應用程序進入exp/basic/02_pthread目錄,使用vi編輯器或其他編輯器閱讀理解源代碼。運行make產(chǎn)生pthread可執(zhí)行文件。2、下載和調(diào)試切換到minicom終端窗口,使用NFSmount開發(fā)主機的/arm2410s到/host目錄。進入/host/exp/basic/pthread目錄,運行pthread,觀察運行結果的正確性。運行程序最后一部分結果如下:waitfornotemptyput-->994put-->995put-->996put-->997put-->998put-->999producerstopped!993-->get994-->get995-->get996-->get997-->get998-->get999-->getconsumerstopped![/host/exp/basic/02_pthread]七、思考題1.加入一個新的線程用于處理鍵盤的輸入,并在按鍵為ESC時終止所有線程。2.線程的優(yōu)先級的控制。

2.3串行端口程序設計一、實驗目的了解在linux環(huán)境下串行程序設計的基本方法。掌握終端的主要屬性及設置方法,熟悉終端I/O函數(shù)的使用。學習使用多線程來完成串口的收發(fā)處理。二、實驗內(nèi)容讀懂程序源代碼,學習終端I/O函數(shù)的使用方法,學習將多線程編程應用到串口的接收和發(fā)送程序設計中。三、預備知識有C語言基礎。掌握在Linux下常用編輯器的使用。掌握Makefile的編寫和使用。掌握Linux下的程序編譯與交叉編譯過程四、實驗設備及工具硬件:UP-NETARM2410嵌入式實驗平臺、PC機Pentium500以上,硬盤10G以上。軟件:PC機操作系統(tǒng)REDHATLINUX9.0+MINICOM+ARM-LINUX開發(fā)環(huán)境五、實驗原理異步串行I/O方式是將傳輸數(shù)據(jù)的每個字符一位接一位(例如先低位、后高位)地傳送。數(shù)據(jù)的各不同位可以分時使用同一傳輸通道,因此串行I/O可以減少信號連線,最少用一對線即可進行。接收方對于同一根線上一連串的數(shù)字信號,首先要分割成位,再按位組成字符。為了恢復發(fā)送的信息,雙方必須協(xié)調(diào)工作。在微型計算機中大量使用異步串行I/O方式,雙方使用各自的時鐘信號,而且允許時鐘頻率有一定誤差,因此實現(xiàn)較容易。但是由于每個字符都要獨立確定起始和結束(即每個字符都要重新同步),字符和字符間還可能有長度不定的空閑時間,因此效率較低。圖2.3.1串行通信字符格式圖2.3.1給出異步串行通信中一個字符的傳送格式。開始前,線路處于空閑狀態(tài),送出連續(xù)“1”。傳送開始時首先發(fā)一個“0”作為起始位,然后出現(xiàn)在通信線上的是字符的二進制編碼數(shù)據(jù)。每個字符的數(shù)據(jù)位長可以約定為5位、6位、7位或8位,一般采用ASCII編碼。后面是奇偶校驗位,根據(jù)約定,用奇偶校驗位將所傳字符中為“1”的位數(shù)湊成奇數(shù)個或偶數(shù)個。也可以約定不要奇偶校驗,這樣就取消奇偶校驗位。最后是表示停止位的“1”信號,這個停止位可以約定持續(xù)1位、1.5位或2位的時間寬度。至此一個字符傳送完畢,線路又進入空閑,持續(xù)為“1”。經(jīng)過一段隨機的時間后,下一個字符開始傳送才又發(fā)出起始位。每一個數(shù)據(jù)位的寬度等于傳送波特率的倒數(shù)。微機異步串行通信中,常用的波特率為50,95,110,150,300,600,1200,2400,4800,9600等。接收方按約定的格式接收數(shù)據(jù),并進行檢查,可以查出以下三種錯誤:奇偶錯:在約定奇偶檢查的情況下,接收到的字符奇偶狀態(tài)和約定不符。幀格式錯:一個字符從起始位到停止位的總位數(shù)不對。溢出錯:若先接收的字符尚未被微機讀取,后面的字符又傳送過來,則產(chǎn)生溢出錯。每一種錯誤都會給出相應的出錯信息,提示用戶處理。一般串口調(diào)試都使用空的MODEM連接電纜,其連接方式如下:圖2.3.2實用RS-232C通訊連線六、程序分析Linux操作系統(tǒng)從一開始就對串行口提供了很好的支持,為進行串行通訊提供了大量的函數(shù),我們的實驗主要是為掌握在Linux中進行串行通訊編程的基本方法。本實驗的程序流程圖如下:圖2.3.3串口通訊實驗流程圖本實驗的代碼如下:#include<termios.h>#include<stdio.h>#include<unistd.h>#include<fcntl.h>#include<sys/signal.h>#include<pthread.h>#defineBAUDRATEB115200#defineCOM1"/dev/ttyS0"#defineCOM2"/dev/ttyS1"#defineENDMINITERM27/*ESCtoquitminiterm*/#defineFALSE0#defineTRUE1volatileintSTOP=FALSE;volatileintfd;voidchild_handler(ints){printf("stop!!!\n");STOP=TRUE;}/**/void*keyboard(void*data){intc; for(;;){ c=getchar(); if(c==ENDMINITERM){ STOP=TRUE; break; } }returnNULL;}/**//*modeminputhandler*/void*receive(void*data){ intc; printf("readmodem\n"); while(STOP==FALSE) { read(fd,&c,1);/*comport*/ write(1,&c,1);/*stdout*/ } printf("exitfromreadingmodem\n"); returnNULL;}/**/void*send(void*data){ intc='0'; printf("senddata\n"); while(STOP==FALSE)/*modeminputhandler*/ { c++; c%=255; write(fd,&c,1);/*stdout*/ usleep(100000); } returnNULL;}/**/intmain(intargc,char**argv){ structtermiosoldtio,newtio,oldstdtio,newstdtio; structsigactionsa; intok; pthread_tth_a,th_b,th_c; void*retval; if(argc>1) fd=open(COM2,O_RDWR); else fd=open(COM1,O_RDWR);//|O_NOCTTY|O_NONBLOCK); if(fd<0){ error(COM1); exit(-1); } tcgetattr(0,&oldstdtio); tcgetattr(fd,&oldtio);/*savecurrentmodemsettings*/ tcgetattr(fd,&newstdtio);/*getworkingstdtio*/ newtio.c_cflag=BAUDRATE|CRTSCTS|CS8|CLOCAL|CREAD;/*ctrolflag*/ newtio.c_iflag=IGNPAR;/*inputflag*/ newtio.c_oflag=0; /*outputflag*/ newtio.c_lflag=0; newtio.c_cc[VMIN]=1; newtio.c_cc[VTIME]=0;/*nowcleanthemodemlineandactivatethesettingsformodem*/ tcflush(fd,TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio);/*setattrib*/ sa.sa_handler=child_handler; sa.sa_flags=0; sigaction(SIGCHLD,&sa,NULL);/*handledyingchild*/ pthread_create(&th_a,NULL,keyboard,0); pthread_create(&th_b,NULL,receive,0); pthread_create(&th_c,NULL,send,0); pthread_join(th_a,&retval); pthread_join(th_b,&retval); pthread_join(th_c,&retval); tcsetattr(fd,TCSANOW,&oldtio);/*restoreoldmodemsetings*/ tcsetattr(0,TCSANOW,&oldstdtio);/*restoreoldttysetings*/ close(fd); exit(0);}下面我們對這個程序的主要部分做一下簡單的分析頭文件#include<stdio.h>/*標準輸入輸出定義*/#include<stdlib.h>/*標準函數(shù)庫定義*/#include<unistd.h>/*linux標準函數(shù)定義*/#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>/*文件控制定義*/#include<termios.h>/*PPSIX終端控制定義*/#include<errno.h>/*錯誤號定義*/#include <pthread.h> /*線程庫定義*/打開串口在Linux下串口文件位于/dev下,一般在老版本的內(nèi)核中串口一為/dev/ttyS0,串口二為/dev/ttyS1,在我們的開發(fā)板中串口設備位于/dev/tts/下,因為開發(fā)板中沒有ttyS0這個設備,所以我們要建立一個連接,方法如下:[/mnt/yaffs]cd/dev[/dev]ln–sf/dev/tts/0ttyS0打開串口是通過標準的文件打開函數(shù)來實現(xiàn)的intfd;fd=open("/dev/ttyS0",O_RDWR);/*以讀寫方式打開串口*/if(-1==fd){/*不能打開串口一*/ perror("提示錯誤!");}串口設置最基本的設置串口包括波特率設置,效驗位和停止位設置。串口的設置主要是設置structtermios結構體的各成員值,關于該結構體的定義可以查看/arm2410s/kernel-2410s/include/asm/termios.h文件。structtermio{ unsignedshortc_iflag; /*輸入模式標志*/ unsignedshortc_oflag; /*輸出模式標志*/ unsignedshortc_cflag; /*控制模式標志*/ unsignedshortc_lflag; /*localmodeflags*/ unsignedcharc_line; /*linediscipline*/ unsignedcharc_cc[NCC];/*controlcharacters*/};設置這個結構體很復雜,可以參考man手冊或者由趙克佳、沈志宇編寫的《UNIX程序編寫教程》,我這里就只

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論