華恒COLDFIRE系列嵌入式LINUX開發(fā)套件常見(jiàn)問(wèn)題解答
華恒公司
|
|
華恒COLDFIRE系列嵌入式LINUX開發(fā)套件常見(jiàn)問(wèn)題解答<BR> ---基于公用核心板HHCF5272-K1(華恒公司版權(quán)所有)</P><P> --------------------------------------------------------------------------------<BR> <BR> 1. 關(guān)于宿主機(jī)LINUX的安裝 </P><P> 建議使用REDHAT系列:建議選擇完全安裝,即選擇Custom,然后在Package中選擇everything。</P><P> <BR> 【以下配置詳見(jiàn)最新PDF手冊(cè)下載(例如:HHCO5272-R1的手冊(cè))】<BR> 宿主機(jī)的網(wǎng)絡(luò)配置</P><P> 主要是要安裝好以太網(wǎng)卡,對(duì)于一般常見(jiàn)的RTL8139網(wǎng)卡,REDHAT7.2可以自動(dòng)識(shí)別并自動(dòng)安裝好,完全不要用戶參與,因此建議使用該網(wǎng)卡。然后配置宿主機(jī)IP:<BR> ifconfig eth0 192.168.2.32<BR> 【注意】<BR> 對(duì)于REDHAT7.2,它默認(rèn)的是打開了防火墻,因此對(duì)于外來(lái)的IP訪問(wèn)它全部拒絕,這樣其它網(wǎng)絡(luò)設(shè)備根本無(wú)法訪問(wèn)它,即無(wú)法用NFS mount它,無(wú)法通過(guò)TFTP從它下載,無(wú)法telnet,ftp它等。因此網(wǎng)絡(luò)安裝完畢后,應(yīng)立即關(guān)閉防火墻。操作如下:<BR> 運(yùn)行setup,選擇Firewall configuration,選中No firewall。然后到上一層菜單選擇System services,去掉ipchains和iptables兩項(xiàng)服務(wù)。最后退出setup。</P><P> 其實(shí),在安裝REDHAT7.2/3時(shí),就要求選擇Custom定制安裝,其中由一項(xiàng)就是要求選擇No Firewall,這樣的話,啟動(dòng)后,就不需要執(zhí)行setup來(lái)設(shè)置防火墻了。還有,REDHAT在這里有個(gè)BUG,即無(wú)論上次你進(jìn)入Firewall configuration選擇什么,每次再次進(jìn)入時(shí)它都顯示High,這是REDHAT顯示的BUG,其實(shí)防火墻已經(jīng)關(guān)閉了。</P><P> 配置NFS</P><P> 運(yùn)行l(wèi)inuxconf,在config選項(xiàng)下選Server tasks,選中Exported File systems(NFS),然后選擇Add Directory,加入根目錄/,然后Accept。系統(tǒng)就會(huì)輸出根目錄允許NFS mount。<BR> 下一步再選擇Control項(xiàng)下面Control panel下的Control Service activity,然后選擇nfs enabled,然后start。配置好后的界面顯示其中nfs必須為: Automatic Running。<BR> 【注意】<BR> 這里建議把ipchains和iptables都取消其自動(dòng)啟動(dòng)的狀態(tài)。<BR> 最后,在Control項(xiàng)下面Control panel下選擇Activate configuration,則彈出界面,提示系統(tǒng)配置的改動(dòng),選擇"Do it",最后退出時(shí)則完成NFS配置。<BR> 配置完成后,可用如下辦法簡(jiǎn)單測(cè)試一下NFS是否配置好了:<BR> 在宿主機(jī)上自己mount自己,看是否成功就可以判斷NFS是否配好了。例如在宿主機(jī)/目錄下執(zhí)行:<BR> mount 192.168.2.32:/ /mnt<BR> 然后到/mnt/目錄下看是否可以列出/目錄下的所有文件和目錄,可以則說(shuō)明mount成功,NFS配置成功。 <BR> 配置TFTP服務(wù)器</P><P> 參見(jiàn)下面第二點(diǎn)介紹。<BR> 【注意】</P><P> 安裝完華恒uClinux軟件光盤后,不要make xconfig,直接make即可。加入驅(qū)動(dòng)等修改內(nèi)核的操作都不必make xconfig,除非要更改處理器平臺(tái),例如移植到MCF5407等才需要make xconfig。其實(shí)這個(gè)操作不過(guò)就是修改linux/.config和linux/include/linux/autoconfig.h中的宏設(shè)置。完全可以由手工完成。</P><P> 2. 關(guān)于gdbtftpflash燒寫<BR> 【注意】</P><P> 燒寫必須接百兆以太網(wǎng)接口,對(duì)于多以太網(wǎng)板的10M口是不能用來(lái)燒寫的。</P><P> <BR> 在一個(gè)LINUX TTY終端執(zhí)行<BR> ./flash<BR> 然后立刻切換到另一個(gè)TTY終端啟動(dòng)的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)鍵所在,前面的信息都無(wú)用,只要這里讀到的字節(jié)數(shù)和宿主機(jī)上/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信息才表示燒寫進(jìn)去了,前面<BR> ********** Sector 0 [FFC00000] (0-unprotect, 1 protect):0等只是顯示FLASH的扇區(qū)分布,<BR> 并沒(méi)有進(jìn)行燒寫,只有看到Read Fill Erase Program End信息才表示在進(jìn)行燒寫。</P><P> 在minicom中用ctrl+a,然后按b,接著用上下箭頭,可以翻看前面的信息,從而查看出了什么錯(cuò)誤。例如,TFTP連接失敗的信息就要前翻來(lái)查看,信息如下:<BR> Unable to locate 192.168.1.46<BR> Errors in TFTP download.<BR> Read 0 bytes (0 blocks)<BR> 這就要查看宿主機(jī)(即TFTP服務(wù)器配置是否成功)。</P><P> 工作機(jī)制:<BR> ./flash調(diào)用hhco.gdb腳本對(duì)CPU進(jìn)行初始化,(sys-init)<BR> 然后指定<BR> target bdm /dev/bdmcf0<BR> load 即下載一個(gè)小軟件(tftp.elf,約80K)到板子的RAM中,并用c(continue)命令讓它跑起來(lái),這時(shí)CPU完全由這個(gè)小軟件接管。這個(gè)小軟件跑起來(lái)后初始化以太網(wǎng)及TFTP協(xié)議棧,然后它運(yùn)行TFTP客戶端,從內(nèi)存中0x00200004(2M+4處)讀取gdb腳本放在此處的TFTP服務(wù)器IP地址,并從該IP的TFTP服務(wù)器PC下載image.bin到板子內(nèi)存1M地址處,再將其燒寫到FLASH上,重啟板子,這時(shí)引導(dǎo)起來(lái)的就是LINUX了。</P><P> <BR> 問(wèn):燒寫時(shí)顯示如下信息,但minicom端什么信息也沒(méi)有打印出來(lái),而且板子仍然在運(yùn)行,運(yùn)行指示仍然正常閃爍?<BR> 在執(zhí)行./flash的TTY一側(cè),會(huì)顯示:<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ū)動(dòng)(linux-bdm.o)的問(wèn)題,必須安裝正確的驅(qū)動(dòng)(例如華恒光盤提供的)。按CTRL+C結(jié)束該進(jìn)程,用rmmod linux-bdm刪除當(dāng)前的驅(qū)動(dòng),用insmod安裝正確版本的驅(qū)動(dòng)再重新執(zhí)行./flash即可。</P><P> <BR> 問(wèn):燒寫完畢后最后會(huì)報(bào)如下錯(cuò)誤:<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> 注意上述信息并非錯(cuò)誤,燒寫完退出時(shí)都要顯示這個(gè)信息,并不能表示燒寫是否成功。燒寫成功與否完全要看minicom端的顯示信息來(lái)判斷。</P><P> <BR> 問(wèn):運(yùn)行./flash時(shí)報(bào)錯(cuò),內(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> 答:這是由于宿主機(jī)REDHAT安裝時(shí)不完全,不支持DEVELOPMENT工具,如gcc,gdb等工具,導(dǎo)致系統(tǒng)沒(méi)有安裝運(yùn)行這些工具所需的共享庫(kù)。建議重新完全安裝系統(tǒng)。</P><P> <BR> 3. 關(guān)于TFTP服務(wù)器設(shè)置<BR> 其實(shí)TFTP服務(wù)器可以是和板子相連的局域網(wǎng)內(nèi)任意一臺(tái)開通了TFTP服務(wù)的LINUX PC機(jī),即板子可以從任意一臺(tái)TFTP服務(wù)器下載IMAGE文件并進(jìn)行燒寫,當(dāng)然首先要檢查IP是否匹配及連線是否正確。但若將LINUX宿主機(jī)(即用串口線連接的那一臺(tái)LINUX PC)同時(shí)開通TFTP服務(wù),這樣就不必占用多臺(tái)機(jī)器。默認(rèn)完全安裝后的REDHAT的TFTP服務(wù)是沒(méi)有開通的,要自己手工開通。</P><P> 開通宿主機(jī)上的TFTP服務(wù),對(duì)于REDHAT6.x,可以在宿主機(jī)上:<BR> vim /etc/inetd.conf<BR> 查找tftp,若發(fā)現(xiàn)前面有#就表示這一行被注釋掉了,即服務(wù)沒(méi)有打開,去掉#就打開了TFTP服務(wù),然后重啟宿主機(jī)即可。<BR> 對(duì)于REDHAT7.2,則在宿主機(jī)上執(zhí)行setup,選擇System services,將其中的tftp一項(xiàng)選中(出現(xiàn) [*]表示選中),并去掉ipchains和iptables兩項(xiàng)服務(wù)(即去掉它們前面的*號(hào))。然后還要選擇Firewall configuration,選中No firewall。最后,退出setup,執(zhí)行如下命令以啟動(dòng)TFTP服務(wù):<BR> service xinetd restart<BR> 配置完成后,建議簡(jiǎn)單測(cè)試一下TFTP服務(wù)器是否可用,即自己tftp自己,例如在宿主機(jī)上執(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ù)器配置成功了。若彈出信息說(shuō):Timed out,則表明未成功,需要按照上述步驟重新檢查一遍。<BR> 或者用如下命令查看tftp服務(wù)是否開通:<BR> netstat -a|grep tftp<BR> 完成上述配置工作后,就可以開始使用該以太網(wǎng)燒寫工具了。</P><P> <BR> 4. BDM與重啟問(wèn)題<BR> 安裝bdm驅(qū)動(dòng)模塊,以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啟動(dòng)都會(huì)自動(dòng)執(zhí)行,否則每次啟動(dòng)宿主機(jī)都要執(zhí)行這一句】<BR> 3. ./MAKEDEV 【在/dev/下創(chuàng)建設(shè)備bdmcf0,只要執(zhí)行一次】<BR> 【注意】<BR> 在insmod時(shí)有可能出現(xiàn).o文件與內(nèi)核版本不匹配現(xiàn)象,這時(shí)只要重編該模塊驅(qū)動(dòng)即可。具體請(qǐng)參閱下面第31條。</P><P> 還有,BDM線的長(zhǎng)度不能加長(zhǎng),否則使用時(shí)會(huì)報(bào)"bdm not open"。</P><P> <BR> 問(wèn):板子剛拿到,一加電就不啟動(dòng),運(yùn)行指示燈不閃,minicom什么信息也沒(méi)有,怎么回事?<BR> 答:這是因?yàn)椴辶薆DM卡,若不插BDM卡,板子就可以正常啟動(dòng)了。</P><P> 從軟件使用者的角度來(lái)說(shuō),插了BDM后,核心板的reset鍵就失效,所以板子加電后沒(méi)有收到reset信號(hào),所以板子不能啟動(dòng)。這時(shí)要板子讓板子上的軟件系統(tǒng)啟動(dòng)運(yùn)行,可以先執(zhí)行一下chk,然后立刻退出則板子就會(huì)自動(dòng)重啟。<BR> cd chk<BR> ./chk<BR> >>>x<BR> 當(dāng)板子啟動(dòng)后,可以通過(guò)minicom接收命令,則要重啟就直接在minicom下鍵入reboot即可重啟,這時(shí)按reset鍵無(wú)效。若不插BDM則板子的reset按鍵是有效的。</P><P> <BR> 有時(shí),執(zhí)行chk時(shí)報(bào)錯(cuò):</P><P> device busy表示有其它程序在使用BDM<BR> 用ps -A<BR> 看看是否有其它程序在使用BDM,例如gdb(即gdbtftpflash下的./flash)或者chk,</P><P> 若提示device not found,則表明沒(méi)有安裝驅(qū)動(dòng)linux-bdm.o</P><P> 5. 板子死了?<BR> 判斷板子是否死機(jī)的標(biāo)準(zhǔn)不是minicom是否可以輸入等,最可信的標(biāo)準(zhǔn)就是看核心板上的運(yùn)行指示燈是否還正常的閃爍,若不再閃了,必死無(wú)疑。有時(shí)串口可以打印輸出信息,但用戶卻無(wú)法輸入命令,這經(jīng)常是由于操作者手上靜電太高導(dǎo)致串口工作異常。這時(shí)建議給板子斷電,把核心板和底板以及串口線等都重新拔插一下再加電重啟試試;或者換一臺(tái)PC,或者用telnet使用網(wǎng)絡(luò)終端。</P><P> 6. TFTP下載與RAM版本問(wèn)題<BR> 用bootloader下載RAM內(nèi)核,總是報(bào)錯(cuò):</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> 因?yàn)門FTP采用的是udp傳輸?shù)模?lt;BR> 而我們的板子是通過(guò)一個(gè)小HUB跟局域網(wǎng)聯(lián)在一起的,<BR> 可能在傳輸中有些包丟失了,或者是在傳輸中有些<BR> 數(shù)據(jù)出現(xiàn)錯(cuò)誤,因此出現(xiàn)RAM版的不能用。后來(lái)單獨(dú)把板子跟一臺(tái)計(jì)算機(jī)的網(wǎng)卡相連,</P><P> 或者都接到同一個(gè)HUB上,就不會(huì)有問(wèn)題了。</P><P> <BR> 有時(shí)燒寫完后板子啟動(dòng)時(shí)回出現(xiàn)如下錯(cuò)誤:<BR> Unable to open an initial console.</P><P> 這種現(xiàn)象有多種原因可能導(dǎo)致出現(xiàn),其中就有可能是這里所提的燒寫錯(cuò)誤所致。</P><P> 7. BUSS ERROR的問(wèn)題<BR> 記住出錯(cuò)時(shí)打印出的PC指針值,將linux/linux<BR> 用m68k-elf-objdump -D linux >tt<BR> vim tt<BR> 反匯編后查看該P(yáng)C地址處在什么函數(shù)調(diào)用內(nèi),<BR> 從而作進(jìn)一步定位。</P><P> <BR> 用chk單步跟蹤,(fp命令)<BR> 建議閱讀chk源代碼,可以根據(jù)自己的需要定制自己的調(diào)試命令。<BR> 所有可用的BDM操作都在bdm/下的一個(gè)bdm.h文件中。</P><P> 8. 硬件擴(kuò)展<BR> 問(wèn):CN5的復(fù)用腳p19,p23,p25是系統(tǒng)寬度總線控制信號(hào),留給 用戶,系統(tǒng)沒(méi)有用嗎?那么復(fù)位期間如何確定總線寬度?<BR> 回答:上電的時(shí)候作為系統(tǒng)寬度總線控制信號(hào);但是上電結(jié)束開始運(yùn)行之后,就變成SPI信號(hào)線了,您可以使用。</P><P> 問(wèn):普通usb口只用d+ d_兩條信號(hào)線,而5272增加了轉(zhuǎn)出去的信號(hào)線:usb-rp,usb-tp....(pa{6:0}),用戶能否用其第一功能?<BR> 回答:5272本身帶有usb收發(fā)器,5272可以讓您選擇是否選擇外部usb收發(fā)器(通過(guò)配置內(nèi)部寄存器來(lái)選擇)。建議選用外部USB收發(fā)器。注意!是收發(fā)器,不是控制器!USB控制器是在5272里面的。<BR> 【注】cn5,cn6只是做簡(jiǎn)單的擴(kuò)展,而你可以通過(guò)自己設(shè)計(jì)底板(華恒底板都已經(jīng)在手冊(cè)里面有原理圖了。瑥亩赾n1,cn2,cn3使用信號(hào)。cn1,cn2,cn3上的管腳對(duì)應(yīng)的信號(hào)原理圖上都有。其中地址線在cn1的1~45(奇數(shù)腳),數(shù)據(jù)線在cn2的2~64(偶數(shù)腳)。ddat[3:0]和DTEA都在cn3上,是用于接BDM口的。具體使用請(qǐng)參考5272處理器手冊(cè)。<BR> USB[3:1]管腳是從一個(gè)外接的USB收發(fā)芯片pdiusb11上接出的。而TX_P~RX_N是以太網(wǎng)隔離變壓器的輸出線。cpuclk的頻率為66Mhz,無(wú)驅(qū)動(dòng)。 </P><P> </P><P> 關(guān)于系統(tǒng)I/O:</P><P> MCF5272共提供48個(gè)通用IO引腳,它們可以分為3個(gè)16位PORT,即PORTA、PORTB、PORTC。其中PORTA,PORTB對(duì)應(yīng)的控制寄存器來(lái)實(shí)現(xiàn)與其它信號(hào)引腳的復(fù)用。Port C沒(méi)有PCCNT寄存器,它只能在工作為外總線16位模式時(shí)作為16位的I/O口線使用,即它與D[0~15]復(fù)用,只有16位外總線模式時(shí),因?yàn)橹挥酶?6位D[16~31],這時(shí)D[0~15]就為PC[0~15]。另外的一個(gè)端口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> 若整個(gè)去掉串口0,又多兩根,即最多21+2=23根。</P><P> 9.串口2檢測(cè)<BR> 將板子的串口2和宿主機(jī)的串口1連接起來(lái),在宿主機(jī)的一個(gè)TTY啟動(dòng)minicom,另一個(gè)TTY執(zhí)行chk<BR> ./chk<BR> >>>fr colilo2.bin e00000 【下載到RAM中0x00e00000地址處】<BR> >>>fg xx e00400 【從0x00e00400地址處開始執(zhí)行,加上0x400是要跳過(guò)前面1024個(gè)字節(jié)的ramvect】<BR> 代碼下到板子RAM中,然后用fg將其激活跑起來(lái)后,CPU就由那個(gè)代碼控制了,這時(shí)就不要在chk中輸入任何命令了。不要在chk中執(zhí)行退出(x),否則板子立即reset,下載到RAM中的內(nèi)容就丟了。【注意】沒(méi)有fg之前,核心板上運(yùn)行指示燈(LEDK1)是不亮不閃的。一旦fg xx e00400后就應(yīng)該亮閃起來(lái)。這是判斷下載軟件是否跑起來(lái)的唯一標(biāo)準(zhǔn),與串口是否打印完全無(wú)關(guān)。若minicom沒(méi)有打印信息,就只能說(shuō)明串口2是壞的。</P><P> </P><P> 10. 開發(fā)/使用注意<BR> ◇無(wú)論編譯內(nèi)核還是自己的某一個(gè)應(yīng)用程序都必須在uClinux目錄下進(jìn)行編譯make,在其它目錄下編譯都會(huì)報(bào)錯(cuò)。</P><P> ◇當(dāng)板子插了網(wǎng)線時(shí),核心板上的百兆以太網(wǎng)連接和碰撞指示燈(LEDL2)就會(huì)亮起來(lái),若這時(shí)板子ping一臺(tái)PC機(jī)或者一臺(tái)PC機(jī)ping板子的話,LEDL2燈就會(huì)閃爍起來(lái)。若LEDL2不亮,可能是以太網(wǎng)插口接觸不好所致,用力插緊即可。<BR> ◇HHCO5272-R1提供了串口2可用于作MODEM撥號(hào),需要把uClinux/user/pppd/、chat/和diald/三個(gè)目錄加入編譯,并編寫正確的撥號(hào)腳本和配置文件。華恒提供完備的PPP撥號(hào)軟件包。<BR> ◇HHCO5272-R1板上采用的是ROMFS的文件系統(tǒng),它是只讀的?梢詳U(kuò)展支持JFFS/JFFS2文件系統(tǒng),它可讀可寫。華恒提供完備的JFFS/JFFS2支持軟件包。</P><P> ◇在用ddd-5272調(diào)試應(yīng)用程序時(shí),若看不到代碼,是因?yàn)闆](méi)有加-g的編譯參數(shù);若代碼能看到,但是是在run的時(shí)候提示BDM not Open! 這是run命令的問(wèn)題,運(yùn)行時(shí)不要用run,而用continue命令,即c。</P><P> ◇MCF5272不支持外設(shè)的DMA,它只有內(nèi)部DMA,為FEC所用。</P><P> ◇要在系統(tǒng)啟動(dòng)時(shí)自動(dòng)執(zhí)行用戶自己的應(yīng)用程序,就必須修改uClinux/romfs/etc/rc文件,這是個(gè)啟動(dòng)的腳本文件,它的作用就相當(dāng)于WINDOWS98下的autoexec.bat,這個(gè)腳本文件中的每一句都是在shell下可直接執(zhí)行的命令。例如用戶移植了WEB SERVER boa,要啟動(dòng)就執(zhí)行boa,就在這個(gè)rc文件的最后加一句boa&,然后到uClinux下執(zhí)行make,然后./flash燒寫板子即可。</P><P> ◇板子IP的修改:</P><P> 可以用ifconfig/route(2.4內(nèi)核不需要route命令)命令來(lái)修改板子啟動(dòng)后的IP,但這個(gè)修改在重啟后無(wú)法保存。因?yàn)榘遄覫P的指定是在其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,就要在宿主機(jī)上修改uClinux/romfs/etc/rc文件中對(duì)應(yīng)的IP設(shè)置內(nèi)容,然后在uClinux下重新編譯,然后重新燒寫。但這樣做的問(wèn)題在于無(wú)法做到動(dòng)態(tài)修改IP并保存。要實(shí)現(xiàn)這種功能,就必須在板子上實(shí)現(xiàn)文件存儲(chǔ)功能。實(shí)現(xiàn)的機(jī)制有許多,如flatfsd、JFFS/JFFS2文件系統(tǒng)等。對(duì)于板子上的存儲(chǔ)機(jī)制,華恒提供完整的JFFS/JFFS2軟件包銷售,可大大加快用戶的開發(fā)進(jìn)度及產(chǎn)品上市時(shí)間。</P><P> 11. 啟動(dòng)失敗 </P><P> 客戶問(wèn):HHCF5272-LCD-IDE-R1套件中:把image.bin寫到flash后,應(yīng)該可以從板子啟動(dòng)進(jìn)入uClinux中,但是它會(huì)出現(xiàn)一個(gè)錯(cuò)誤是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一行,然后重新編譯燒寫就沒(méi)有問(wèn)題了。</P><P> </P><P> 12. 串口2問(wèn)題 </P><P> ◇客戶問(wèn):</P><P> 一個(gè)簡(jiǎn)單測(cè)試程序,向/dev/ttyS0發(fā)送數(shù)據(jù),波特率設(shè)為38400,在PC機(jī)下順利接收到。利用5272開發(fā)板上的串口1發(fā)送,另一端在minicom下,設(shè)為相同的波特率,能接收到數(shù)據(jù),但是相同的程序,只修改為/dev/ttyS1確收不到任何數(shù)據(jù),<BR> 答復(fù):經(jīng)次測(cè)試,發(fā)現(xiàn)是缺少了對(duì)串口2占用的PD口的初始化。<BR> 對(duì)于HHCF5272-R1,更新的文件sysinit.c,<BR> 將它覆蓋到uClinux/linux/arch/m68knommu/platform/5272/目錄下,<BR> 重新編譯燒寫即可。<BR> 對(duì)于HHCF5272-LCD-IDE-R1 ,將附件colilo.bin覆蓋到uClinux/colilo/目錄下,重新編譯燒寫即可。 </P><P> <BR> 13. 擴(kuò)大RAM盤的方法<BR> 有客戶問(wèn)到增大HHCF5272-R1板子上的/var/目錄大小的問(wèn)題,<BR> 這個(gè)目錄是RAM盤,可讀可寫。<BR> 它的大小是在uClinux/romfs.mk中指定的:<BR> 例如要指定為2M大小的RAM盤:<BR> 則加入如下一句:<BR> RAMFSy = $(USER)/ramimage/ramfs2048.img<BR> 即可。 </P><P> 【注意】<BR> RAM盤太大好像會(huì)引起系統(tǒng)死機(jī)。</P><P> </P><P> 14. 關(guān)于編譯重?zé)龁?dòng)時(shí)出現(xiàn)“unable to open an initial console”問(wèn)題</P><P> 解決辦法:<BR> 修改uClinux/vendor/HHtech/M5272/Makefile,<BR> 將其中的genromfs改為/usr/local/bin/genromfs即可。</P><P> </P><P> 15. 關(guān)于BDM驅(qū)動(dòng)“ kernel-module version mismatch”問(wèn)題<BR> 現(xiàn)象:在bdm/driver/linux下執(zhí)行make后,insmod linux-bdm.o時(shí)出現(xiàn)如下錯(cuò)誤:</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機(jī)上執(zhí)行uname -r<BR> 看看當(dāng)前的內(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> 這樣編譯就不會(huì)有內(nèi)核版本不匹配的問(wèn)題了</P><P> </P><P> 16. 關(guān)于系統(tǒng)啟動(dòng)時(shí)數(shù)據(jù)總線寬度的問(wèn)題</P><P> 5272復(fù)用腳L5 QSPICLK/BUSW1 和M5 SPI_CS0/BUSW0<BR> 在HHCO5272-R1中用作 QSPICLK 和 SPI_CS0 功能(CN1 <BR> pin93 ,CN1 pin95) , 而只有在CPU復(fù)位時(shí)它們才作為BUSW1:BUSW0組合決定CS0內(nèi)存數(shù)據(jù)寬度。這個(gè)是不需要配置的。<BR> 具體參見(jiàn)MCF5272手冊(cè):P14-2頁(yè),即P14.3.1節(jié)介紹。<BR> 華恒板子的BUSW1:BUSW0組合為[1:0],即16位模式,因此剛加電時(shí)接CS0的FLASH0的數(shù)據(jù)總線寬度為16位模式。<BR> 同理,N4 QSPI_DOUT/WSEL 在HHCO5272-R1中用作 <BR> QSPI_DOUT 功能(CN1 pin89 ), <BR> WSEL也只是CPU復(fù)位時(shí)生效,華恒板子此腳接下拉電阻,表示為0,因此為32位模式。此后都作為QSPI_DOUT信號(hào)使用,不需配置。</P><P> </P><P> 17. 關(guān)于REDHAT7.3宿主機(jī)環(huán)境配置的問(wèn)題 </P><P> 目前主要的問(wèn)題在于完全安裝的REDHAT7.3沒(méi)有提供linuxconf工具軟件,因此無(wú)法配置NFS服務(wù)器。不過(guò)這個(gè)問(wèn)題很容易解決,這需要到<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>下載一個(gè)名為:linuxconf-1.25r7-3.i386.rpm的RPM包,然后在REDHAT7.3 LINUX機(jī)器上執(zhí)行:</P><P> rpm -i linuxconf-1.25r7-3.i386.rpm (6,995KB)</P><P> 這個(gè)安裝比較耗時(shí),安裝完畢后,立即就可以使用linuxconf工具了</P><P> </P><P> 18. 關(guān)于定時(shí)器使用的問(wèn)題</P><P> 對(duì)于秒級(jí)以上的應(yīng)用程序:<BR> alarm(sec)<BR> 在sec秒以后就會(huì)產(chǎn)生一個(gè)sigalrm信號(hào)。<BR> 注冊(cè)一個(gè)自己的處理函數(shù)來(lái)處理這個(gè)信號(hào)就可以實(shí)現(xiàn)。</P><P> 對(duì)于ms級(jí)的定時(shí),usleep為us級(jí)的延時(shí),但無(wú)法提供中斷。<BR> MCF5272提供四個(gè)定時(shí)器,uClinux只使用了其中一個(gè):<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中增加對(duì)TMR2初始化設(shè)置和中斷申請(qǐng)。然后自己寫TMR2的定時(shí)器中斷服務(wù)程序,<BR> 這個(gè)代碼可放在config.c中,也可加到OS代碼中:<BR> uClinux/linux/arch/m68knommu/kernel/time.c:<BR> 這個(gè)文件中有LINUX使用TMR1的定時(shí)器中斷服務(wù)程序代碼:<BR> void timer_interrupt(int irq, void *dummy, struct pt_regs * regs)<BR> 它是用來(lái)給LINUX OS提供時(shí)鐘的,自己的定時(shí)中斷就不必做這個(gè)工作了,讓它10ms進(jìn)一次中斷,在自己的TMR2中斷程序中做自己的工作就可以了。當(dāng)然這里的處理一定要快。</P><P> <BR> </P><P> 19. 關(guān)于C++支持<BR> 華恒HHCF系列開發(fā)套件光盤提供的軟件系統(tǒng)支持C++代碼,下面給出一個(gè)編譯參數(shù)的例子:</P><P> m68k-elf-g++ -m5307 -msep-data -Wl,-elf2flt -o test test.cpp -lstdc++ -lc -lgcc </P><P> 【注意】</P><P> 這里沒(méi)有加入庫(kù)的路徑和頭文件的路徑:-L和-I,請(qǐng)用戶在編譯時(shí)自己指定絕對(duì)路徑。<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> 說(shuō)明:uclinux(uclibc)現(xiàn)在對(duì)iostream的支持還不夠,不能使用iostream庫(kù)。<BR> 【注】</P><P> 華恒客戶可發(fā)信到support@hhcn.com索取測(cè)試代碼。</P><P> </P><P> 20. 關(guān)于進(jìn)程間通信IPC的問(wèn)題</P><P> uClinux下system V的進(jìn)程間通信IPC機(jī)制不可用!</P><P> (現(xiàn)在已經(jīng)可以用了,在make menuconfig中內(nèi)核配置菜單中選擇General setup --->,選中:</P><P> [*] System V IPC)<BR> 1 信號(hào):但要求知道另一個(gè)進(jìn)程的pid號(hào):<BR> 進(jìn)程間用信號(hào)通信時(shí),用kill發(fā)送信號(hào),但需要指定進(jìn)程號(hào),<BR> 可以這樣作:<BR> 接收信號(hào)的進(jìn)程把自己的進(jìn)程號(hào)寫到RAM盤(如/tmp目錄)下的一個(gè)文件中,發(fā)送信號(hào)的進(jìn)程從這個(gè)文件中讀取這個(gè)進(jìn)程號(hào)即可成功的實(shí)現(xiàn)信號(hào)發(fā)送。</P><P> 這里是直接指定內(nèi)存地址(當(dāng)然做好是在靠后的未用地址),然后用一個(gè)進(jìn)程啟動(dòng)另一個(gè)進(jìn)程,這兩個(gè)進(jìn)程之間的進(jìn)程號(hào)恰好相差1,這樣就可以在兩個(gè)進(jìn)程之間使用信號(hào)了。<BR> 2 共享文件:兩個(gè)進(jìn)程訪問(wèn)同一個(gè)文件,用文件鎖實(shí)現(xiàn)互斥訪問(wèn)。<BR> 要保護(hù)/tmp/a文件,<BR> 在一個(gè)進(jìn)程中每次要fopen前,先判斷是否有a.lock文件鎖,<BR> 若有就等待。<BR> 若沒(méi)有,則創(chuàng)建該文件鎖用open(O_CREAT|0_EXECL,<BR> S_IRUSR|S_IWUSR)創(chuàng)建。<BR> 另一方法:在RAM中建立共享區(qū)(相當(dāng)于文件)<BR> 在一個(gè)進(jìn)程里面分配一個(gè)內(nèi)存快,然后將內(nèi)存快的地址傳給<BR> 由vfork和exclp創(chuàng)建的另一個(gè)進(jìn)程,這樣這兩個(gè)進(jìn)程就可以對(duì)這塊內(nèi)存進(jìn)行讀寫了,對(duì)共享內(nèi)存的互鎖是通過(guò)發(fā)信號(hào)實(shí)現(xiàn)的。<BR> 一共有4個(gè)進(jìn)程,分別一個(gè)啟動(dòng)一個(gè),這樣他們的進(jìn)稱號(hào)恰好是連續(xù)的,一就是說(shuō)一個(gè)進(jìn)程知道任意一個(gè)它想發(fā)信號(hào)的進(jìn)程號(hào)。這樣就可以在所有進(jìn)程間發(fā)信號(hào)了,共享內(nèi)存是先分配內(nèi)存塊,然后傳遞已經(jīng)有操作系統(tǒng)分配好的共享內(nèi)存地址,管道使用的pipe創(chuàng)建,然后使用vfork創(chuàng)建另一個(gè)進(jìn)程,并傳遞管道的讀、寫fd,就可以讀寫管道了。</P><P> 3 消息隊(duì)列<BR> 含消息隊(duì)列的程序編譯程序時(shí)會(huì)提示沒(méi)有定義符號(hào)--"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里沒(méi)包含"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)修改上一級(jí)目錄里makefile,添加msg目錄;->加函數(shù)到libc.a里;<BR> 5)make dep;<BR> 6)make;<BR> 注意:在系統(tǒng)機(jī)上發(fā)消息隊(duì)列的長(zhǎng)度和接收消息隊(duì)列的長(zhǎng)度可以不等長(zhǎng);華恒內(nèi)核中長(zhǎng)度好象必須相等,(最大不要超過(guò)BUFSIZ=1024)。<BR> 消息隊(duì)列可以對(duì)其進(jìn)行編址,使得各個(gè)進(jìn)程各取所需,并且可以使消息隊(duì)列的個(gè)數(shù)變少。但是如果在消息隊(duì)列被刪除后還有N個(gè)要發(fā)送或檢索的進(jìn)程,會(huì)發(fā)生問(wèn)題 <BR> 信號(hào)量的做法一樣!</P><P> <BR> </P><P> 21. 關(guān)于應(yīng)用程序中使用GPIO的問(wèn)題</P><P> 關(guān)于GPIO,要設(shè)置三個(gè)寄存器,分別是:以PB口為例<BR> 1)PBCNT,絕對(duì)各個(gè)引腳的復(fù)用信號(hào)是否為IO<BR> 2)方向寄存器,每個(gè)引腳是輸入還是輸出。<BR> 3)數(shù)據(jù)寄存器,進(jìn)行IO的輸入輸出。</P><P> 給個(gè)例子代碼:(注意:這是在用戶應(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> 下面是一個(gè)例子,在一個(gè)進(jìn)程中通過(guò)管道啟動(dòng)另一個(gè)進(jìn)程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下時(shí)應(yīng)在popen后加入,pclose(fd)或wait(&waitstat)。因?yàn)閡Clibc中popen的實(shí)現(xiàn)與X86下的不同,它使用了vfork(PC上是用fork)必須等子進(jìn)程可靠結(jié)束關(guān)閉文件后才執(zhí)行對(duì)文件的下一步讀寫。</P><P> <BR> </P><P> 23. 關(guān)于外設(shè)中斷的問(wèn)題</P><P> MCF5272處理器提供了6路外部中斷以供外設(shè)控制芯片使用。在MCF5272的啟動(dòng)代碼中(sysinit.c代碼中)屏蔽了所有的內(nèi)部和外部中斷,因?yàn)橛脩粼跀U(kuò)展使用自己的中斷源設(shè)備時(shí),在該設(shè)備的驅(qū)動(dòng)初始化代碼(如open函數(shù)中)中就必須手工打開允許這個(gè)外部中斷源。屏蔽和允許一個(gè)中斷源都是通過(guò)設(shè)置ICRn寄存器來(lái)實(shí)現(xiàn)的。<BR> 在對(duì)應(yīng)的PI位寫1,而后面的三位IPL位都為0就表示屏蔽該中斷源。<BR> 在對(duì)應(yīng)的PI位寫1,后面的三位IPL位寫001~111就表明打開運(yùn)行該中斷源,并設(shè)置其中斷優(yōu)先級(jí)為1到7級(jí),級(jí)別越高,優(yōu)先級(jí)越高。<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下來(lái)的版本的區(qū)別在于:</P><P> 1)網(wǎng)上開源的版本只提供了RAM版內(nèi)核,不提供ROM版本,呵呵,這樣做我想可能就是為了限制商業(yè)化用戶吧,因?yàn)镽AM版本還需要bootloader來(lái)引導(dǎo)(但行業(yè)內(nèi),bootloader基本上大家都不提供源代碼),不能直接啟動(dòng),根本無(wú)法作為商業(yè)產(chǎn)品使用,因此也就只能給愛(ài)好者折騰著玩玩而已。華恒替客戶完成了這部分ROM化的工作。</P><P> 2)華恒以本地化器件提供的硬件板卡,因此要針對(duì)自己的硬件修改系統(tǒng)啟動(dòng)代碼、硬件設(shè)備驅(qū)動(dòng)BSP,并相應(yīng)的提供下載、燒寫等工具軟件,這些都要自己移植,修改或者完全自己定制。沒(méi)有這些輔助工具,空有uClinux的tar包,是根本無(wú)法進(jìn)行開發(fā)調(diào)試的。</P><P> 3)本地化全中文技術(shù)手冊(cè)及相關(guān)的技術(shù)支持(論壇)。</P><P> </P><P> 25. 關(guān)于不同內(nèi)核版本間應(yīng)用程序移植的問(wèn)題</P><P> 應(yīng)用程序的移植一般的和內(nèi)核版本是沒(méi)有任何關(guān)系的,當(dāng)然有的應(yīng)用程序是需要內(nèi)核支持的,例如pppd等。在2.0.38內(nèi)核和2.4內(nèi)核之間互移應(yīng)用程序,唯一要注意的就是Makefile的寫法:</P><P> 其實(shí)區(qū)別就一句話,就是2.4下面,它把elf2flt作為gcc的一個(gè)參數(shù)一步完成了,而2.0.38還要分為兩步完成,體現(xiàn)在Makefile上就如下:</P><P> 對(duì)于2.0.38:</P><P> $(LD) $(LDFLAGS) -o $@.elf $(OBJS) $(LDLIBS)<BR> $(CONVERT)<BR> 對(duì)于2.4.x:</P><P> $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)</P><P> </P><P> 26. 關(guān)于中斷的問(wèn)題</P><P> 在每個(gè)使用中斷的設(shè)備的驅(qū)動(dòng)初始化代碼中,都首先要打開中斷,因?yàn)閱?dòng)代碼把所有中斷都禁止(mask)了,根據(jù)CPU手冊(cè),在ICRn對(duì)應(yīng)的PI位寫1,而后面的三位IPL位都為0就表示屏蔽該中斷源。即將對(duì)應(yīng)ICR中對(duì)應(yīng)的字節(jié)設(shè)置為8。例如啟動(dòng)時(shí),ICR1就被設(shè)置為:0x88888888。</P><P> 打開中斷時(shí),則在ICRn對(duì)應(yīng)的PI位寫1,后面的三位IPL位寫001~111就表明打開運(yùn)行該中斷源,并設(shè)置其中斷優(yōu)先級(jí)為1到7級(jí),級(jí)別越高,優(yōu)先級(jí)越高。例如MCF5272的幾個(gè)內(nèi)部模塊所使用的內(nèi)部中斷:<BR> 1)TIMER:在ICR1對(duì)應(yīng)位設(shè)置0xd,即priority == 5(2.0.38用的是TMR1,2.4內(nèi)核用的是TMR4)<BR> 2)FEC:在ICR3對(duì)應(yīng)位設(shè)置0xd,即priority == 5<BR> 3)FEC要工作的同時(shí)還要使用MII(占用INT2),在ICR1對(duì)應(yīng)位設(shè)置0xd,即priority == 5<BR> 4)UART:在ICR2對(duì)應(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中對(duì)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中,有如下代碼對(duì)UART進(jìn)行中斷初始化:<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)外部中斷后,并不會(huì)自動(dòng)的清楚該中斷的pending位,這樣用戶就必須在自己的中斷處理函數(shù)的末尾自己來(lái)替處理器完成這一工作。例如:對(duì)于外部中斷3</P><P> *(volatile unsigned long*)(MCF_MBAR+0x20) |= 0x00800000;</P><P> </P><P> 27. 應(yīng)用程序中如何定時(shí)產(chǎn)生信號(hào)?</P><P> 這個(gè)問(wèn)題就相當(dāng)于實(shí)現(xiàn)WINDOWS下的WM_TIMER功能,定時(shí)給應(yīng)用程序發(fā)送消息</P><P> 例如:要求每一秒產(chǎn)生一個(gè)信號(hào),去打印一句test。本來(lái)signal/alarm只能一次性工作,現(xiàn)在要讓它循環(huán)起來(lái),每一秒都產(chǎn)生信號(hào),就要再其信號(hào)處理函數(shù)中對(duì)其進(jìn)行重置。<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)用程序時(shí),也是要在uClinux下執(zhí)行make,屏幕一滾就過(guò)去了,SHIFT+PAGEUP也翻不了那末多,其實(shí)自己的應(yīng)用怎么編譯的也不清楚。</P><P> 在uClinux下執(zhí)行make >&t,則自動(dòng)生成臨時(shí)文件t,它記錄了整個(gè)編譯過(guò)程及每步編譯的詳細(xì)參數(shù),對(duì)于理解編譯工具的使用及其參數(shù)非常有幫助。(整個(gè)的編譯過(guò)程詳細(xì)分析請(qǐng)參見(jiàn)手冊(cè)2.1.3節(jié)),舉例而言,以應(yīng)用程序uClinux/user/inetd和ping為例:</P><P> 對(duì)于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> 對(duì)于uClinux-2.4.17下的編譯全部以gcc為前臺(tái),連ld也被隱藏到后臺(tái)了:<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庫(kù)的路徑。庫(kù)路徑可以有多個(gè)(對(duì)于一個(gè)應(yīng)用程序而言,很多庫(kù)并沒(méi)有用),因此可以看到有多個(gè)-L參數(shù);<BR> -I參數(shù)表明后面所跟的為C語(yǔ)言INCLUDE頭文件的路徑,這個(gè)路徑可以有多個(gè),因此可以看到有多個(gè)-I參數(shù);<BR> -m5200(-m5307)為處理器相關(guān)編譯參數(shù),2.4下采用了-m5307,這其實(shí)對(duì)于應(yīng)用程序而言沒(méi)有任何區(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í)文件保存,無(wú)法永久的保存數(shù)據(jù),例如配置文件等。下面大概介紹一下幾種FLASH上保存配置的方法:</P><P> 1. 對(duì)于簡(jiǎn)單的數(shù)據(jù),小的配置文件等,而且不是非常頻繁的(例如一分鐘寫10次)寫入的,可以直接自己在FLASH的空余處(例如第二片F(xiàn)LASH上)劃出一塊區(qū)域,以自己定義的方式寫入,并在板子啟動(dòng)時(shí)自動(dòng)讀出。華恒提供了這樣的樣例代碼,即user/memtools/,其詳細(xì)介紹在手冊(cè)第二章“FLASH扇區(qū)保存IP地址”一節(jié)。這樣作最大的好處是用戶的控制程度最大,形式最靈活,保存的可以是自定義的數(shù)據(jù),可以不是文件的形式。而下面的幾種方式都是要求文件的形式保存,無(wú)法處理自定義的數(shù)據(jù)保存。</P><P> 2. 對(duì)于比較多的配置文件,一般的都先寫在RAM盤中,然后選擇保存,一次性寫入FLASH的某幾個(gè)扇區(qū)。這時(shí)就可使用flatfsd軟件,它的使用需要內(nèi)核的配合支持,即要在blkmem.c中為其指定保存數(shù)據(jù)的幾個(gè)扇區(qū)的起始/結(jié)束地址。這中方式也不能適應(yīng)非常頻繁的寫入。</P><P> 3. 對(duì)于比較頻繁的數(shù)據(jù)保存,就要在板子上建立額外的日志型文件系統(tǒng)JFFS/JFFS2,或者干脆就用JFFS/JFFS2取代ROMFS作根文件系統(tǒng)。這樣板子的目錄就是可寫的,就像硬盤一樣,不需要額外的工具來(lái)負(fù)責(zé)將數(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上實(shí)現(xiàn)支持并不復(fù)雜,但它的實(shí)用還需要一些額外的工作,例如燒寫工具的配合,新型image.bin編譯生成,因?yàn)檎嬲a(chǎn)品化的軟件是不能允許每次啟動(dòng)后都還要進(jìn)行許多的手工操作,例如加載文件系統(tǒng)等,板子出廠燒寫也要一次完成,而不能還要分多次燒寫等等,這些工作都是比較繁雜的,而且沒(méi)有燒寫工具的源代碼是無(wú)法完成的。華恒提供JFFS/JFFS2整套軟件技術(shù)。</P><P> </P><P> 30. 關(guān)于2.4內(nèi)核版本下的RAM版內(nèi)核的編譯</P><P> 對(duì)于2.0.38內(nèi)核,華恒提供了完備的ram.ld和crt0_ram.S,它們和華恒提供的bootloader可配合使用。 對(duì)于2.4.17的內(nèi)核,從網(wǎng)上直接DOWN的uClinux-Coldfire版本(例如最新版本:uClinux-dist-20020701.tar.gz)是可以直接在華恒bootloader提示符HHCN>下執(zhí)行readàgo 100000跑起來(lái)的。而若客戶要從華恒2.4系列開發(fā)套件軟件系統(tǒng)的基礎(chǔ)上改動(dòng)跑RAM版則需要做一些改動(dòng)才可以的,例如HHCF5272-LCD-IDE-R1、HHCF5272-2ETH-R2等都是采用的2.4內(nèi)核。因?yàn)槿A恒板子燒在FLASH上的就是一個(gè)RAM版本的內(nèi)核,經(jīng)由華恒的bootloader解壓復(fù)制到RAM中才激活執(zhí)行的,它的執(zhí)行方式和readàgo的方式是完全不同的,雖然都是RAM版。要做到這一點(diǎn),華恒是做了一些改動(dòng)的,而現(xiàn)在實(shí)際上就是要恢復(fù)成從網(wǎng)上直接DOWN下來(lái)的狀態(tài)。<BR> 1 首先是crt0_ram.S和直接下載的uClinux-Coldfire版本的crt0_ram.S有區(qū)別,是經(jīng)過(guò)華恒修改的代碼,若直接使用必然無(wú)法通過(guò)bootloaderàreadàgo 100000而跑起來(lái)。因此這時(shí)就必須使用網(wǎng)上下載的原始未經(jīng)改動(dòng)的crt0_ram.S,其實(shí)兩個(gè)文件的區(qū)別很小,僅在于華恒的版本注釋了復(fù)制romfs的部分代碼:<BR> 只要把uClinux/linux-2.4.x/arch/m68knommu/platform/5272/HHTECH/crt0_ram.S中的一個(gè)#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【這里原來(lái)是#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下來(lái)默認(rèn)的ORIGIN = 0x20000,這樣用我們的bootloader下載下去當(dāng)然是跑不起來(lái)的。以下的SECTIONS 節(jié)不需要任何改動(dòng)。<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> 其實(shí)關(guān)鍵就是去掉CAT_ROMARRAY的定義。</P><P> </P><P> <BR> 31. 2.4 LINUX內(nèi)核大小 </P><P> uClinux/linux-2.4.x/目錄下編譯出來(lái)的linux文件有5M多,這是ELF格式的文件,它轉(zhuǎn)換成image.bin時(shí)還要用m68k-elf-objcopy工具轉(zhuǎn)換成binary格式的linux.bin,這時(shí)它就只有800k了,再壓縮一下就變成300k了。這個(gè)工作具體可參見(jiàn)uClinux/vendors/HHTECH/M5272/Makefile。</P><P> <BR> 32. 從SDRAM中劃出一塊不讓LINUX訪問(wèn),供自己使用,可作共享內(nèi)存用 </P><P> 對(duì)于2.4內(nèi)核修改uClinux/linux-2.4.x/arch/m68knommu/platform/5272/HHTECH/crt0_ram.S(對(duì)于2.0ROM版,為uClinux/linux/arch/m68knommu/platform/5272/MOTOROLA/crt0_rom.S),只要修改一處:即文件最前面定義的MEM_SIZE宏,華恒提供的為0x01000000,即16M。用戶若想劃出8M為自己管理使用,只要將這個(gè)值改為0x00800000即可。這樣作就是不讓LINUX知道還有這8M地址,這樣OS在分配內(nèi)存的時(shí)候就不會(huì)用到這些地址空間,相當(dāng)于從OS那里偷內(nèi)存給自己使用。例如可用于內(nèi)核驅(qū)動(dòng)和應(yīng)用程序的通信用共享內(nèi)存等。</P><P> </P><P> 33. 關(guān)于通過(guò)NFS mount宿主機(jī)硬盤調(diào)試應(yīng)用程序的問(wèn)題 </P><P> 嵌入式LINUX調(diào)試應(yīng)用程序最主要的方式就是通過(guò)NFS mount宿主機(jī)硬盤上的應(yīng)用程序來(lái)執(zhí)行,通過(guò)觀察其在串口終端打印的信息來(lái)達(dá)到調(diào)試的目的。</P><P> 在這個(gè)過(guò)程中,存在一個(gè)權(quán)限的問(wèn)題,即板子mount宿主機(jī)硬盤后,這個(gè)NFS mount的操作默認(rèn)的不是以root的權(quán)限執(zhí)行的,因此一般的板子沒(méi)有權(quán)限執(zhí)行宿主機(jī)硬盤上的程序,這時(shí)就要在宿主機(jī)上執(zhí)行chmod 777 app,其中app為應(yīng)用程序可執(zhí)行文件的名字。其實(shí)這種現(xiàn)象還是比較容易為開發(fā)人員解決的,因?yàn)楫?dāng)執(zhí)行應(yīng)用時(shí),minicom就會(huì)報(bào)錯(cuò),permision denied,或者unknown error 4。但對(duì)于有的情況就不一定這么容易看出是權(quán)限的問(wèn)題:</P><P> 例如:調(diào)試WEB管理軟件cgi代碼時(shí),我們把宿主機(jī)上/cgi-bin/通過(guò)NFS mount到板子的CGI工作目錄/home/httpd/cgi-bin/上,這時(shí)通過(guò)瀏覽器IE執(zhí)行CGI操作時(shí),就會(huì)報(bào)錯(cuò)403,這里也是一個(gè)權(quán)限的問(wèn)題,即CGI要求其工作目錄可寫,這時(shí)就必須在宿主機(jī)上執(zhí)行:chmod 777 /cgi-bin,這時(shí)瀏覽器里立刻就可以工作了。</P><P> </P><P> 34. 關(guān)于uClinux下線程的使用</P><P> 使用線程是要求uClibc里加入pThread庫(kù)編譯。<BR> 這樣就要求make menuconfig時(shí)選擇uClibc,而不是華恒默認(rèn)選擇的uC-libc。<BR> 在uClibc中選擇pThread庫(kù),可以按照以下操作:<BR> 1.cd uClibc<BR> 2.make menuconfig CROSS=m68k-elf-<BR> 3.選上posix thread support選項(xiàng)<BR> 4.cd ..<BR> 5.make clean<BR> 6.make</P><P> 庫(kù)選擇好之后,先不必自己編制應(yīng)用程序,uClinux提供了完備的測(cè)試程序:即uClinux/user/threaddemos<BR> 你make menuconfig在應(yīng)用程序中選擇這個(gè)程序加入編譯,看是否可以編譯通過(guò),通過(guò)后執(zhí)行是否正確即可。</P><P> 若編譯有錯(cuò)誤,可以直接到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)測(cè)試代碼。</P><P> </P><P> 35. 關(guān)于支持模塊動(dòng)態(tài)加載(Loadable Module)的問(wèn)題</P><P> 在make menuconfig中配置內(nèi)核時(shí)選擇: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)用程序動(dòng)態(tài)鏈接uClibc的問(wèn)題 </P><P> 早期的uClinux下的應(yīng)用程序都是采用靜態(tài)鏈接的方式鏈接uClibc/uC-libc,現(xiàn)在uClinux早就已經(jīng)可以支持動(dòng)態(tài)鏈接uClibc庫(kù)了。動(dòng)態(tài)鏈接的好處是可以實(shí)現(xiàn)多個(gè)應(yīng)用程序?qū)崿F(xiàn)代碼共享,從而可以節(jié)省內(nèi)存消耗,就相當(dāng)于WINDOWS下的DLL所引入的共享優(yōu)勢(shì)。</P><P> 動(dòng)態(tài)鏈接在NOMMU處理器上的實(shí)現(xiàn)采用了XIP(execute in place)代碼。</P><P> 詳細(xì)分析參見(jiàn):</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> 參見(jiàn):<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機(jī)上,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)用程序時(shí)報(bào)錯(cuò):BINFMT_FLAT: bad magic/rev (0x1010100, need 0x4)</P><P> 例如:mount宿主機(jī)上的nmbd,在minicom下執(zhí)行/mnt/nmbd&,出現(xiàn)如下錯(cuò)誤:</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àn)檫@個(gè)應(yīng)用程序沒(méi)有使用交叉編譯工具編譯,而是用了PC LINUX下的gcc編譯出來(lái)的。造成這種問(wèn)題的經(jīng)常是由于客戶不是在uClinux目錄下執(zhí)行make統(tǒng)一進(jìn)行編譯,而是直接到該應(yīng)用程序目錄下執(zhí)行make所致。這是由于uClinux/user/下每個(gè)應(yīng)用程序的Makefile中使用了許多宏,列入CC等,這些宏都是統(tǒng)一在uClinux下的一個(gè)目錄下的文件中定義的,若用戶直接到user/下的應(yīng)用程序目錄下執(zhí)行make,則這些宏就無(wú)法獲取uClinux為其設(shè)定的值,而是自動(dòng)采用PC LINUX系統(tǒng)默認(rèn)的,例如CC若用戶不指定,默認(rèn)的就是gcc,所以應(yīng)用程序就沒(méi)有用m68k-elf-gcc編譯,而是用PC LINUX下的gcc編譯的,這樣編出來(lái)的可執(zhí)行文件在板子上當(dāng)然是無(wú)法執(zhí)行的了。</P><P> </P><P> 39. 關(guān)于關(guān)閉shell,使能串口通信</P><P> 鑒于我們提供的版本不斷的升級(jí),所以針對(duì)不同版本的方法略有區(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> 修改以后啟動(dòng)過(guò)程中printk內(nèi)容仍會(huì)打印,printf內(nèi)容如rc內(nèi)步驟不會(huì)打印。</P><P> 2.同時(shí)最好在user/init/simpleinit.c中不要啟動(dòng)/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> 【這是最新的測(cè)試結(jié)果】<BR> 通常不能使用COM1進(jìn)行串口通信的原因是它已被重定向?yàn)闃?biāo)準(zhǔn)輸入輸出,系統(tǒng)的shell進(jìn)程將對(duì)其監(jiān)視并處理從此處發(fā)送進(jìn)來(lái)的數(shù)據(jù),而不能被用戶程序所得到。<BR> 解決辦法我認(rèn)為有兩種,一是不把Com1口重定向?yàn)闃?biāo)準(zhǔn)輸入輸出,二是在標(biāo)準(zhǔn)輸入輸出上不啟動(dòng)shell。第一種沒(méi)有試過(guò),第二種可以按下面方法修改。<BR> ü uC的版本很多,好像有一種是在uClinux/linux-2.4.x/init/main.c中啟動(dòng)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> 沒(méi)有就算了。<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> 這樣并不是說(shuō)就永遠(yuǎn)不會(huì)啟動(dòng)shell了,只是在標(biāo)準(zhǔn)輸出上不啟動(dòng)shell,但若用戶telnet板子還是仍然會(huì)在p0口上啟動(dòng)shell的,否則用戶就永遠(yuǎn)無(wú)法向板子發(fā)布command命令了。</P><P> <BR> </P><P> 40. 關(guān)于malloc使用問(wèn)題</P><P> 在HHCF5272-R2的uClinux下測(cè)試, malloc最大空間約為2,048,000<BR> 設(shè)為2,100,000時(shí),出現(xiàn):<BR> kernel panic : BUG!<BR> 另:realloc結(jié)果同malloc一樣,大小上沒(méi)有區(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> 對(duì)串口波特率修改為<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就對(duì)應(yīng)上表的19200,默認(rèn)串口波特率為19200</P><P> 對(duì)串口傳輸格式修改<BR> ioctl(spfd,SETFORMAT,"8n1");</P><P> 默認(rèn)為8n1</P><P> </P><P> 42.關(guān)于CGI</P><P> CGI是一種WEB SERVER端擴(kuò)展代碼。例如IIS端的ISAPI等開發(fā)的DLL代碼都是WINDOWS上的WEB SERVER端的擴(kuò)展,用于處理用戶通過(guò)WEB瀏覽器的表單輸入等靜態(tài)頁(yè)面以外的智能輸入處理。<BR> CGI可用于WINDOWS和LINUX上的WEB SERVER端擴(kuò)展,可用各種腳本如PHP等實(shí)現(xiàn),最原始的就是用C代碼實(shí)現(xiàn)的,具體用什么代碼要看你的WEB SERVER是否支持。對(duì)于嵌入式LINUX采用的boa這個(gè)WEB SERVER而言,就不支持任何的腳本,只支持C代碼的CGI程序,每連接一個(gè)客戶端瀏覽器連接就在SERVER端(板子上)啟動(dòng)一個(gè)CGI進(jìn)程的COPY。</P><P> <BR> 43.在REDHAT 9.0環(huán)境下使用BDM時(shí),提示“DEVICE BUSY”,是并口被占用?</P><P> 請(qǐng)?jiān)谀腞EDHAT9機(jī)器上執(zhí)行如下命令<BR> rmmod lp<BR> rmmod parport_pc<BR> rmmod parport<BR> 這時(shí)您再執(zhí)行./chk就沒(méi)有問(wèn)題了。</P><P> <BR> 44.xxx函數(shù)或者結(jié)構(gòu)體是在哪里定義的等類似的問(wèn)題。</P><P> 在LINUX這種開源的環(huán)境下工作,最重要的不是你己經(jīng)掌握了多少知識(shí),而是要掌握獲取信息的手段,源代碼都有,所有的知識(shí)都在那個(gè)uClinux的目錄下,不需要任何的書籍,只有有搜索和查找的工具就可以獲取任何需要的知識(shí),搞開發(fā)就像學(xué)語(yǔ)言,模仿是非常有效的手段,看系統(tǒng)中運(yùn)行的代碼是怎么寫的,仿照著做就是了。<BR> 搜索和查找的手段就兩個(gè):<BR> 一個(gè)是在所有文件中搜索字符串:<BR> grep xxx * -r<BR> 另一個(gè)是搜索文件:<BR> find -name xxx.c<BR> 還有,可在uClinux目錄下(其實(shí)任何目錄都可以,只是作用范圍小些)用:<BR> ctags -R .<BR> 這樣在vi中閱讀代碼時(shí)可用ctrl+]跳轉(zhuǎn)到想要查詢的函數(shù)/結(jié)構(gòu)定義處;用ctrl+T返回。</P><P> </P><P> 45.關(guān)于uClinux浮點(diǎn)支持<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編譯項(xiàng)到<BR> OBJ= $(AOBJ) $(POBJ) $(SOBJ) dputs.o snprintf.o getdelim.o getline.o <BR> gcvt.o<BR> ~~~~~~添加項(xiàng)<BR> 2b.添加編譯參數(shù)-DFLOATS=1到all: $(LIBC) $(OBJ)前面<BR> 3.可增加make clean相關(guān)項(xiàng)<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):
離線
公司簡(jiǎn)介
產(chǎn)品目錄
|
|
公司名稱:
|
華恒公司
|
聯(lián) 系 人: |
市場(chǎng)部
|
電 話: |
0551-5325652
|
傳 真: |
0551-5325323 |
地 址: |
合肥市長(zhǎng)江西路669 號(hào)高新技術(shù)產(chǎn)業(yè)開發(fā)區(qū)軟件園四號(hào)樓204-206華恒科技 |
郵 編: |
230088 |
主 頁(yè): |
|
|
|
|
|