當(dāng)前位置: 首頁(yè) > 工業(yè)電子產(chǎn)品 > 其他電子產(chǎn)品 > 開(kāi)發(fā)板,套件,編程器 > 開(kāi)發(fā)板
發(fā)布日期:2022-10-14 點(diǎn)擊率:111
i.MX6是Freescale推出的ARM架構(gòu)高端多媒體處理器,與常規(guī)的ARM處理器不同的是,i.MX6具有非常實(shí)用的PCI Express接口,這對(duì)于從事WiFi行業(yè)的人士來(lái)說(shuō)具有非常大的吸引力。通常的基于WLAN SoC進(jìn)行無(wú)線產(chǎn)品設(shè)計(jì),很難具備高性能多媒體處理能力;通常的基于ARM處理器進(jìn)行多媒體處理器平臺(tái)設(shè)計(jì),又很難實(shí)現(xiàn)高性能無(wú)線傳輸。i.MX6的出現(xiàn)使得高性能無(wú)線多媒體平臺(tái)的設(shè)計(jì)大大簡(jiǎn)化。其實(shí)此前也使用過(guò)TI AM3894進(jìn)行無(wú)線媒體服務(wù)器的設(shè)計(jì),但是其過(guò)大的發(fā)熱量極大地限制了其應(yīng)用,Mindspeed公司也具有PCI-e接口的ARM處理器,但畢竟不是主流廠商,所以i.MX6深深地贏得了廣大工程師的喜愛(ài),包括我本人。
說(shuō)了這么多,開(kāi)始進(jìn)入本文的主題。做過(guò)Qualcomm Atheros平臺(tái)的讀者一定知道,WiFi產(chǎn)品出廠前需要在產(chǎn)線通過(guò)復(fù)雜的產(chǎn)測(cè)環(huán)節(jié),主要包括射頻校準(zhǔn),測(cè)試,參數(shù)寫入等步驟,未寫入射頻參數(shù)的WiFi產(chǎn)品是無(wú)法正常使用的。如果是基于Qualcomm Atheros WLAN SoC做的無(wú)線產(chǎn)品,官方會(huì)有移植完成的ark.ko內(nèi)核模塊,nart.out應(yīng)用程序及各種所需的庫(kù)文件,F(xiàn)reescale i.MX6不在官方支持的范圍內(nèi)。因此,如果想順利產(chǎn)測(cè),就必須自行移植驅(qū)動(dòng)程序及測(cè)試程序。
鄭重聲明:本文關(guān)于驅(qū)動(dòng)移植部分寫得很不專業(yè),并且是以流水賬的方式記錄,主要是想幫助面臨同樣問(wèn)題的讀者,所以還請(qǐng)讀者海涵。
1 此前調(diào)試i.MX6驅(qū)動(dòng)程序時(shí)已經(jīng)搭建好i.MX6的開(kāi)發(fā)環(huán)境,因此本文不進(jìn)行搭建過(guò)程的描述,讀者可以訪問(wèn)https://www.witimes.com/imx6-build-environment/了解大致過(guò)程。
2 首先編譯art.ko 模塊。將ART2 2.28源代碼解壓在ltib/rpm/BUILD目錄下 ,進(jìn)入driver/linux目錄,更改makefile.artmod文件,指定Linux內(nèi)核路徑及工具鏈的路徑,如下:
KDIR:=/home/tom/ltib/rpm/BUILD/linux-3.0.35 PWD:=$(shell pwd) ROOTDIR:=$(PWD)/modules ifeq($(ARM),1) ARC:=arm CROSS_CC:=/opt/freescale/usr/local/gcc-4.6.2-glibc-2.13-linaro-multilib-2011.12/fsl-linaro toolchain/bin/arm-none-linux-gnueabi- DEBUG:=0 endif
其中,將DEBUG改為1可以開(kāi)啟調(diào)試模式。
3 使用make –f makefile.artmod命令即可開(kāi)始編譯,但是會(huì)遇到很多的問(wèn)題。
3.1. error: 'phys_t' undeclared (first use in this function),含義是phys_t數(shù)據(jù)類型未定義,查看Atheros SDK中關(guān)于phys_t數(shù)據(jù)類型的定義,將phys_t的定義復(fù)制到/modules/include/ dk_flash.h中,此錯(cuò)誤不再出現(xiàn)。
3.2. modules/dk_func.c:468:2: error: unknown field 'ioctl' specified in initializer,這是由于2.6.36內(nèi)核之后 去掉了原來(lái)的ioctl,添加兩個(gè)新的成員,所以會(huì)出錯(cuò):
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
修改modules/ dk_func.c中的ioctl為compat_ioctl,編譯通過(guò)。
3.3 modules/dk_event.c:21:26: error: 'SPIN_LOCK_UNLOCKED' undeclared here (not in a function),含義是SPIN_LOCK_UNLOCKED未聲明,修改modules/dk_event.c中的
spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
為
static DEFINE_SPINLOCK(driver_lock);
編譯通過(guò),得到art.ko。
4 將編譯得到的art.ko模塊下載到目標(biāo)板中,insmod art.ko命令插入模塊,出現(xiàn)一條錯(cuò)誤信息“Could not find flash device!”,這是flash_init()函數(shù)報(bào)出的錯(cuò)誤。考慮到PCIe網(wǎng)卡的驅(qū)動(dòng)程序不應(yīng)該初始化Flash設(shè)備,因?yàn)镻CIe網(wǎng)卡的校準(zhǔn)信息保存在EEPROM或者OTP中,推測(cè)必定有配置錯(cuò)誤導(dǎo)致了這條錯(cuò)誤信息。
5 仔細(xì)閱讀makfile.artmod文件,發(fā)現(xiàn)意一條重要的注釋信息“Making generic AP art module build. This build target is used for 3rd party AP processor”,即“編譯用于第三方處理器的目標(biāo)文件”,對(duì)應(yīng)的編譯命令為
make ARCH=$(ARC) PB42=1 DEBUG=$(DEBUG) CROSS_COMPILE=$(CROSS_CC) -C $(KDIR) M=$(PWD)/modules modules
很明顯,問(wèn)題就出在這里。再次編譯,得到了可以正確加載的內(nèi)核模塊。
6 接下來(lái)就是nart的移植。遇到了諸多的問(wèn)題。
6.1 /home/tom/ltib/rpm/BUILD/art2_ver_2_20ap_src/art/../wlan/hal/nartlinux/ah_osdep.h:93:15: error: conflicting types for 'va_list',
/opt/freescale/usr/local/gcc-4.6.2-glibc-2.13-linaro-multilib-2011.12/fsl-linaro-toolchain/bin/../arm-fsl-linux-gnueabi/multi-libs/usr/include/stdio.h:80:20: note: previous declaration of 'va_list' was here,含義為va_list數(shù)據(jù)類型定義沖突。既然工具鏈中已經(jīng)定義了va_list,那么最簡(jiǎn)單的辦法自然是屏蔽nart中對(duì)于va_list的定義,更改wlan/hal/nartlinux/ah_osdep.h文件
#ifndef __LINUX_POWERPC_ARCH__ //typedef void *va_list; #endif
再次編譯,問(wèn)題不再出現(xiàn)。
6.2 uint32_t數(shù)據(jù)類型未聲明的錯(cuò)誤,我的解決辦法是將uint32_t類型重命名為uint32_imx,并修改nart源碼中所有涉及到uint32_t的部分。
6.3 經(jīng)過(guò)6.1,6.2的調(diào)整,編譯過(guò)程可以完成大部分,但在最后的link環(huán)節(jié),出現(xiàn)了大堆的關(guān)于readl,writel的錯(cuò)誤。折騰了大概1天的時(shí)間,此問(wèn)題一直沒(méi)有解決。
7 由于本人水平十分有限,所以不得不放棄在ART2 2.28版本上的嘗試,開(kāi)始使用ART2 4.6版本,好在這個(gè)版本未在link環(huán)節(jié),現(xiàn)了關(guān)于readl,writel的錯(cuò)誤,順利地得到nart.out及各種庫(kù)文件。
8 將第7步得到的art.ko ,nart.out及各種庫(kù)文件下載到目標(biāo)板中,nart.out可以正常運(yùn)行。然而悲劇的是,更大的問(wèn)題來(lái)了。每當(dāng)我嘗試使用artgui load dut時(shí),總會(huì)出現(xiàn)“Error: get version ioctl failed !”,這個(gè)問(wèn)題大概困擾了我3-4天的時(shí)間。期間非常仔細(xì)地閱讀了源代碼得知這條打印信息出現(xiàn)在get_version_info()函數(shù)中:
if ((status=get_version_info(hDevice, pDrvVer)) != A_OK) {
close(hDevice);
A_FREE(pdevInfo->pdkInfo);
A_FREE(pdevInfo);
return status;
}
說(shuō)明,如果get_version_info()返回的不是OK,則關(guān)閉設(shè)備,這部分代碼出現(xiàn)在common/linux_hw.c中。get_version_info()在get_device_client_info()中被調(diào)用,get_device_client_info()在deviceInit()中被調(diào)用看字面意思就是初始化設(shè)備,deviceInit()在setupDevice()函數(shù)中被調(diào)用。跟蹤調(diào)試get_version_info(),發(fā)現(xiàn)其通過(guò)以下語(yǔ)句獲得version的值
if (ioctl(hDevice,DK_IOCTL_GET_VERSION,&version) < 0)
那么問(wèn)題應(yīng)該就是出在ioctl函數(shù)這里。
9 是時(shí)候了解一下ioctl函數(shù)了(做驅(qū)動(dòng)開(kāi)發(fā)的讀者可不要見(jiàn)笑,哈哈)。ioctl是設(shè)備驅(qū)動(dòng)程序中對(duì)設(shè)備的I/O通道進(jìn)行管理的函數(shù)。所謂對(duì)I/O通道進(jìn)行管理,就是對(duì)設(shè)備的一些特性進(jìn)行控制,例如串口的傳輸波特率、馬達(dá)的轉(zhuǎn)速等等。它的調(diào)用方式如下:
int ioctl(int fd, ind cmd, …);
其中fd是用戶程序打開(kāi)設(shè)備時(shí)使用open函數(shù)返回的文件標(biāo)示符,cmd是用戶程序?qū)υO(shè)備的控制命令,至于后面的省略號(hào),那是一些補(bǔ)充參數(shù),一般最多一個(gè),這個(gè)參數(shù)的有無(wú)和cmd的意義相關(guān)。
ioctl函數(shù)是文件結(jié)構(gòu)中的一個(gè)屬性分量,就是說(shuō)如果你的驅(qū)動(dòng)程序提供了對(duì)ioctl的支持,用戶就可以在用戶程序中使用ioctl函數(shù)來(lái)控制設(shè)備的I/O通道。
分析一下nart代碼,的確符合這樣的調(diào)用過(guò)程,下圖(不知道原作者是哪位,如有侵權(quán),請(qǐng)聯(lián)系無(wú)線時(shí)代)很好地展示了這一過(guò)程。

那么,根據(jù)本人的粗淺理解,用戶空間的ioctl調(diào)用通過(guò)內(nèi)核向驅(qū)動(dòng)程序傳遞了fd,cmd兩個(gè)重要參數(shù),其余的參數(shù)是可選的。那么ioctl(hDevice,DK_IOCTL_GET_VERSION,&version)主要就是將hDevice及DK_IOCTL_GET_VERSION命令傳遞給驅(qū)動(dòng)程序,其中DK_IOCTL_GET_VERSION定義在driver/linux/modules/include/dk_ioctl.h中。查看驅(qū)動(dòng)程序中對(duì)于cmd的處理
switch (cmd) {
case DK_IOCTL_GET_VERSION:
#ifdef DK_DEBUG
printk("DK:: DK_IOCTL_GET_VERISION n");
#endif
data = (DRV_MAJOR_VERSION << 16) | (DRV_MINOR_VERSION);
ret = put_user(data, (INT32 *)arg);
break;
case DK_IOCTL_GET_CLIENT_INFO:
#ifdef DK_DEBUG
printk("DK:: DK_IOCTL_GET_CLIENT_INFO n");
#endif
在驅(qū)動(dòng)程序的編譯過(guò)程中已經(jīng)開(kāi)啟了DEBUG功能,那么應(yīng)該打印出“DK:: DK_IOCTL_GET_VERISION”這條信息,然而實(shí)際的log中并不存在——ioctl沒(méi)有將參數(shù)傳遞至驅(qū)動(dòng)程序!
10 回想3.2中的改動(dòng),一定引起了內(nèi)核與驅(qū)動(dòng)程序不匹配,才導(dǎo)致fd及cmd無(wú)法正確傳遞,看來(lái)2.3中的改動(dòng)無(wú)法根本解決問(wèn)題,需要對(duì)驅(qū)動(dòng)程序進(jìn)行大幅度調(diào)整才行。可是想想自己的軟件水平,實(shí)在是對(duì)自己沒(méi)有信心。
然而,我承諾的事情一定兌現(xiàn),絕不能輕易放棄。
萬(wàn)般無(wú)奈之下,我想到了Qualcomm Atheros的IPQ8064也是ARM架構(gòu),如果Qualcomm想在自己的Demo板上運(yùn)行ART,就必須經(jīng)歷同樣的過(guò)程!于是托朋友弄到了最新版本的nart及驅(qū)動(dòng)程序源代碼,此處不便透露版本信息,需要做的主要工作就是仿照AP148的config文件及makefile文件編寫Freescale i.MX6的config文件及makefile文件,問(wèn)題終于解決!
11 以下是nart正常運(yùn)行dut上的打印信息。

以下是artgui的截圖。

使用artgui讀取EEPROM,發(fā)現(xiàn)其內(nèi)容完全正確,其中MAC地址為“7C:C3:A1:B7:F2:5B”。
正常加載ath9k驅(qū)動(dòng)程序,MAC地址同樣為“7C:C3:A1:B7:F2:5B”,至此,為Freescale i.MX6處理器移植ART驅(qū)動(dòng)程序已全部完成。
下一篇: PLC、DCS、FCS三大控
上一篇: Qualcomm Atheros QCA