華恒COLDFIRE系列嵌入式LINUX開發(fā)套件常見問題解答
華恒公司
|
|
華恒COLDFIRE系列嵌入式LINUX開發(fā)套件常見問題解答<BR> ---基于公用核心板HHCF5272-K1(華恒公司版權(quán)所有)</P><P> --------------------------------------------------------------------------------<BR> <BR> 1. 關(guān)于宿主機LINUX的安裝 </P><P> 建議使用REDHAT系列:建議選擇完全安裝,即選擇Custom,然后在Package中選擇everything。</P><P> <BR> 【以下配置詳見最新PDF手冊下載(例如:HHCO5272-R1的手冊)】<BR> 宿主機的網(wǎng)絡(luò)配置</P><P> 主要是要安裝好以太網(wǎng)卡,對于一般常見的RTL8139網(wǎng)卡,REDHAT7.2可以自動識別并自動安裝好,完全不要用戶參與,因此建議使用該網(wǎng)卡。然后配置宿主機IP:<BR> ifconfig eth0 192.168.2.32<BR> 【注意】<BR> 對于REDHAT7.2,它默認的是打開了防火墻,因此對于外來的IP訪問它全部拒絕,這樣其它網(wǎng)絡(luò)設(shè)備根本無法訪問它,即無法用NFS mount它,無法通過TFTP從它下載,無法telnet,ftp它等。因此網(wǎng)絡(luò)安裝完畢后,應(yīng)立即關(guān)閉防火墻。操作如下:<BR> 運行setup,選擇Firewall configuration,選中No firewall。然后到上一層菜單選擇System services,去掉ipchains和iptables兩項服務(wù)。最后退出setup。</P><P> 其實,在安裝REDHAT7.2/3時,就要求選擇Custom定制安裝,其中由一項就是要求選擇No Firewall,這樣的話,啟動后,就不需要執(zhí)行setup來設(shè)置防火墻了。還有,REDHAT在這里有個BUG,即無論上次你進入Firewall configuration選擇什么,每次再次進入時它都顯示High,這是REDHAT顯示的BUG,其實防火墻已經(jīng)關(guān)閉了。</P><P> 配置NFS</P><P> 運行l(wèi)inuxconf,在config選項下選Server tasks,選中Exported File systems(NFS),然后選擇Add Directory,加入根目錄/,然后Accept。系統(tǒng)就會輸出根目錄允許NFS mount。<BR> 下一步再選擇Control項下面Control panel下的Control Service activity,然后選擇nfs enabled,然后start。配置好后的界面顯示其中nfs必須為: Automatic Running。<BR> 【注意】<BR> 這里建議把ipchains和iptables都取消其自動啟動的狀態(tài)。<BR> 最后,在Control項下面Control panel下選擇Activate configuration,則彈出界面,提示系統(tǒng)配置的改動,選擇"Do it",最后退出時則完成NFS配置。<BR> 配置完成后,可用如下辦法簡單測試一下NFS是否配置好了:<BR> 在宿主機上自己mount自己,看是否成功就可以判斷NFS是否配好了。例如在宿主機/目錄下執(zhí)行:<BR> mount 192.168.2.32:/ /mnt<BR> 然后到/mnt/目錄下看是否可以列出/目錄下的所有文件和目錄,可以則說明mount成功,NFS配置成功。 <BR> 配置TFTP服務(wù)器</P><P> 參見下面第二點介紹。<BR> 【注意】</P><P> 安裝完華恒uClinux軟件光盤后,不要make xconfig,直接make即可。加入驅(qū)動等修改內(nèi)核的操作都不必make xconfig,除非要更改處理器平臺,例如移植到MCF5407等才需要make xconfig。其實這個操作不過就是修改linux/.config和linux/include/linux/autoconfig.h中的宏設(shè)置。完全可以由手工完成。</P><P> 2. 關(guān)于gdbtftpflash燒寫<BR> 【注意】</P><P> 燒寫必須接百兆以太網(wǎng)接口,對于多以太網(wǎng)板的10M口是不能用來燒寫的。</P><P> <BR> 在一個LINUX TTY終端執(zhí)行<BR> ./flash<BR> 然后立刻切換到另一個TTY終端啟動的minicom下去查看信息<BR> Reading image.bin from 192.168.2.46 to 0x00100000<BR> TFTP download successful </P><P> 或者信息如下:<BR> ICMP: Port unreachable<BR> ICMP: Port unreachable<BR> ICMP: Port unreachable<BR> TFTP could not make connection to server<BR> Errors in TFTP download</P><P> Read 1004740 bytes (1963 blocks)【這才是關(guān)鍵所在,前面的信息都無用,只要這里讀到的字節(jié)數(shù)和宿主機上/tftpboot/目錄下的image.bin文件的大小一致就表明TFTP下載成功了!】<BR> >>>>>>>>>> Init mflash<BR> >>>>>>>>>> Init mflash Successfully<BR> ********** File size : 0xF54C4 bytes<BR> ********** Address base : 0x0<BR> ********** Manufacturer ID 1<BR> ********** Device ID 2249<BR> ********** Sector 0 [FFC00000] (0-unprotect, 1 protect):0<BR> ********** Sector 1 [FFC04000] (0-unprotect, 1 protect):0<BR> ********** Sector 2 [FFC06000] (0-unprotect, 1 protect):0<BR> ********** Sector 3 [FFC08000] (0-unprotect, 1 protect):0<BR> ********** Sector 4 [FFC10000] (0-unprotect, 1 protect):0<BR> ********** Sector 5 [FFC20000] (0-unprotect, 1 protect):0<BR> ********** Sector 6 [FFC30000] (0-unprotect, 1 protect):0<BR> ********** Sector 7 [FFC40000] (0-unprotect, 1 protect):0<BR> ********** Sector 8 [FFC50000] (0-unprotect, 1 protect):0<BR> ********** Sector 9 [FFC60000] (0-unprotect, 1 protect):0<BR> ********** Sector 10 [FFC70000] (0-unprotect, 1 protect):0<BR> ********** Sector 11 [FFC80000] (0-unprotect, 1 protect):0<BR> ********** Sector 12 [FFC90000] (0-unprotect, 1 protect):0<BR> ********** Sector 13 [FFCA0000] (0-unprotect, 1 protect):0<BR> ********** Sector 14 [FFCB0000] (0-unprotect, 1 protect):0<BR> ********** Sector 15 [FFCC0000] (0-unprotect, 1 protect):0<BR> ********** Sector 16 [FFCD0000] (0-unprotect, 1 protect):0<BR> ********** Sector 17 [FFCE0000] (0-unprotect, 1 protect):0<BR> ********** Sector 18 [FFCF0000] (0-unprotect, 1 protect):0<BR> ********** Sector 19 [FFD00000] (0-unprotect, 1 protect):0<BR> ********** Sector 20 [FFD10000] (0-unprotect, 1 protect):0<BR> ********** Sector 21 [FFD20000] (0-unprotect, 1 protect):0<BR> ********** Sector 22 [FFD30000] (0-unprotect, 1 protect):0<BR> ********** Sector 23 [FFD40000] (0-unprotect, 1 protect):0<BR> ********** Sector 24 [FFD50000] (0-unprotect, 1 protect):0<BR> ********** Sector 25 [FFD60000] (0-unprotect, 1 protect):0<BR> ********** Sector 26 [FFD70000] (0-unprotect, 1 protect):0<BR> ********** Sector 27 [FFD80000] (0-unprotect, 1 protect):0<BR> ********** Sector 28 [FFD90000] (0-unprotect, 1 protect):0<BR> ********** Sector 29 [FFDA0000] (0-unprotect, 1 protect):0<BR> ********** Sector 30 [FFDB0000] (0-unprotect, 1 protect):0<BR> ********** Sector 31 [FFDC0000] (0-unprotect, 1 protect):0<BR> ********** Sector 32 [FFDD0000] (0-unprotect, 1 protect):0<BR> ********** Sector 33 [FFDE0000] (0-unprotect, 1 protect):0<BR> ********** Sector 34 [FFDF0000] (0-unprotect, 1 protect):0<BR> xxxxxxxxxx Program sector 0 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 1 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 2 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 3 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 4 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 5 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 6 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 7 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 8 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 9 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 10 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 11 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 12 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 13 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 14 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 15 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 16 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 17 : Read Fill Erase Program End<BR> xxxxxxxxxx Program sector 18 : Read Fill Erase Program End<BR> ********** Verify Complete<BR> 下面板子開始重啟。</P><P> 【注意】<BR> 一定要看到這些Read Fill Erase Program End信息才表示燒寫進去了,前面<BR> ********** Sector 0 [FFC00000] (0-unprotect, 1 protect):0等只是顯示FLASH的扇區(qū)分布,<BR> 并沒有進行燒寫,只有看到Read Fill Erase Program End信息才表示在進行燒寫。</P><P> 在minicom中用ctrl+a,然后按b,接著用上下箭頭,可以翻看前面的信息,從而查看出了什么錯誤。例如,TFTP連接失敗的信息就要前翻來查看,信息如下:<BR> Unable to locate 192.168.1.46<BR> Errors in TFTP download.<BR> Read 0 bytes (0 blocks)<BR> 這就要查看宿主機(即TFTP服務(wù)器配置是否成功)。</P><P> 工作機制:<BR> ./flash調(diào)用hhco.gdb腳本對CPU進行初始化,(sys-init)<BR> 然后指定<BR> target bdm /dev/bdmcf0<BR> load 即下載一個小軟件(tftp.elf,約80K)到板子的RAM中,并用c(continue)命令讓它跑起來,這時CPU完全由這個小軟件接管。這個小軟件跑起來后初始化以太網(wǎng)及TFTP協(xié)議棧,然后它運行TFTP客戶端,從內(nèi)存中0x00200004(2M+4處)讀取gdb腳本放在此處的TFTP服務(wù)器IP地址,并從該IP的TFTP服務(wù)器PC下載image.bin到板子內(nèi)存1M地址處,再將其燒寫到FLASH上,重啟板子,這時引導(dǎo)起來的就是LINUX了。</P><P> <BR> 問:燒寫時顯示如下信息,但minicom端什么信息也沒有打印出來,而且板子仍然在運行,運行指示仍然正常閃爍?<BR> 在執(zhí)行./flash的TTY一側(cè),會顯示:<BR> GNU gdb 4.18<BR> Copyright 1998 Free Software Foundation, Inc.<BR> GDB is free software, covered by the GNU General Public License, and you are<BR> welcome to change it and/or distribute copies of it under certain conditions.<BR> Type "show copying" to see the conditions.<BR> There is absolutely no warranty for GDB. Type "show warranty" for details.<BR> This GDB was configured as "--host=i686-pc-linux-gnu --target=m68k-bdm-elf"...</P><P> <BR> 這是PC端BDM驅(qū)動(linux-bdm.o)的問題,必須安裝正確的驅(qū)動(例如華恒光盤提供的)。按CTRL+C結(jié)束該進程,用rmmod linux-bdm刪除當前的驅(qū)動,用insmod安裝正確版本的驅(qū)動再重新執(zhí)行./flash即可。</P><P> <BR> 問:燒寫完畢后最后會報如下錯誤:<BR> Program received signal SIGBUS, Bus error.<BR> 0x488 in asm_exception_handler ()<BR> 1: x/i $pc 0x488 <asm_exception_handler+4>: orib #84,%d0<BR> 注意上述信息并非錯誤,燒寫完退出時都要顯示這個信息,并不能表示燒寫是否成功。燒寫成功與否完全要看minicom端的顯示信息來判斷。</P><P> <BR> 問:運行./flash時報錯,內(nèi)容如下:<BR> ./gdb:error while loading shared libraries:libncurses.so.4:cannot load shared object file:No such file or directory.<BR> 這是怎么回事呢?</P><P> 答:這是由于宿主機REDHAT安裝時不完全,不支持DEVELOPMENT工具,如gcc,gdb等工具,導(dǎo)致系統(tǒng)沒有安裝運行這些工具所需的共享庫。建議重新完全安裝系統(tǒng)。</P><P> <BR> 3. 關(guān)于TFTP服務(wù)器設(shè)置<BR> 其實TFTP服務(wù)器可以是和板子相連的局域網(wǎng)內(nèi)任意一臺開通了TFTP服務(wù)的LINUX PC機,即板子可以從任意一臺TFTP服務(wù)器下載IMAGE文件并進行燒寫,當然首先要檢查IP是否匹配及連線是否正確。但若將LINUX宿主機(即用串口線連接的那一臺LINUX PC)同時開通TFTP服務(wù),這樣就不必占用多臺機器。默認完全安裝后的REDHAT的TFTP服務(wù)是沒有開通的,要自己手工開通。</P><P> 開通宿主機上的TFTP服務(wù),對于REDHAT6.x,可以在宿主機上:<BR> vim /etc/inetd.conf<BR> 查找tftp,若發(fā)現(xiàn)前面有#就表示這一行被注釋掉了,即服務(wù)沒有打開,去掉#就打開了TFTP服務(wù),然后重啟宿主機即可。<BR> 對于REDHAT7.2,則在宿主機上執(zhí)行setup,選擇System services,將其中的tftp一項選中(出現(xiàn) [*]表示選中),并去掉ipchains和iptables兩項服務(wù)(即去掉它們前面的*號)。然后還要選擇Firewall configuration,選中No firewall。最后,退出setup,執(zhí)行如下命令以啟動TFTP服務(wù):<BR> service xinetd restart<BR> 配置完成后,建議簡單測試一下TFTP服務(wù)器是否可用,即自己tftp自己,例如在宿主機上執(zhí)行:<BR> cd /<BR> cp /HHCO5272-R1/image/image.bin /tftpboot/<BR> tftp 192.168.2.32<BR> tftp>get image.bin<BR> 若出現(xiàn)如下信息:<BR> Received 634732 bytes in 0.7 seconds<BR> 就表示TFTP服務(wù)器配置成功了。若彈出信息說:Timed out,則表明未成功,需要按照上述步驟重新檢查一遍。<BR> 或者用如下命令查看tftp服務(wù)是否開通:<BR> netstat -a|grep tftp<BR> 完成上述配置工作后,就可以開始使用該以太網(wǎng)燒寫工具了。</P><P> <BR> 4. BDM與重啟問題<BR> 安裝bdm驅(qū)動模塊,以HHCO5272-R1為例:<BR> 1. cd HHCO5272-R1/bdm<BR> 2. insmod linux-bdm.o 【可將此句寫入/etc/rc.d/rc.local文件中,如:</P><P> /sbin/insmod /HHCO5272-R1/bdm/linux-bdm.o,這樣每次PC啟動都會自動執(zhí)行,否則每次啟動宿主機都要執(zhí)行這一句】<BR> 3. ./MAKEDEV 【在/dev/下創(chuàng)建設(shè)備bdmcf0,只要執(zhí)行一次】<BR> 【注意】<BR> 在insmod時有可能出現(xiàn).o文件與內(nèi)核版本不匹配現(xiàn)象,這時只要重編該模塊驅(qū)動即可。具體請參閱下面第31條。</P><P> 還有,BDM線的長度不能加長,否則使用時會報"bdm not open"。</P><P> <BR> 問:板子剛拿到,一加電就不啟動,運行指示燈不閃,minicom什么信息也沒有,怎么回事?<BR> 答:這是因為插了BDM卡,若不插BDM卡,板子就可以正常啟動了。</P><P> 從軟件使用者的角度來說,插了BDM后,核心板的reset鍵就失效,所以板子加電后沒有收到reset信號,所以板子不能啟動。這時要板子讓板子上的軟件系統(tǒng)啟動運行,可以先執(zhí)行一下chk,然后立刻退出則板子就會自動重啟。<BR> cd chk<BR> ./chk<BR> >>>x<BR> 當板子啟動后,可以通過minicom接收命令,則要重啟就直接在minicom下鍵入reboot即可重啟,這時按reset鍵無效。若不插BDM則板子的reset按鍵是有效的。</P><P> <BR> 有時,執(zhí)行chk時報錯:</P><P> device busy表示有其它程序在使用BDM<BR> 用ps -A<BR> 看看是否有其它程序在使用BDM,例如gdb(即gdbtftpflash下的./flash)或者chk,</P><P> 若提示device not found,則表明沒有安裝驅(qū)動linux-bdm.o</P><P> 5. 板子死了?<BR> 判斷板子是否死機的標準不是minicom是否可以輸入等,最可信的標準就是看核心板上的運行指示燈是否還正常的閃爍,若不再閃了,必死無疑。有時串口可以打印輸出信息,但用戶卻無法輸入命令,這經(jīng)常是由于操作者手上靜電太高導(dǎo)致串口工作異常。這時建議給板子斷電,把核心板和底板以及串口線等都重新拔插一下再加電重啟試試;或者換一臺PC,或者用telnet使用網(wǎng)絡(luò)終端。</P><P> 6. TFTP下載與RAM版本問題<BR> 用bootloader下載RAM內(nèi)核,總是報錯:</P><P> KERNEL: Bad trap from supervisor state, vector=4 </P><P> CURRENT PROCESS: <BR> COMM=swapper PID=1 <BR> TEXT=00100000-00156e6c DATA=00000000-0016685c BSS=0016685c-0017d7f0 <BR> USER-STACK=00000000 KERNEL-STACK=0021d000<BR> ......</P><P> 答:</P><P> 因為TFTP采用的是udp傳輸?shù)模?lt;BR> 而我們的板子是通過一個小HUB跟局域網(wǎng)聯(lián)在一起的,<BR> 可能在傳輸中有些包丟失了,或者是在傳輸中有些<BR> 數(shù)據(jù)出現(xiàn)錯誤,因此出現(xiàn)RAM版的不能用。后來單獨把板子跟一臺計算機的網(wǎng)卡相連,</P><P> 或者都接到同一個HUB上,就不會有問題了。</P><P> <BR> 有時燒寫完后板子啟動時回出現(xiàn)如下錯誤:<BR> Unable to open an initial console.</P><P> 這種現(xiàn)象有多種原因可能導(dǎo)致出現(xiàn),其中就有可能是這里所提的燒寫錯誤所致。</P><P> 7. BUSS ERROR的問題<BR> 記住出錯時打印出的PC指針值,將linux/linux<BR> 用m68k-elf-objdump -D linux >tt<BR> vim tt<BR> 反匯編后查看該PC地址處在什么函數(shù)調(diào)用內(nèi),<BR> 從而作進一步定位。</P><P> <BR> 用chk單步跟蹤,(fp命令)<BR> 建議閱讀chk源代碼,可以根據(jù)自己的需要定制自己的調(diào)試命令。<BR> 所有可用的BDM操作都在bdm/下的一個bdm.h文件中。</P><P> 8. 硬件擴展<BR> 問:CN5的復(fù)用腳p19,p23,p25是系統(tǒng)寬度總線控制信號,留給 用戶,系統(tǒng)沒有用嗎?那么復(fù)位期間如何確定總線寬度?<BR> 回答:上電的時候作為系統(tǒng)寬度總線控制信號;但是上電結(jié)束開始運行之后,就變成SPI信號線了,您可以使用。</P><P> 問:普通usb口只用d+ d_兩條信號線,而5272增加了轉(zhuǎn)出去的信號線:usb-rp,usb-tp....(pa{6:0}),用戶能否用其第一功能?<BR> 回答:5272本身帶有usb收發(fā)器,5272可以讓您選擇是否選擇外部usb收發(fā)器(通過配置內(nèi)部寄存器來選擇)。建議選用外部USB收發(fā)器。注意!是收發(fā)器,不是控制器!USB控制器是在5272里面的。<BR> 【注】cn5,cn6只是做簡單的擴展,而你可以通過自己設(shè)計底板(華恒底板都已經(jīng)在手冊里面有原理圖了。,從而在cn1,cn2,cn3使用信號。cn1,cn2,cn3上的管腳對應(yīng)的信號原理圖上都有。其中地址線在cn1的1~45(奇數(shù)腳),數(shù)據(jù)線在cn2的2~64(偶數(shù)腳)。ddat[3:0]和DTEA都在cn3上,是用于接BDM口的。具體使用請參考5272處理器手冊。<BR> USB[3:1]管腳是從一個外接的USB收發(fā)芯片pdiusb11上接出的。而TX_P~RX_N是以太網(wǎng)隔離變壓器的輸出線。cpuclk的頻率為66Mhz,無驅(qū)動。 </P><P> </P><P> 關(guān)于系統(tǒng)I/O:</P><P> MCF5272共提供48個通用IO引腳,它們可以分為3個16位PORT,即PORTA、PORTB、PORTC。其中PORTA,PORTB對應(yīng)的控制寄存器來實現(xiàn)與其它信號引腳的復(fù)用。Port C沒有PCCNT寄存器,它只能在工作為外總線16位模式時作為16位的I/O口線使用,即它與D[0~15]復(fù)用,只有16位外總線模式時,因為只用高16位D[16~31],這時D[0~15]就為PC[0~15]。另外的一個端口Port D不能被用做I/O線。<BR> 系統(tǒng)剩余GPIO資源(以HHCO5272-R1為例):<BR> PA7~PA14(8根引腳);PB4~PB7(4根引腳);<BR> 若去掉USB接口,則PA[6:0]可用(7根引腳)。<BR> 所以一般的去掉USB,通用IO引腳可用的有8+4+7=19根。<BR> 串口0所占用的PB[3:0](4根引腳),其中PB0/1為URT0_TxD/URT0RxD,PB2/3為CTS/RTS。<BR> 若去掉串口0的CTS/RTS,又多2根,即可19+2=21根。<BR> 若整個去掉串口0,又多兩根,即最多21+2=23根。</P><P> 9.串口2檢測<BR> 將板子的串口2和宿主機的串口1連接起來,在宿主機的一個TTY啟動minicom,另一個TTY執(zhí)行chk<BR> ./chk<BR> >>>fr colilo2.bin e00000 【下載到RAM中0x00e00000地址處】<BR> >>>fg xx e00400 【從0x00e00400地址處開始執(zhí)行,加上0x400是要跳過前面1024個字節(jié)的ramvect】<BR> 代碼下到板子RAM中,然后用fg將其激活跑起來后,CPU就由那個代碼控制了,這時就不要在chk中輸入任何命令了。不要在chk中執(zhí)行退出(x),否則板子立即reset,下載到RAM中的內(nèi)容就丟了。【注意】沒有fg之前,核心板上運行指示燈(LEDK1)是不亮不閃的。一旦fg xx e00400后就應(yīng)該亮閃起來。這是判斷下載軟件是否跑起來的唯一標準,與串口是否打印完全無關(guān)。若minicom沒有打印信息,就只能說明串口2是壞的。</P><P> </P><P> 10. 開發(fā)/使用注意<BR> ◇無論編譯內(nèi)核還是自己的某一個應(yīng)用程序都必須在uClinux目錄下進行編譯make,在其它目錄下編譯都會報錯。</P><P> ◇當板子插了網(wǎng)線時,核心板上的百兆以太網(wǎng)連接和碰撞指示燈(LEDL2)就會亮起來,若這時板子ping一臺PC機或者一臺PC機ping板子的話,LEDL2燈就會閃爍起來。若LEDL2不亮,可能是以太網(wǎng)插口接觸不好所致,用力插緊即可。<BR> ◇HHCO5272-R1提供了串口2可用于作MODEM撥號,需要把uClinux/user/pppd/、chat/和diald/三個目錄加入編譯,并編寫正確的撥號腳本和配置文件。華恒提供完備的PPP撥號軟件包。<BR> ◇HHCO5272-R1板上采用的是ROMFS的文件系統(tǒng),它是只讀的。可以擴展支持JFFS/JFFS2文件系統(tǒng),它可讀可寫。華恒提供完備的JFFS/JFFS2支持軟件包。</P><P> ◇在用ddd-5272調(diào)試應(yīng)用程序時,若看不到代碼,是因為沒有加-g的編譯參數(shù);若代碼能看到,但是是在run的時候提示BDM not Open! 這是run命令的問題,運行時不要用run,而用continue命令,即c。</P><P> ◇MCF5272不支持外設(shè)的DMA,它只有內(nèi)部DMA,為FEC所用。</P><P> ◇要在系統(tǒng)啟動時自動執(zhí)行用戶自己的應(yīng)用程序,就必須修改uClinux/romfs/etc/rc文件,這是個啟動的腳本文件,它的作用就相當于WINDOWS98下的autoexec.bat,這個腳本文件中的每一句都是在shell下可直接執(zhí)行的命令。例如用戶移植了WEB SERVER boa,要啟動就執(zhí)行boa,就在這個rc文件的最后加一句boa&,然后到uClinux下執(zhí)行make,然后./flash燒寫板子即可。</P><P> ◇板子IP的修改:</P><P> 可以用ifconfig/route(2.4內(nèi)核不需要route命令)命令來修改板子啟動后的IP,但這個修改在重啟后無法保存。因為板子IP的指定是在其ROMFS文件系統(tǒng)的/etc/rc文件中指定的,如下:</P><P> ifconfig eth0 192.168.2.112</P><P> route add -net 192.168.2.0</P><P> 要永久的改變板子的IP,就要在宿主機上修改uClinux/romfs/etc/rc文件中對應(yīng)的IP設(shè)置內(nèi)容,然后在uClinux下重新編譯,然后重新燒寫。但這樣做的問題在于無法做到動態(tài)修改IP并保存。要實現(xiàn)這種功能,就必須在板子上實現(xiàn)文件存儲功能。實現(xiàn)的機制有許多,如flatfsd、JFFS/JFFS2文件系統(tǒng)等。對于板子上的存儲機制,華恒提供完整的JFFS/JFFS2軟件包銷售,可大大加快用戶的開發(fā)進度及產(chǎn)品上市時間。</P><P> 11. 啟動失敗 </P><P> 客戶問:HHCF5272-LCD-IDE-R1套件中:把image.bin寫到flash后,應(yīng)該可以從板子啟動進入uClinux中,但是它會出現(xiàn)一個錯誤是kernel panic attempted to kill init!</P><P> 答復(fù):都是usb_init惹的禍<BR> 這樣修改:<BR> vim uClinux/linux-2.4.x/drivers/char/mem.c<BR> 去掉usb_init一行,然后重新編譯燒寫就沒有問題了。</P><P> </P><P> 12. 串口2問題 </P><P> ◇客戶問:</P><P> 一個簡單測試程序,向/dev/ttyS0發(fā)送數(shù)據(jù),波特率設(shè)為38400,在PC機下順利接收到。利用5272開發(fā)板上的串口1發(fā)送,另一端在minicom下,設(shè)為相同的波特率,能接收到數(shù)據(jù),但是相同的程序,只修改為/dev/ttyS1確收不到任何數(shù)據(jù),<BR> 答復(fù):經(jīng)次測試,發(fā)現(xiàn)是缺少了對串口2占用的PD口的初始化。<BR> 對于HHCF5272-R1,更新的文件sysinit.c,<BR> 將它覆蓋到uClinux/linux/arch/m68knommu/platform/5272/目錄下,<BR> 重新編譯燒寫即可。<BR> 對于HHCF5272-LCD-IDE-R1 ,將附件colilo.bin覆蓋到uClinux/colilo/目錄下,重新編譯燒寫即可。 </P><P> <BR> 13. 擴大RAM盤的方法<BR> 有客戶問到增大HHCF5272-R1板子上的/var/目錄大小的問題,<BR> 這個目錄是RAM盤,可讀可寫。<BR> 它的大小是在uClinux/romfs.mk中指定的:<BR> 例如要指定為2M大小的RAM盤:<BR> 則加入如下一句:<BR> RAMFSy = $(USER)/ramimage/ramfs2048.img<BR> 即可。 </P><P> 【注意】<BR> RAM盤太大好像會引起系統(tǒng)死機。</P><P> </P><P> 14. 關(guān)于編譯重燒啟動時出現(xiàn)“unable to open an initial console”問題</P><P> 解決辦法:<BR> 修改uClinux/vendor/HHtech/M5272/Makefile,<BR> 將其中的genromfs改為/usr/local/bin/genromfs即可。</P><P> </P><P> 15. 關(guān)于BDM驅(qū)動“ kernel-module version mismatch”問題<BR> 現(xiàn)象:在bdm/driver/linux下執(zhí)行make后,insmod linux-bdm.o時出現(xiàn)如下錯誤:</P><P> linux-bdm.o: kernel-module version mismatch<BR> linux-bdm.o was compiled for kernel version 2.4.17<BR> while this kernel is version 2.4.5. </P><P> 解決辦法:</P><P> 在PC機上執(zhí)行uname -r<BR> 看看當前的內(nèi)核版本,<BR> 例如:顯示為2.4.5<BR> ,則修改bdm/driver/linux/Makefile中的CFLAGS一行為如下:<BR> CFLAGS = -Wall -g -O -pipe -I/usr/src/linux-2.4.5/include -I.. -DMODULE -D__KERNEL__ $(MODVERSIONS)</P><P> 這樣編譯就不會有內(nèi)核版本不匹配的問題了</P><P> </P><P> 16. 關(guān)于系統(tǒng)啟動時數(shù)據(jù)總線寬度的問題</P><P> 5272復(fù)用腳L5 QSPICLK/BUSW1 和M5 SPI_CS0/BUSW0<BR> 在HHCO5272-R1中用作 QSPICLK 和 SPI_CS0 功能(CN1 <BR> pin93 ,CN1 pin95) , 而只有在CPU復(fù)位時它們才作為BUSW1:BUSW0組合決定CS0內(nèi)存數(shù)據(jù)寬度。這個是不需要配置的。<BR> 具體參見MCF5272手冊:P14-2頁,即P14.3.1節(jié)介紹。<BR> 華恒板子的BUSW1:BUSW0組合為[1:0],即16位模式,因此剛加電時接CS0的FLASH0的數(shù)據(jù)總線寬度為16位模式。<BR> 同理,N4 QSPI_DOUT/WSEL 在HHCO5272-R1中用作 <BR> QSPI_DOUT 功能(CN1 pin89 ), <BR> WSEL也只是CPU復(fù)位時生效,華恒板子此腳接下拉電阻,表示為0,因此為32位模式。此后都作為QSPI_DOUT信號使用,不需配置。</P><P> </P><P> 17. 關(guān)于REDHAT7.3宿主機環(huán)境配置的問題 </P><P> 目前主要的問題在于完全安裝的REDHAT7.3沒有提供linuxconf工具軟件,因此無法配置NFS服務(wù)器。不過這個問題很容易解決,這需要到<img align=absmiddle src=pic/url.gif border=0><a target=_blank href=http://ftp.boe.tcc.edu.tw/tnc/firewall/> http://ftp.boe.tcc.edu.tw/tnc/firewall/</a>下載一個名為:linuxconf-1.25r7-3.i386.rpm的RPM包,然后在REDHAT7.3 LINUX機器上執(zhí)行:</P><P> rpm -i linuxconf-1.25r7-3.i386.rpm (6,995KB)</P><P> 這個安裝比較耗時,安裝完畢后,立即就可以使用linuxconf工具了</P><P> </P><P> 18. 關(guān)于定時器使用的問題</P><P> 對于秒級以上的應(yīng)用程序:<BR> alarm(sec)<BR> 在sec秒以后就會產(chǎn)生一個sigalrm信號。<BR> 注冊一個自己的處理函數(shù)來處理這個信號就可以實現(xiàn)。</P><P> 對于ms級的定時,usleep為us級的延時,但無法提供中斷。<BR> MCF5272提供四個定時器,uClinux只使用了其中一個:<BR> uClinux/linux/arch/m68knommu/platform/5272/config.c中:<BR> void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *))<BR> {<BR> volatile unsigned short *timerp;<BR> volatile unsigned long *icrp;</P><P> /* Set up TIMER 1 as poll clock */<BR> timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1);<BR> timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE;</P><P> timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ);<BR> timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |<BR> MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;</P><P> icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);<BR> *icrp = 0x0000d000; /* TMR1 with priority 5 */<BR> request_irq(69, handler, SA_INTERRUPT, "ColdFire Timer", NULL);<BR> }<BR> void config_BSP(char *commandp, int size)<BR> {<BR> memset(commandp, 0, size);<BR> mach_sched_init = coldfire_timer_init;<BR> mach_tick = coldfire_tick;<BR> mach_trap_init = coldfire_trap_init;<BR> }<BR> uClinux/linux/arch/m68knommu/kernel/time.c:<BR> void time_init(void)<BR> {<BR> unsigned int year, mon, day, hour, min, sec;</P><P> extern void arch_gettod(int *year, int *mon, int *day, int *hour,<BR> int *min, int *sec);</P><P> arch_gettod (&year, &mon, &day, &hour, &min, &sec);</P><P> if ((year += 1900) < 1970)<BR> year += 100;<BR> xtime.tv_sec = mktime(year, mon, day, hour, min, sec);<BR> xtime.tv_usec = 0;</P><P> if (mach_sched_init)<BR> mach_sched_init(timer_interrupt);<BR> }<BR> /*<BR> * timer_interrupt() needs to keep up the real-time clock,<BR> * as well as call the "do_timer()" routine every clocktick<BR> */<BR> void timer_interrupt(int irq, void *dummy, struct pt_regs * regs)<BR> {<BR> /* last time the cmos clock got updated */<BR> static long last_rtc_update=0;</P><P> /* may need to kick the hardware timer */<BR> if (mach_tick)<BR> mach_tick();</P><P> do_timer(regs);</P><P> /*<BR> * If we have an externally synchronized Linux clock, then update<BR> * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be<BR> * called as close as possible to 500 ms before the new second starts.<BR> */<BR> if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&<BR> xtime.tv_usec > 500000 - (tick >> 1) &&<BR> xtime.tv_usec < 500000 + (tick >> 1)) {<BR> if (set_rtc_mmss(xtime.tv_sec) == 0)<BR> last_rtc_update = xtime.tv_sec;<BR> else<BR> last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */<BR> }</P><P> }<BR> add_timer函數(shù)在uClinux/linux/kernel/sched.c中定義<BR> void add_timer(struct timer_list *timer)<BR> {<BR> unsigned long flags;<BR> save_flags(flags);<BR> cli();<BR> #if SLOW_BUT_DEBUGGING_TIMERS<BR> if (timer->next || timer->prev) {<BR> printk("add_timer() called with non-zero list from %p\n",<BR> __builtin_return_address(0));<BR> goto out;<BR> }<BR> #endif<BR> internal_add_timer(timer);<BR> #if SLOW_BUT_DEBUGGING_TIMERS<BR> out:<BR> #endif<BR> restore_flags(flags);<BR> }<BR> static inline void internal_add_timer(struct timer_list *timer)<BR> {<BR> /*<BR> * must be cli-ed when calling this<BR> */<BR> unsigned long expires = timer->expires;<BR> unsigned long idx = expires - timer_jiffies;</P><P> if (idx < TVR_SIZE) {<BR> int i = expires & TVR_MASK;<BR> insert_timer(timer, tv1.vec, i);<BR> } else if (idx < 1 << (TVR_BITS + TVN_BITS)) {<BR> int i = (expires >> TVR_BITS) & TVN_MASK;<BR> insert_timer(timer, tv2.vec, i);<BR> } else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) {<BR> int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;<BR> insert_timer(timer, tv3.vec, i);<BR> } else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {<BR> int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;<BR> insert_timer(timer, tv4.vec, i);<BR> } else if (expires < timer_jiffies) {<BR> /* can happen if you add a timer with expires == jiffies,<BR> * or you set a timer to go off in the past<BR> */<BR> insert_timer(timer, tv1.vec, tv1.index);<BR> } else if (idx < 0xffffffffUL) {<BR> int i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;<BR> insert_timer(timer, tv5.vec, i);<BR> } else {<BR> /* Can only get here on architectures with 64-bit jiffies */<BR> timer->next = timer->prev = timer;<BR> }<BR> }<BR> 在uClinux/linux/arch/m68knommu/platform/5272/config.c中的coldfire_timer_init中增加對TMR2初始化設(shè)置和中斷申請。然后自己寫TMR2的定時器中斷服務(wù)程序,<BR> 這個代碼可放在config.c中,也可加到OS代碼中:<BR> uClinux/linux/arch/m68knommu/kernel/time.c:<BR> 這個文件中有LINUX使用TMR1的定時器中斷服務(wù)程序代碼:<BR> void timer_interrupt(int irq, void *dummy, struct pt_regs * regs)<BR> 它是用來給LINUX OS提供時鐘的,自己的定時中斷就不必做這個工作了,讓它10ms進一次中斷,在自己的TMR2中斷程序中做自己的工作就可以了。當然這里的處理一定要快。</P><P> <BR> </P><P> 19. 關(guān)于C++支持<BR> 華恒HHCF系列開發(fā)套件光盤提供的軟件系統(tǒng)支持C++代碼,下面給出一個編譯參數(shù)的例子:</P><P> m68k-elf-g++ -m5307 -msep-data -Wl,-elf2flt -o test test.cpp -lstdc++ -lc -lgcc </P><P> 【注意】</P><P> 這里沒有加入庫的路徑和頭文件的路徑:-L和-I,請用戶在編譯時自己指定絕對路徑。<BR> 下面介紹一下將C++代碼統(tǒng)一到user目錄下像普通應(yīng)用程序一樣參與編譯:</P><P> C++程序在5272上的編譯,首先要修改uclinux目錄下的config.arch文件,將其中的<BR> CXX = $(CROSS_COMPILE)g++ <BR> 改為:<BR> CXX = $(CROSS_COMPILE)g++ $(CPUFLAGS) -DCONFIG_COLDFIRE<BR> 再將其中的<BR> CXXLIBS = $(LDPATH) $(LIBSTDCPP) $(LIBIOSTREAM) $(LIBIO) $(LIBIBERTY) $(LIBC) $(LIBGCC)<BR> 改為:<BR> CXXLIBS = $(LDPATH) $(LIBSTDCPP) $(LIBIBERTY) $(LIBC) $(LIBGCC)<BR> 然后模仿以下的Makefile書寫:<BR> EXEC = test<BR> OBJS = test.o<BR> all: $(EXEC)<BR> $(EXEC): $(OBJS)<BR> $(CXX) $(LDFLAGS) -o $@ $(OBJS) $(CXXLIBS)<BR> romfs:<BR> $(ROMFSINST) /bin/$(EXEC)<BR> clean:<BR> -rm -f $(EXEC) *.elf *.gdb *.o<BR> 即可。<BR> 說明:uclinux(uclibc)現(xiàn)在對iostream的支持還不夠,不能使用iostream庫。<BR> 【注】</P><P> 華恒客戶可發(fā)信到support@hhcn.com索取測試代碼。</P><P> </P><P> 20. 關(guān)于進程間通信IPC的問題</P><P> uClinux下system V的進程間通信IPC機制不可用!</P><P> (現(xiàn)在已經(jīng)可以用了,在make menuconfig中內(nèi)核配置菜單中選擇General setup --->,選中:</P><P> [*] System V IPC)<BR> 1 信號:但要求知道另一個進程的pid號:<BR> 進程間用信號通信時,用kill發(fā)送信號,但需要指定進程號,<BR> 可以這樣作:<BR> 接收信號的進程把自己的進程號寫到RAM盤(如/tmp目錄)下的一個文件中,發(fā)送信號的進程從這個文件中讀取這個進程號即可成功的實現(xiàn)信號發(fā)送。</P><P> 這里是直接指定內(nèi)存地址(當然做好是在靠后的未用地址),然后用一個進程啟動另一個進程,這兩個進程之間的進程號恰好相差1,這樣就可以在兩個進程之間使用信號了。<BR> 2 共享文件:兩個進程訪問同一個文件,用文件鎖實現(xiàn)互斥訪問。<BR> 要保護/tmp/a文件,<BR> 在一個進程中每次要fopen前,先判斷是否有a.lock文件鎖,<BR> 若有就等待。<BR> 若沒有,則創(chuàng)建該文件鎖用open(O_CREAT|0_EXECL,<BR> S_IRUSR|S_IWUSR)創(chuàng)建。<BR> 另一方法:在RAM中建立共享區(qū)(相當于文件)<BR> 在一個進程里面分配一個內(nèi)存快,然后將內(nèi)存快的地址傳給<BR> 由vfork和exclp創(chuàng)建的另一個進程,這樣這兩個進程就可以對這塊內(nèi)存進行讀寫了,對共享內(nèi)存的互鎖是通過發(fā)信號實現(xiàn)的。<BR> 一共有4個進程,分別一個啟動一個,這樣他們的進稱號恰好是連續(xù)的,一就是說一個進程知道任意一個它想發(fā)信號的進程號。這樣就可以在所有進程間發(fā)信號了,共享內(nèi)存是先分配內(nèi)存塊,然后傳遞已經(jīng)有操作系統(tǒng)分配好的共享內(nèi)存地址,管道使用的pipe創(chuàng)建,然后使用vfork創(chuàng)建另一個進程,并傳遞管道的讀、寫fd,就可以讀寫管道了。</P><P> 3 消息隊列<BR> 含消息隊列的程序編譯程序時會提示沒有定義符號--"msgctl,msgsnd,msgget,msgrcv";<BR> 在/uClinux/linux/ipc/msg.c里有系統(tǒng)調(diào)用的源代碼<BR> -"sys_msgget,sys_msgctl,sys_msgsnd,sys_msgrcv";<BR> 再查看系統(tǒng)uClinux\linux\arch\m68knommu\kernel/sys_m68k.c里ipc系統(tǒng)調(diào)用里調(diào)用--"sys_msgget,sys_msgctl,sys_msgsnd,sys_msgrcv"內(nèi)核函數(shù);<BR> 所以推斷是檔案libc.a里沒包含"msgctl,msgsnd,msgget,msgrcv"原形函數(shù)調(diào)用;<BR> 做法:<BR> 1)make xconfig;選取SYSTEM V IPC<BR> 2)在/uClinux/lib/libc/生成目錄./msg<BR> 3)添加文件msgctl.c,msgsnd.c,msgget.c,msgrcv.c,寫相應(yīng)的makefile;<BR> 4)修改上一級目錄里makefile,添加msg目錄;->加函數(shù)到libc.a里;<BR> 5)make dep;<BR> 6)make;<BR> 注意:在系統(tǒng)機上發(fā)消息隊列的長度和接收消息隊列的長度可以不等長;華恒內(nèi)核中長度好象必須相等,(最大不要超過BUFSIZ=1024)。<BR> 消息隊列可以對其進行編址,使得各個進程各取所需,并且可以使消息隊列的個數(shù)變少。但是如果在消息隊列被刪除后還有N個要發(fā)送或檢索的進程,會發(fā)生問題 <BR> 信號量的做法一樣!</P><P> <BR> </P><P> 21. 關(guān)于應(yīng)用程序中使用GPIO的問題</P><P> 關(guān)于GPIO,要設(shè)置三個寄存器,分別是:以PB口為例<BR> 1)PBCNT,絕對各個引腳的復(fù)用信號是否為IO<BR> 2)方向寄存器,每個引腳是輸入還是輸出。<BR> 3)數(shù)據(jù)寄存器,進行IO的輸入輸出。</P><P> 給個例子代碼:(注意:這是在用戶應(yīng)用程序中的代碼,不是內(nèi)核態(tài)代碼)</P><P> *(volatile unsigned long *)0x10000080 &=0xff003fff; // PACNT 14-23 bit is cleared,use PA7-11<BR> *((volatile unsigned short *)0x10000084 |= 0x0f80; // PADDR 7-11 bit is setted,use as output</P><P> *(volatile unsigned short *)0x10000086 = 0x0080; // PA7為0,PA8為0<BR> *(volatile unsigned short *)0x10000086 = 0x0180; // PA7為0,PA8為1</P><P> </P><P> <BR> 22. 關(guān)于管道的使用</P><P> 下面是一個例子,在一個進程中通過管道啟動另一個進程test。<BR> #include <sys/wait.h><BR> #include <stdio.h></P><P> int main(void)<BR> {<BR> FILE *fd;<BR> int waitstat;<BR> char buf[20];<BR> if((fd=popen("/bin/test","r"))==NULL)<BR> printf("popen error! \n");<BR> wait(&waitstat);<BR> //pclose(fd);<BR> if(fgets(buf,15,fd)==NULL)<BR> printf("fgets error! \n");<BR> printf("%s",buf);<BR> return 0;<BR> }<BR> 代碼移植到uC下時應(yīng)在popen后加入,pclose(fd)或wait(&waitstat)。因為uClibc中popen的實現(xiàn)與X86下的不同,它使用了vfork(PC上是用fork)必須等子進程可靠結(jié)束關(guān)閉文件后才執(zhí)行對文件的下一步讀寫。</P><P> <BR> </P><P> 23. 關(guān)于外設(shè)中斷的問題</P><P> MCF5272處理器提供了6路外部中斷以供外設(shè)控制芯片使用。在MCF5272的啟動代碼中(sysinit.c代碼中)屏蔽了所有的內(nèi)部和外部中斷,因為用戶在擴展使用自己的中斷源設(shè)備時,在該設(shè)備的驅(qū)動初始化代碼(如open函數(shù)中)中就必須手工打開允許這個外部中斷源。屏蔽和允許一個中斷源都是通過設(shè)置ICRn寄存器來實現(xiàn)的。<BR> 在對應(yīng)的PI位寫1,而后面的三位IPL位都為0就表示屏蔽該中斷源。<BR> 在對應(yīng)的PI位寫1,后面的三位IPL位寫001~111就表明打開運行該中斷源,并設(shè)置其中斷優(yōu)先級為1到7級,級別越高,優(yōu)先級越高。<BR> switch(irq)<BR> {<BR> case 1:<BR> *(volatile unsigned long *)(0x10000020) |= 0xb0000000;<BR> break;<BR> case 3:<BR> *(volatile unsigned long *)(0x10000020) |= 0x00b00000;<BR> break;<BR> case 4:<BR> *(volatile unsigned long *)(0x10000020) |= 0x000b0000;<BR> break;<BR> case 5:<BR> *(volatile unsigned long *)(0x1000002c) |= 0x0b000000;<BR> break;<BR> }</P><P> <BR> </P><P> 24. 關(guān)于COLDFIRE系列開發(fā)套件的uClinux內(nèi)核版本</P><P> 華恒COLDFIRE系列開發(fā)套件提供的嵌入式uClinux內(nèi)核版本目前主要有兩種:2.0.38和2.4.x,</P><P> 其中只有HHCF5272-R1還保留了2.0.38的內(nèi)核版本,其它套件全部為2.4內(nèi)核。目前HHCF5272-R1也可以提供2.4的內(nèi)核。</P><P> 華恒版本的uClinux和從網(wǎng)上uClinux.org down下來的版本的區(qū)別在于:</P><P> 1)網(wǎng)上開源的版本只提供了RAM版內(nèi)核,不提供ROM版本,呵呵,這樣做我想可能就是為了限制商業(yè)化用戶吧,因為RAM版本還需要bootloader來引導(dǎo)(但行業(yè)內(nèi),bootloader基本上大家都不提供源代碼),不能直接啟動,根本無法作為商業(yè)產(chǎn)品使用,因此也就只能給愛好者折騰著玩玩而已。華恒替客戶完成了這部分ROM化的工作。</P><P> 2)華恒以本地化器件提供的硬件板卡,因此要針對自己的硬件修改系統(tǒng)啟動代碼、硬件設(shè)備驅(qū)動BSP,并相應(yīng)的提供下載、燒寫等工具軟件,這些都要自己移植,修改或者完全自己定制。沒有這些輔助工具,空有uClinux的tar包,是根本無法進行開發(fā)調(diào)試的。</P><P> 3)本地化全中文技術(shù)手冊及相關(guān)的技術(shù)支持(論壇)。</P><P> </P><P> 25. 關(guān)于不同內(nèi)核版本間應(yīng)用程序移植的問題</P><P> 應(yīng)用程序的移植一般的和內(nèi)核版本是沒有任何關(guān)系的,當然有的應(yīng)用程序是需要內(nèi)核支持的,例如pppd等。在2.0.38內(nèi)核和2.4內(nèi)核之間互移應(yīng)用程序,唯一要注意的就是Makefile的寫法:</P><P> 其實區(qū)別就一句話,就是2.4下面,它把elf2flt作為gcc的一個參數(shù)一步完成了,而2.0.38還要分為兩步完成,體現(xiàn)在Makefile上就如下:</P><P> 對于2.0.38:</P><P> $(LD) $(LDFLAGS) -o $@.elf $(OBJS) $(LDLIBS)<BR> $(CONVERT)<BR> 對于2.4.x:</P><P> $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)</P><P> </P><P> 26. 關(guān)于中斷的問題</P><P> 在每個使用中斷的設(shè)備的驅(qū)動初始化代碼中,都首先要打開中斷,因為啟動代碼把所有中斷都禁止(mask)了,根據(jù)CPU手冊,在ICRn對應(yīng)的PI位寫1,而后面的三位IPL位都為0就表示屏蔽該中斷源。即將對應(yīng)ICR中對應(yīng)的字節(jié)設(shè)置為8。例如啟動時,ICR1就被設(shè)置為:0x88888888。</P><P> 打開中斷時,則在ICRn對應(yīng)的PI位寫1,后面的三位IPL位寫001~111就表明打開運行該中斷源,并設(shè)置其中斷優(yōu)先級為1到7級,級別越高,優(yōu)先級越高。例如MCF5272的幾個內(nèi)部模塊所使用的內(nèi)部中斷:<BR> 1)TIMER:在ICR1對應(yīng)位設(shè)置0xd,即priority == 5(2.0.38用的是TMR1,2.4內(nèi)核用的是TMR4)<BR> 2)FEC:在ICR3對應(yīng)位設(shè)置0xd,即priority == 5<BR> 3)FEC要工作的同時還要使用MII(占用INT2),在ICR1對應(yīng)位設(shè)置0xd,即priority == 5<BR> 4)UART:在ICR2對應(yīng)位設(shè)置0xe,即priority == 6</P><P> <BR> 樣例代碼如下:<BR> FEC:fec.c中int __init fec_enet_init(struct net_device *dev)<BR> volatile unsigned long *icrp;<BR> icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3);//FEC<BR> *icrp = 0x00000ddd;<BR> icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);//MII<BR> *icrp = (*icrp & 0x70777777) | 0x0d000000;</P><P> <BR> TMR4:在uClinux/linux-2.4.x/arch/m68knommu/platform/5272/config.c中對TIMER的初始化如下:<BR> void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *))函數(shù)中有如下代碼:<BR> icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);<BR> *icrp = 0x0000000d; /* TMR4 with priority 5 */<BR> request_irq(72, handler, SA_INTERRUPT, "ColdFire Timer", NULL);</P><P> </P><P> UART1/UART2:在uClinux/linux-2.4.x/drivers/char/mcfserial.c中,有如下代碼對UART進行中斷初始化:<BR> static void mcfrs_irqinit(struct mcf_serial *info)<BR> volatile unsigned long *icrp;<BR> volatile unsigned long *portp;<BR> icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR2);<BR> switch (info->line) {<BR> case 0:<BR> *icrp = 0xe0000000;<BR> break;<BR> case 1:<BR> *icrp = 0x0e000000;<BR> break;</P><P> <BR> 此外,MCF5272相應(yīng)外部中斷后,并不會自動的清楚該中斷的pending位,這樣用戶就必須在自己的中斷處理函數(shù)的末尾自己來替處理器完成這一工作。例如:對于外部中斷3</P><P> *(volatile unsigned long*)(MCF_MBAR+0x20) |= 0x00800000;</P><P> </P><P> 27. 應(yīng)用程序中如何定時產(chǎn)生信號?</P><P> 這個問題就相當于實現(xiàn)WINDOWS下的WM_TIMER功能,定時給應(yīng)用程序發(fā)送消息</P><P> 例如:要求每一秒產(chǎn)生一個信號,去打印一句test。本來signal/alarm只能一次性工作,現(xiàn)在要讓它循環(huán)起來,每一秒都產(chǎn)生信號,就要再其信號處理函數(shù)中對其進行重置。<BR> void test()<BR> {<BR> signal(SIGALRM,test);//重置<BR> alarm(1);<BR> printf("test\n");<BR> }<BR> main()<BR> {<BR> signal(SIGALRM,test);<BR> alarm(1);<BR> for(;;)<BR> {/*主函數(shù)處理部分*/<BR> }<BR> }</P><P> <BR> 28. 應(yīng)用程序的編譯參數(shù)觀察</P><P> 用戶在編譯自己的應(yīng)用程序時,也是要在uClinux下執(zhí)行make,屏幕一滾就過去了,SHIFT+PAGEUP也翻不了那末多,其實自己的應(yīng)用怎么編譯的也不清楚。</P><P> 在uClinux下執(zhí)行make >&t,則自動生成臨時文件t,它記錄了整個編譯過程及每步編譯的詳細參數(shù),對于理解編譯工具的使用及其參數(shù)非常有幫助。(整個的編譯過程詳細分析請參見手冊2.1.3節(jié)),舉例而言,以應(yīng)用程序uClinux/user/inetd和ping為例:</P><P> 對于uClinux-2.0.38下的寫法如下:<BR> /HHCF5272-R1/uClinux/tools/m68k-elf-gcc -m5200 -Wa,-m5200 -DCONFIG_COLDFIRE -Dl<BR> inux -D__linux__ -Dunix -DEMBED -O2 -msoft-float <BR> -I/HHCF5272-R1/uClinux/tools/gcc-include -I/HHCF5272-R1/uClinux/lib/libc/include <BR> -I/HHCF5272-R1/uClinux/lib/libm <BR> -I/HHCF5272-R1/uClinux/vendors/include -fno-builtin -DSERVICES=\"/etc/services<BR> \" -DINETD_CONF=\"/etc/inetd.conf\" -c -o inetd.o inetd.c<BR> 對于uClinux-2.4.17下的編譯全部以gcc為前臺,連ld也被隱藏到后臺了:<BR> m68k-elf-gcc -m5307 -DCONFIG_COLDFIRE -Os -g -fomit-frame-pointer -Dlinux <BR> -D__linux__ -Dunix -D__uClinux__ -DEMBED <BR> -I/HHCF5272-R1/uClinux/lib/libc/include -I/HHCF5272-R1/uClinux/lib/libm <BR> -I/HHCF5272-R1/uClinux -I/HHCF5272-R1/uClinux/linux-2.4.x/include <BR> -fno-builtin -msep-data -c -o ping.o ping.c</P><P> m68k-elf-gcc -m5307 -DCONFIG_COLDFIRE -Os -g -fomit-frame-pointer <BR> -Dlinux -D__linux__ -Dunix -D__uClinux__ -DEMBED <BR> -I/HHCF5272-R1/uClinux/lib/libc/include -I/HHCF5272-R1/uClinux/lib/libm <BR> -I/HHCF5272-R1/uClinux -I/HHCF5272-R1/uClinux/linux-2.4.x/include <BR> -fno-builtin -msep-data -Wl,-elf2flt -o ping ping.o <BR> -L/HHCF5272-R1/uClinux/lib/libc/. -L/HHCF5272-R1/uClinux/lib/libc/lib <BR> -L/HHCF5272-R1/uClinux/lib/libm -L/HHCF5272-R1/uClinux/lib/libnet <BR> -L/HHCF5272-R1/uClinux/lib/libdes -L/HHCF5272-R1/uClinux/lib/libpcap <BR> -L/HHCF5272-R1/uClinux/lib/libssl -lc</P><P> <BR> -L表明后面為所要鏈接的libc庫的路徑。庫路徑可以有多個(對于一個應(yīng)用程序而言,很多庫并沒有用),因此可以看到有多個-L參數(shù);<BR> -I參數(shù)表明后面所跟的為C語言INCLUDE頭文件的路徑,這個路徑可以有多個,因此可以看到有多個-I參數(shù);<BR> -m5200(-m5307)為處理器相關(guān)編譯參數(shù),2.4下采用了-m5307,這其實對于應(yīng)用程序而言沒有任何區(qū)別;<BR> -c后面為所要編譯的C文件;<BR> -o后面為這行編譯操作的目的,即這行編譯完畢后要生成的文件;<BR> -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce:這些都是編譯參數(shù);</P><P> <BR> </P><P> 29. FLASH上數(shù)據(jù)保存</P><P> 鑒于目前發(fā)行的套件中的uClinux均采用ROMFS作為其根文件系統(tǒng),因此其目錄大多是不可寫的。只有/var,/tmp是RAM盤可寫,但板子一掉電里面的內(nèi)容就丟失了,因此只能作臨時文件保存,無法永久的保存數(shù)據(jù),例如配置文件等。下面大概介紹一下幾種FLASH上保存配置的方法:</P><P> 1. 對于簡單的數(shù)據(jù),小的配置文件等,而且不是非常頻繁的(例如一分鐘寫10次)寫入的,可以直接自己在FLASH的空余處(例如第二片F(xiàn)LASH上)劃出一塊區(qū)域,以自己定義的方式寫入,并在板子啟動時自動讀出。華恒提供了這樣的樣例代碼,即user/memtools/,其詳細介紹在手冊第二章“FLASH扇區(qū)保存IP地址”一節(jié)。這樣作最大的好處是用戶的控制程度最大,形式最靈活,保存的可以是自定義的數(shù)據(jù),可以不是文件的形式。而下面的幾種方式都是要求文件的形式保存,無法處理自定義的數(shù)據(jù)保存。</P><P> 2. 對于比較多的配置文件,一般的都先寫在RAM盤中,然后選擇保存,一次性寫入FLASH的某幾個扇區(qū)。這時就可使用flatfsd軟件,它的使用需要內(nèi)核的配合支持,即要在blkmem.c中為其指定保存數(shù)據(jù)的幾個扇區(qū)的起始/結(jié)束地址。這中方式也不能適應(yīng)非常頻繁的寫入。</P><P> 3. 對于比較頻繁的數(shù)據(jù)保存,就要在板子上建立額外的日志型文件系統(tǒng)JFFS/JFFS2,或者干脆就用JFFS/JFFS2取代ROMFS作根文件系統(tǒng)。這樣板子的目錄就是可寫的,就像硬盤一樣,不需要額外的工具來負責將數(shù)據(jù)寫入FLASH。JFFS為2.0.38內(nèi)核所支持,它不支持JFFS2,JFFS2到2.4內(nèi)核才被支持,它采用了成熟穩(wěn)定的MTD技術(shù),因此要比JFFS穩(wěn)定。這兩種文件系統(tǒng)要在uClinux上實現(xiàn)支持并不復(fù)雜,但它的實用還需要一些額外的工作,例如燒寫工具的配合,新型image.bin編譯生成,因為真正產(chǎn)品化的軟件是不能允許每次啟動后都還要進行許多的手工操作,例如加載文件系統(tǒng)等,板子出廠燒寫也要一次完成,而不能還要分多次燒寫等等,這些工作都是比較繁雜的,而且沒有燒寫工具的源代碼是無法完成的。華恒提供JFFS/JFFS2整套軟件技術(shù)。</P><P> </P><P> 30. 關(guān)于2.4內(nèi)核版本下的RAM版內(nèi)核的編譯</P><P> 對于2.0.38內(nèi)核,華恒提供了完備的ram.ld和crt0_ram.S,它們和華恒提供的bootloader可配合使用。 對于2.4.17的內(nèi)核,從網(wǎng)上直接DOWN的uClinux-Coldfire版本(例如最新版本:uClinux-dist-20020701.tar.gz)是可以直接在華恒bootloader提示符HHCN>下執(zhí)行readàgo 100000跑起來的。而若客戶要從華恒2.4系列開發(fā)套件軟件系統(tǒng)的基礎(chǔ)上改動跑RAM版則需要做一些改動才可以的,例如HHCF5272-LCD-IDE-R1、HHCF5272-2ETH-R2等都是采用的2.4內(nèi)核。因為華恒板子燒在FLASH上的就是一個RAM版本的內(nèi)核,經(jīng)由華恒的bootloader解壓復(fù)制到RAM中才激活執(zhí)行的,它的執(zhí)行方式和readàgo的方式是完全不同的,雖然都是RAM版。要做到這一點,華恒是做了一些改動的,而現(xiàn)在實際上就是要恢復(fù)成從網(wǎng)上直接DOWN下來的狀態(tài)。<BR> 1 首先是crt0_ram.S和直接下載的uClinux-Coldfire版本的crt0_ram.S有區(qū)別,是經(jīng)過華恒修改的代碼,若直接使用必然無法通過bootloaderàreadàgo 100000而跑起來。因此這時就必須使用網(wǎng)上下載的原始未經(jīng)改動的crt0_ram.S,其實兩個文件的區(qū)別很小,僅在于華恒的版本注釋了復(fù)制romfs的部分代碼:<BR> 只要把uClinux/linux-2.4.x/arch/m68knommu/platform/5272/HHTECH/crt0_ram.S中的一個#if 0 改為#if 1<BR> 下面貼出華恒代碼:<BR> _start:<BR> nop /* Filler */<BR> move.w #0x2700, %sr /* No interrupts */<BR> /*<BR> * Setup VBR here, otherwise buserror remap will not work.<BR> * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)<BR> *<BR> * bkr@cut.de 19990306<BR> *<BR> * Note: this is because dBUG points VBR to ROM, making vectors read<BR> * only, so the bus trap can't be changed. (RS)<BR> */<BR> move.l #VBR_BASE, %a7 /* Note VBR can't be read */<BR> movec %a7, %VBR<BR> move.l %a7, _ramvec /* Set up vector addr */<BR> move.l %a7, _rambase /* Set up base RAM addr */</P><P> /*<BR> * Set to 4 meg for the Cadre III board (m5206e).<BR> */<BR> move.l #MEM_SIZE, %a0</P><P> move.l %a0, %d0 /* Mem end addr is in a0 */<BR> move.l %d0, %sp /* Set up initial stack ptr */<BR> move.l %d0, _ramend /* Set end ram addr */</P><P> #if 1<BR> /*<BR> * Enable CPU internal cache.<BR> */<BR> move.l #0x01000000, %d0 /* Invalidate cache cmd */<BR> movec %d0, %CACR /* Invalidate cache */<BR> move.l #0x80000100, %d0 /* Setup cache mask */<BR> movec %d0, %CACR /* Enable cache */<BR> #endif</P><P> /*<BR> * Move ROM filesystem above bss :-)<BR> */<BR> lea.l _ebss, %a1 /* Set up destination */<BR> move.l %a1, _ramstart /* Set start of ram */<BR> #if 1【這里原來是#if 0,即在華恒版本中被注釋掉了】<BR> lea.l _sbss, %a0 /* Get start of bss */<BR> lea.l _ebss, %a1 /* Set up destination */<BR> move.l %a0, %a2 /* Copy of bss start */<BR> move.l 8(%a0), %d0 /* Get size of ROMFS */<BR> addq.l #8, %d0 /* Allow for rounding */<BR> and.l #0xfffffffc, %d0 /* Whole words */<BR> add.l %d0, %a0 /* Copy from end */<BR> add.l %d0, %a1 /* Copy from end */<BR> move.l %a1, _ramstart /* Set start of ram */<BR> _copy_romfs:<BR> move.l -(%a0), %d0 /* Copy dword */<BR> move.l %d0, -(%a1)<BR> cmp.l %a0, %a2 /* Check if at end */<BR> bne _copy_romfs<BR> #endif<BR> /*<BR> * Zero out the bss region.<BR> */<BR> lea.l _sbss, %a0 /* Get start of bss */<BR> lea.l _ebss, %a1 /* Get end of bss */<BR> clr.l %d0 /* Set value */<BR> _clear_bss:<BR> move.l %d0, (%a0)+ /* Clear each word */<BR> cmp.l %a0, %a1 /* Check if at end */<BR> bne _clear_bss</P><P> /*<BR> * load the current task pointer and stack<BR> */<BR> lea init_task_union, %a0<BR> movel %a0, _current_task<BR> lea 0x2000(%a0), %sp</P><P> /*<BR> * Assember start up done, start code proper.<BR> */<BR> jsr start_kernel /* Start Linux kernel */</P><P> _exit:<BR> jmp _exit /* Should never get here */</P><P> 2 ram.ld也要有修改,<BR> MEMORY {<BR> ram : ORIGIN = 0x100000, LENGTH = 0x6e0000<BR> }<BR> 從網(wǎng)上直接DOWN下來默認的ORIGIN = 0x20000,這樣用我們的bootloader下載下去當然是跑不起來的。以下的SECTIONS 節(jié)不需要任何改動。<BR> 3修改vendors/HHTECH/M5272/Makefile<BR> image:<BR> [ -d $(IMAGEDIR) ] || mkdir -p $(IMAGEDIR)<BR> /usr/local/bin/genromfs -v -V "ROMdisk" -f $(ROMFSIMG) -d $(ROMFSDIR)<BR> m68k-elf-objcopy -O binary $(ROOTDIR)/$(LINUXDIR)/linux $(IMAGEDIR)/linux.bin<BR> #gzip -f $(IMAGEDIR)/linux.bin 【注釋掉】<BR> #cat $(IMAGEDIR)/linux.bin.gz $(ROMFSIMG) > $(IMAGE) 【注釋掉】<BR> cat $(IMAGEDIR)/linux.bin $(ROMFSIMG) > $(IMAGE)<BR> $(ROOTDIR)/tools/cksum -b -o 2 $(IMAGE) >> $(IMAGE)<BR> [ -n "$(NO_BUILD_INTO_TFTPBOOT)" ] || cp $(IMAGE) /tftpboot<BR> #$(MAKE) -C ../../../colilo 【注釋掉】<BR> BSS=`m68k-elf-objdump --headers $(ROOTDIR)/$(LINUXDIR)/linux | grep .bss` ; ADDR=`set -- $${BSS} ; echo 0x$${4}` ; m68k-elf-objcopy --add-section=.romfs=$(ROMFSIMG) --adjust-section-vma=.romfs=$${ADDR} --no-adjust-warnings --set-section-flags=.romfs=alloc,load,data $(ROOTDIR)/$(LINUXDIR)/linux $(ELFIMAGE) 2> /dev/null</P><P> </P><P> 4 修改linux-2.4.x/drivers/block/blkmem.c的第125行開始的幾句,注釋掉defined(CONFIG_HHTECH),修改后代碼如下:</P><P> #ifdef CONFIG_COLDFIRE<BR> #ifdef CONFIG_TELOS<BR> #undef CONFIG_CARDE3<BR> #define CAT_ROMARRAY</P><P> ......</P><P> 其實關(guān)鍵就是去掉CAT_ROMARRAY的定義。</P><P> </P><P> <BR> 31. 2.4 LINUX內(nèi)核大小 </P><P> uClinux/linux-2.4.x/目錄下編譯出來的linux文件有5M多,這是ELF格式的文件,它轉(zhuǎn)換成image.bin時還要用m68k-elf-objcopy工具轉(zhuǎn)換成binary格式的linux.bin,這時它就只有800k了,再壓縮一下就變成300k了。這個工作具體可參見uClinux/vendors/HHTECH/M5272/Makefile。</P><P> <BR> 32. 從SDRAM中劃出一塊不讓LINUX訪問,供自己使用,可作共享內(nèi)存用 </P><P> 對于2.4內(nèi)核修改uClinux/linux-2.4.x/arch/m68knommu/platform/5272/HHTECH/crt0_ram.S(對于2.0ROM版,為uClinux/linux/arch/m68knommu/platform/5272/MOTOROLA/crt0_rom.S),只要修改一處:即文件最前面定義的MEM_SIZE宏,華恒提供的為0x01000000,即16M。用戶若想劃出8M為自己管理使用,只要將這個值改為0x00800000即可。這樣作就是不讓LINUX知道還有這8M地址,這樣OS在分配內(nèi)存的時候就不會用到這些地址空間,相當于從OS那里偷內(nèi)存給自己使用。例如可用于內(nèi)核驅(qū)動和應(yīng)用程序的通信用共享內(nèi)存等。</P><P> </P><P> 33. 關(guān)于通過NFS mount宿主機硬盤調(diào)試應(yīng)用程序的問題 </P><P> 嵌入式LINUX調(diào)試應(yīng)用程序最主要的方式就是通過NFS mount宿主機硬盤上的應(yīng)用程序來執(zhí)行,通過觀察其在串口終端打印的信息來達到調(diào)試的目的。</P><P> 在這個過程中,存在一個權(quán)限的問題,即板子mount宿主機硬盤后,這個NFS mount的操作默認的不是以root的權(quán)限執(zhí)行的,因此一般的板子沒有權(quán)限執(zhí)行宿主機硬盤上的程序,這時就要在宿主機上執(zhí)行chmod 777 app,其中app為應(yīng)用程序可執(zhí)行文件的名字。其實這種現(xiàn)象還是比較容易為開發(fā)人員解決的,因為當執(zhí)行應(yīng)用時,minicom就會報錯,permision denied,或者unknown error 4。但對于有的情況就不一定這么容易看出是權(quán)限的問題:</P><P> 例如:調(diào)試WEB管理軟件cgi代碼時,我們把宿主機上/cgi-bin/通過NFS mount到板子的CGI工作目錄/home/httpd/cgi-bin/上,這時通過瀏覽器IE執(zhí)行CGI操作時,就會報錯403,這里也是一個權(quán)限的問題,即CGI要求其工作目錄可寫,這時就必須在宿主機上執(zhí)行:chmod 777 /cgi-bin,這時瀏覽器里立刻就可以工作了。</P><P> </P><P> 34. 關(guān)于uClinux下線程的使用</P><P> 使用線程是要求uClibc里加入pThread庫編譯。<BR> 這樣就要求make menuconfig時選擇uClibc,而不是華恒默認選擇的uC-libc。<BR> 在uClibc中選擇pThread庫,可以按照以下操作:<BR> 1.cd uClibc<BR> 2.make menuconfig CROSS=m68k-elf-<BR> 3.選上posix thread support選項<BR> 4.cd ..<BR> 5.make clean<BR> 6.make</P><P> 庫選擇好之后,先不必自己編制應(yīng)用程序,uClinux提供了完備的測試程序:即uClinux/user/threaddemos<BR> 你make menuconfig在應(yīng)用程序中選擇這個程序加入編譯,看是否可以編譯通過,通過后執(zhí)行是否正確即可。</P><P> 若編譯有錯誤,可以直接到user/threaddemos目錄下,執(zhí)行:</P><P> m68k-elf-gcc -m5307 -msep-data -Wl,-elf2flt -o bcdm bcdm.c -lpthread -lc</P><P> 可直接生成可執(zhí)行文件bcdm,可直接mount到板子上執(zhí)行。<BR> 【注意】</P><P> 這里要求使用20030314的elf-tools 。</P><P> 華恒客戶可發(fā)信到support@hhcn.com索取相關(guān)測試代碼。</P><P> </P><P> 35. 關(guān)于支持模塊動態(tài)加載(Loadable Module)的問題</P><P> 在make menuconfig中配置內(nèi)核時選擇:Loadable module support ---></P><P> [*] Enable loadable module support ??<BR> [*] Set version information on all module symbols (NEW) ??<BR> [*] Kernel module loader (NEW)<BR> 并在應(yīng)用程序配置中選擇busybox下的insmod/rmmod/lsmod,</P><P> 并選中: [*] Post 2.1 kernel modules。</P><P> </P><P> </P><P> 36. 關(guān)于支持應(yīng)用程序動態(tài)鏈接uClibc的問題 </P><P> 早期的uClinux下的應(yīng)用程序都是采用靜態(tài)鏈接的方式鏈接uClibc/uC-libc,現(xiàn)在uClinux早就已經(jīng)可以支持動態(tài)鏈接uClibc庫了。動態(tài)鏈接的好處是可以實現(xiàn)多個應(yīng)用程序?qū)崿F(xiàn)代碼共享,從而可以節(jié)省內(nèi)存消耗,就相當于WINDOWS下的DLL所引入的共享優(yōu)勢。</P><P> 動態(tài)鏈接在NOMMU處理器上的實現(xiàn)采用了XIP(execute in place)代碼。</P><P> 詳細分析參見:</P><P> <img align=absmiddle src=pic/url.gif border=0><a target=_blank href=http://mailman.uclinux.org/pipermail/uclinux-dev/2002-April/007786.html> http://mailman.uclinux.org/pipermail/uclinux-dev/2002-April/007786.html</a></P><P> </P><P> 37. 關(guān)于最新的20030314 elf toolschain </P><P> 參見:<img align=absmiddle src=pic/url.gif border=0><a target=_blank href=http://www.uclinux.org/pub/uClinux/m68k-elf-tools/> http://www.uclinux.org/pub/uClinux/m68k-elf-tools/</a></P><P> 下載m68k-elf-tools-20030314.sh到LINUX PC機上,chmod 777 m68k-elf-tools-20030314.sh,然后./m68k-elf-tools-20030314.sh則直接將最新的m68k-elf-xxx工具集合安裝到/usr/local/下面,可以直接使用。</P><P> </P><P> 38. 執(zhí)行我的應(yīng)用程序時報錯:BINFMT_FLAT: bad magic/rev (0x1010100, need 0x4)</P><P> 例如:mount宿主機上的nmbd,在minicom下執(zhí)行/mnt/nmbd&,出現(xiàn)如下錯誤:</P><P> BINFMT_FLAT: bad magic/rev (0x1010100, need 0x4)<BR> BINFMT_FLAT: bad magic/rev (0x1010100, need 0x4)<BR> /mnt/nmbd: Exec format error<BR> 這是因為這個應(yīng)用程序沒有使用交叉編譯工具編譯,而是用了PC LINUX下的gcc編譯出來的。造成這種問題的經(jīng)常是由于客戶不是在uClinux目錄下執(zhí)行make統(tǒng)一進行編譯,而是直接到該應(yīng)用程序目錄下執(zhí)行make所致。這是由于uClinux/user/下每個應(yīng)用程序的Makefile中使用了許多宏,列入CC等,這些宏都是統(tǒng)一在uClinux下的一個目錄下的文件中定義的,若用戶直接到user/下的應(yīng)用程序目錄下執(zhí)行make,則這些宏就無法獲取uClinux為其設(shè)定的值,而是自動采用PC LINUX系統(tǒng)默認的,例如CC若用戶不指定,默認的就是gcc,所以應(yīng)用程序就沒有用m68k-elf-gcc編譯,而是用PC LINUX下的gcc編譯的,這樣編出來的可執(zhí)行文件在板子上當然是無法執(zhí)行的了。</P><P> </P><P> 39. 關(guān)于關(guān)閉shell,使能串口通信</P><P> 鑒于我們提供的版本不斷的升級,所以針對不同版本的方法略有區(qū)別,下面一共提供兩種方法:<BR> 方法一<BR> 1.修改uClinux/linux-2.4.x/init/main.c<BR> - if (open("/dev/ttyS0", O_RDWR, 0) < 0)<BR> + if (open("/dev/null", O_RDWR, 0) < 0)<BR> 修改以后啟動過程中printk內(nèi)容仍會打印,printf內(nèi)容如rc內(nèi)步驟不會打印。</P><P> 2.同時最好在user/init/simpleinit.c中不要啟動/bin/sh,具體操作是:</P><P> /* Fake an inittab entry if boot console defined */<BR> #ifdef CONFIG_USER_INIT_CONSOLE_SH<BR> #if LINUX_VERSION_CODE < 0x020100<BR> if (console_device && strcmp(console_device, "/dev/null"))<BR> #else<BR> if (have_console)<BR> #endif<BR> /*{ 【就是注釋掉這一段代碼。。!】<BR> struct initline *p;<BR> p = inittab + numcmd++;<BR> init_itab(p);<BR> strcpy(p->fullline, "console");<BR> strcpy(p->tty, "console");<BR> strcpy(p->termcap, "linux");<BR> p->toks[0] = "/bin/sh";<BR> } */<BR> #endif<BR> **************************************************************************************<BR> 方法二<BR> 【這是最新的測試結(jié)果】<BR> 通常不能使用COM1進行串口通信的原因是它已被重定向為標準輸入輸出,系統(tǒng)的shell進程將對其監(jiān)視并處理從此處發(fā)送進來的數(shù)據(jù),而不能被用戶程序所得到。<BR> 解決辦法我認為有兩種,一是不把Com1口重定向為標準輸入輸出,二是在標準輸入輸出上不啟動shell。第一種沒有試過,第二種可以按下面方法修改。<BR> ü uC的版本很多,好像有一種是在uClinux/linux-2.4.x/init/main.c中啟動shell,該代碼在do_shell函數(shù)中,檢查main.c文件,如果有該函數(shù),把<BR> if(open("/dev/ttyS0",O_RDWR,0)<0)<BR> 改為<BR> if(open("/dev/null",O_RDWR,0)<0)<BR> 沒有就算了。<BR> ü 在uClinux/user/init/simpleinit.c中注掉read_inittab函數(shù)中下面HHTECH部分的內(nèi)容:<BR> void read_inittab(void)<BR> {<BR> numcmd = 0;<BR> /* Fake an inittab entry if boot console defined */<BR> #ifdef CONFIG_USER_INIT_CONSOLE_SH<BR> #if LINUX_VERSION_CODE < 0x020100<BR> if (console_device && strcmp(console_device, "/dev/null"))<BR> #else<BR> if (have_console)<BR> #endif<BR> /*HHTECH<BR> {<BR> struct initline *p;<BR> p = inittab + numcmd++;<BR> init_itab(p);<BR> strcpy(p->fullline, "console");<BR> strcpy(p->tty, "console");<BR> strcpy(p->termcap, "linux");<BR> strcpy(p->termcap, "linux");<BR> p->toks[0] = "/bin/sh";<BR> }<BR> */<BR> #endif<BR> read_initfile(_PATH_INITTAB);<BR> #ifdef CONFIG_USER_FLATFSD_FLATFSD<BR> read_initfile(_PATH_CONFIGTAB);<BR> #endif<BR> if (numcmd == 0)<BR> _exit(1);<BR> }</P><P> 注意:<BR> 這樣并不是說就永遠不會啟動shell了,只是在標準輸出上不啟動shell,但若用戶telnet板子還是仍然會在p0口上啟動shell的,否則用戶就永遠無法向板子發(fā)布command命令了。</P><P> <BR> </P><P> 40. 關(guān)于malloc使用問題</P><P> 在HHCF5272-R2的uClinux下測試, malloc最大空間約為2,048,000<BR> 設(shè)為2,100,000時,出現(xiàn):<BR> kernel panic : BUG!<BR> 另:realloc結(jié)果同malloc一樣,大小上沒有區(qū)別;在內(nèi)核中使用kmalloc,大小亦相同。</P><P> </P><P> 41.MFC5272-16com 開發(fā)板串口波特率設(shè)置?</P><P> #define SETBAUDRATE 0xe021<BR> #define SETBUFFER 0xe022<BR> #define SETFORMAT 0xe023<BR> 對串口波特率修改為<BR> ioctl(spfd,SETBAUDRATE,4);</P><P> </P><P> 波特率表</P><P> </P><P> <BR> char hh_mcf5272_baud_table[10][2] = {<BR> { 0x80, 0x01 }, /* 1200 300 *///0<BR> { 0xc0, 0x00 }, /* 2400 600 *///1<BR> { 0x60, 0x00 }, /* 4800 1200 *///2<BR> { 0x30, 0x00 }, /* 9600 2400 *///3<BR> { 0x18, 0x00 }, /* 19.2K 4800 *///4<BR> { 0x0c, 0x00 }, /* 38.4K 9600 *///5<BR> { 0x06, 0x00 }, /* 76.8K 19K *///6<BR> { 0x03, 0x00 }, /* 153.6K 38k *///7<BR> { 0x02, 0x00 }, /* 230.4K 56k *///8<BR> { 0x01, 0x00 } /* 460.8K 115k *///9<BR> };</P><P> 4就對應(yīng)上表的19200,默認串口波特率為19200</P><P> 對串口傳輸格式修改<BR> ioctl(spfd,SETFORMAT,"8n1");</P><P> 默認為8n1</P><P> </P><P> 42.關(guān)于CGI</P><P> CGI是一種WEB SERVER端擴展代碼。例如IIS端的ISAPI等開發(fā)的DLL代碼都是WINDOWS上的WEB SERVER端的擴展,用于處理用戶通過WEB瀏覽器的表單輸入等靜態(tài)頁面以外的智能輸入處理。<BR> CGI可用于WINDOWS和LINUX上的WEB SERVER端擴展,可用各種腳本如PHP等實現(xiàn),最原始的就是用C代碼實現(xiàn)的,具體用什么代碼要看你的WEB SERVER是否支持。對于嵌入式LINUX采用的boa這個WEB SERVER而言,就不支持任何的腳本,只支持C代碼的CGI程序,每連接一個客戶端瀏覽器連接就在SERVER端(板子上)啟動一個CGI進程的COPY。</P><P> <BR> 43.在REDHAT 9.0環(huán)境下使用BDM時,提示“DEVICE BUSY”,是并口被占用?</P><P> 請在您的REDHAT9機器上執(zhí)行如下命令<BR> rmmod lp<BR> rmmod parport_pc<BR> rmmod parport<BR> 這時您再執(zhí)行./chk就沒有問題了。</P><P> <BR> 44.xxx函數(shù)或者結(jié)構(gòu)體是在哪里定義的等類似的問題。</P><P> 在LINUX這種開源的環(huán)境下工作,最重要的不是你己經(jīng)掌握了多少知識,而是要掌握獲取信息的手段,源代碼都有,所有的知識都在那個uClinux的目錄下,不需要任何的書籍,只有有搜索和查找的工具就可以獲取任何需要的知識,搞開發(fā)就像學(xué)語言,模仿是非常有效的手段,看系統(tǒng)中運行的代碼是怎么寫的,仿照著做就是了。<BR> 搜索和查找的手段就兩個:<BR> 一個是在所有文件中搜索字符串:<BR> grep xxx * -r<BR> 另一個是搜索文件:<BR> find -name xxx.c<BR> 還有,可在uClinux目錄下(其實任何目錄都可以,只是作用范圍小些)用:<BR> ctags -R .<BR> 這樣在vi中閱讀代碼時可用ctrl+]跳轉(zhuǎn)到想要查詢的函數(shù)/結(jié)構(gòu)定義處;用ctrl+T返回。</P><P> </P><P> 45.關(guān)于uClinux浮點支持<BR> 1.從/uClinux/lib/libm復(fù)制gcvt.c和mathf.h到/uClinux/lib/libc/stdio2<BR> 2.修改/uClinux/lib/libc/stidio2/Makefile<BR> 2a.增加gcvt.o編譯項到<BR> OBJ= $(AOBJ) $(POBJ) $(SOBJ) dputs.o snprintf.o getdelim.o getline.o <BR> gcvt.o<BR> ~~~~~~添加項<BR> 2b.添加編譯參數(shù)-DFLOATS=1到all: $(LIBC) $(OBJ)前面<BR> 3.可增加make clean相關(guān)項<BR> Makefile文件如下:</P><P> # Copyright (C) 1995,1996 Robert de Bath <BR> # This file is part of the Linux-8086 C library and is distributed<BR> # under the GNU Library General Public License.</P><P> LIBC=../libc.a<BR> ASRC=stdio.c<BR> AOBJ=_stdio_init.o fputc.o fgetc.o fflush.o fgets.o gets.o fputs.o puts.o fread.o fwrite.o fopen.o fclose.o fseek.o rewind.o ftell.o setbuffer.o setvbuf.o ungetc.o</P><P> PSRC=printf.c<BR> POBJ=printf.o sprintf.o fprintf.o snprintf.o vprintf.o vsprintf.o vfprintf.o vfnprintf.o vsnprintf.o</P><P> SSRC=scanf.c<BR> SOBJ=scanf.o sscanf.o fscanf.o vscanf.o vsscanf.o vfscanf.o</P><P> OBJ= $(AOBJ) $(POBJ) $(SOBJ) dputs.o getdelim.o getline.o gcvt.o<BR> CFLAGS += -DFLOATS=1<BR> all: $(LIBC) $(OBJ)<BR> #@$(RM) $(OBJ)</P><P> $(LIBC): $(LIBC)($(OBJ))</P><P> $(LIBC)($(AOBJ)): $(ASRC)<BR> $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o<BR> $(AR) $(ARFLAGS) $@ $*.o</P><P> $(LIBC)($(POBJ)): $(PSRC)<BR> $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o<BR> $(AR) $(ARFLAGS) $@ $*.o</P><P> $(LIBC)($(SOBJ)): $(SSRC)<BR> $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o<BR> $(AR) $(ARFLAGS) $@ $*.o</P><P> transfer:<BR> -@rm -f ../include/stdio.h<BR> cp -p stdio.h ../include/.</P><P> clean:<BR> rm -f *.o libc.a</P><P> $(LIBC)($(OBJ)): stdio.h<BR> <BR>
|
|
狀 態(tài):
離線
公司簡介
產(chǎn)品目錄
|
|
公司名稱:
|
華恒公司
|
聯(lián) 系 人: |
市場部
|
電 話: |
0551-5325652
|
傳 真: |
0551-5325323 |
地 址: |
合肥市長江西路669 號高新技術(shù)產(chǎn)業(yè)開發(fā)區(qū)軟件園四號樓204-206華恒科技 |
郵 編: |
230088 |
主 頁: |
|
|
|
|
|