新聞中心
Linux v1.2 Successfully Ported to ARM Platform

讓客戶(hù)滿(mǎn)意是我們工作的目標(biāo),不斷超越客戶(hù)的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶(hù),將通過(guò)不懈努力成為客戶(hù)在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:主機(jī)域名、虛擬主機(jī)、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、北侖網(wǎng)站維護(hù)、網(wǎng)站推廣。
Introduction
Linux has gned worldwide recognition as an open-source, Unix-like operating system. When Linus Torvalds created the first Linux kernel in 1991, he never imagined that it would become one of the most versatile and widely used OS in the world. Linux was originally designed for x86-based personal computers but has over the years found its way into other hardware architectures including the ARM platform. In this article, we will discuss how Linux v1.2 was successfully ported to the ARM platform.
ARM Architecture
ARM (Advanced RISC Machines) is a reduced instruction set computing (RISC) instruction set architecture (ISA) developed by ARM Holdings. ARM processors are known for their energy efficiency, low power consumption, and high performance. The ARM architecture is widely used in embedded systems, artphones, tablets, and IoT devices. Linux, being an open-source OS, can run on a wide range of hardware platforms, including those based on the ARM architecture.
Linux v1.2
Linux 1.2 was released on March 7, 1995, and was the first version of Linux to run on machines with less than 4MB of RAM. At the time of its release, Linux had support for the i386 architecture, and ports to other architectures were actively being developed. The v1.2 release featured significant improvements over previous releases, including support for ELF binaries, shared libraries, and virtual memory management.
Porting Linux v1.2 to ARM
The initial work on porting Linux v1.2 to ARM began in 1995 by British programmer Russell King. Russell was inspired by the work of Dave Hillis, who had ported an earlier version of Linux to ARM. Russell started by modifying the Linux kernel source code to support the ARM platform, which required the development of a new set of drivers for the platform’s hardware devices. Russell also developed a new bootloader program, which is responsible for loading the Linux kernel into memory.
One of the biggest challenges in porting Linux to ARM was the lack of avlable documentation. At the time, ARM processors and their documentation were proprietary, making it difficult to develop open-source software for the platform. Russell had to rely on reverse engineering and trial and error to get the OS to run on ARM.
Another challenge was the limited memory avlable on the ARM-based devices. Linux v1.2 was designed to run on machines with less than 4MB of RAM, but many ARM-based devices had much less memory than that. Russell had to optimize the operating system to work within these limitations, which required significant manual effort.
Despite these challenges, Russell was successful in porting Linux v1.2 to the ARM platform, and the first ARM-based Linux kernel was released in 1996. Since then, Linux has become the dominant OS in the embedded systems market, with ARM processors being one of the most widely used architectures.
Conclusion
In conclusion, the successful porting of Linux v1.2 to ARM was a significant milestone in the history of Linux. It demonstrated the versatility of the OS, and its ability to run on a wide range of hardware architectures. The porting process required significant effort, and the challenges faced by Russell King are a testament to the dedication and tenacity of open-source developers. Today, Linux continues to evolve, and new ports to emerging architectures will undoubtedly be developed.
相關(guān)問(wèn)題拓展閱讀:
- ARM linux內(nèi)核啟動(dòng)時(shí)幾個(gè)關(guān)鍵地址
- 四 . 樹(shù)莓派A20 GPIO中斷程序編寫(xiě)(1基本處理)
- linux下jlink-linux-arm怎么安裝
ARM linux內(nèi)核啟動(dòng)時(shí)幾個(gè)關(guān)鍵地址
1.內(nèi)核啟動(dòng)地址
ZTEXTADDR
解壓代碼運(yùn)行的開(kāi)始地址。沒(méi)有物理地址和虛擬地址之分,因?yàn)榇藭r(shí)MMU處于關(guān)閉輪滲狀態(tài)。這個(gè)地址不一定時(shí)RAM的地址,可以是支持讀寫(xiě)尋址的flash等存儲(chǔ)中介。
Start address of decompressor. here’s no point in talking about virtual or physical addresses here, since the MMU will be off at the time when you call the decompressor code. You normally call the kernel at this address to start it booting. This doesn’t have to be located in RAM, it can be in flash or other read-only or read-write addressable medium.
在arch/arm/搭指boot/compressed/Makefile中說(shuō)的很明確
#
# We now have a PIC decompressor implementation. Decompressors running
# from RAM should not define ZTEXTADDR. Decompressors running directly
# from ROM or Flash must define ZTEXTADDR (preferably via the config)
# FIXME: Previous assignment to ztextaddr-y is lost here. See SHARK
ifeq ($(CONFIG_ZBOOT_ROM),y)
ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT)
ZBSSADDR := $(CONFIG_ZBOOT_ROM_BSS)
else
ZTEXTADDR :=
ZBSSADDR := ALIGN(8)
endif
ZRELADDR
內(nèi)核啟動(dòng)在RAM中的地址。壓縮的內(nèi)核映像被解壓到這個(gè)地址,然后執(zhí)行。
This is the address where the decompressed kernel will be written, and eventually executed. The following constraint must be valid:
__virt_to_phys(TEXTADDR) == ZRELADDR
The initial part of the kernel is carefully coded to be position independent.
一般定義在項(xiàng)目目錄下,比如:
arch/arm/mach-at91/Makefile.boot: zreladdr-y+= 0x
arch/arm/mach-at91/Makefile.boot: zreladdr-y+= 0x
arch/arm/mach-cns3xxx/Makefile.boot: zreladdr-y+= 0x
arch/arm/mach-davinci/Makefile.boot: zreladdr-y+= 0xc
arch/arm/mach-davinci/Makefile.boot: zreladdr-y+= 0x
arch/arm/mach-dove/Makefile.boot: zreladdr-y+= 0x
arch/arm/mach-ebsa110/Makefile.boot: zreladdr-y+= 0x
arch/arm/mach-exynos/Makefile.boot: zreladdr-y+= 0x
arch/臘枝脊arm/mach-footbridge/Makefile.boot: zreladdr-y+= 0x
arch/arm/mach-gemini/Makefile.boot: zreladdr-y+= 0x
arch/arm/mach-gemini/Makefile.boot: zreladdr-y+= 0x
arch/arm/mach-integrator/Makefile.boot: zreladdr-y+= 0x
arch/arm/mach-iop13xx/Makefile.boot: zreladdr-y += 0x
在arch/arm/boot/Makefile中被賦值:
ZRELADDR := $(zreladdr-y)
PARAMS_PHYS := $(params_phys-y)
INITRD_PHYS := $(initrd_phys-y)
… …
ifneq ($(LOADADDR),)
UIMAGE_LOADADDR=$(LOADADDR)
else
ifeq ($(CONFIG_ZBOOT_ROM),y)
UIMAGE_LOADADDR=$(CONFIG_ZBOOT_ROM_TEXT)
四 . 樹(shù)莓派A20 GPIO中斷程序編寫(xiě)(1基本處理)
關(guān)于按鍵,在DVK521上為:
我又從一份數(shù)據(jù)手冊(cè)中看到,PI7,PI8,PI9是沒(méi)有外部中斷功能的。如下圖所示:
還好,目前的按鍵是通過(guò)短接帽來(lái)連接PI7
PI9的,那么可以將短接帽拿掉,使用杜邦線(xiàn)連接PI10
PI12。
現(xiàn)在我將Key2連接到PI10上。那么KEY2的中斷引腳為EINT22。
配置sys_config.fex文件:
現(xiàn)在使用的樹(shù)莓派A20,是一個(gè)雙核A7的芯片,而這個(gè)屬于P架構(gòu),中斷處理方式也已經(jīng)和原先的理念大有不同。所以還是要知道關(guān)于linux的中斷原理,可以從網(wǎng)絡(luò)中獲取相關(guān)歷史性技術(shù)知識(shí)。
從A20的數(shù)據(jù)手冊(cè)中,可以看到外部中斷數(shù)到了EINT31。也就是說(shuō)PIO中斷功能有32個(gè)。
下面列出的API函數(shù)是在 \linux-sunxi\arch\arm\plat-sunxi\Sys_config.c中。
1.gpio_request_ex(),獲取sys_config.fex中設(shè)置的中斷IO口。
2.gpio_set_one_pin_io_status(),設(shè)置為輸入狀態(tài)。
3.gpio_set_one_pin_pull(),設(shè)置輸入引腳的上下拉狀態(tài)。
4.request_irq()注冊(cè)中斷函數(shù)。
request_irq()函數(shù):
之一個(gè)參數(shù)為SW_INT_IRQNO_PIO,表示是外部并尺端口的中斷號(hào)。
第二個(gè)參數(shù)為中斷處理函數(shù)名。
第三個(gè)參數(shù)為中斷方式,如IRQ_TYPE_EDGE_RISING,上升沿觸發(fā),而IRQ_TYPE_EDGE_FALLING則是下降沿觸發(fā),IRQF_SHARED為共享。
第四個(gè)參數(shù)為中斷名。
第五個(gè)參數(shù)為中斷傳遞的數(shù)據(jù)。
1.獲取IO中斷源信息
由于內(nèi)核使用的是虛擬地址尋址硬件地址,獲取中斷源就需要將IO硬件地址空間映射到虛擬地址上??梢允褂胕oremap(PIO_BASE_ADDRESS, PIO_RANGE_SIZE)進(jìn)行映射。
2.屏蔽中斷源
a.讀取中斷源寄存器的狀態(tài),可以使用readl(映射的IO地址 + PIO_INT_STAT_OFFSET);
b.判斷對(duì)應(yīng)的中斷,使用writel(reg_val&(1
寫(xiě)到這里,本應(yīng)該很順利,可是,在驅(qū)動(dòng)程序加載進(jìn)內(nèi)核的時(shí)候,明顯是報(bào)錯(cuò)。錯(cuò)誤我就不貼出來(lái)了,可是我可以將中斷信息附上:
從這里,可以看出來(lái),PIO中斷號(hào)60已經(jīng)注冊(cè)進(jìn)內(nèi)核了。我們現(xiàn)在使用的一個(gè)IO中斷是被包含在里面的。所以,需要在內(nèi)核中找到sunxi-gpio是怎么去注冊(cè)中斷,而我們就需絕兆高要將我們的中斷程序內(nèi)容附加到已經(jīng)注冊(cè)的中斷上去。
在 maroard\maroard-a20-linux-sdk-v1.2\linux-sunxi\drivers\gpio\Gpio-sunxi.c中我們可以找到函數(shù):
里面最重要的函數(shù)是:
最終調(diào)用的是:
然而,它又被賦值了:
在一定程度的意義上,gpio-sunxi.c已經(jīng)猜御將中斷基本處理做好了,我們要做的只是和它共享中斷。
sys_config.fex文件配置如下:
從上面的實(shí)驗(yàn)中,已經(jīng)發(fā)現(xiàn)在request_irq中設(shè)置邊沿等等觸發(fā),在安裝ko文件的時(shí)候,都會(huì)報(bào)錯(cuò),從這里看出,在共享中斷的時(shí)候,是不允許設(shè)置其他的內(nèi)容的。那么,只能去找A20寄存器中關(guān)于io口中斷的設(shè)置。在這些設(shè)置已經(jīng)設(shè)置好的情況下,中斷應(yīng)該就能響應(yīng)了。這里貼出一個(gè)比較簡(jiǎn)單的驅(qū)動(dòng)程序:
int main(int argc,char *argv)
{
int fd;
int val;
fd = open(“/dev/key_device”,O_RDWR);
if(fd
printf(“—open file error—-\r\n”);
return -1;
}
}
ifeq ($(KERNELRELEASE),)
KERNEL_DIR=/home/wityuan/Downloads/MarsBoard-A20-Linux-SDK-V1.2/linux-sunxi
PWD=$(shell pwd)
modules:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
arm-linux-gnueabihf-gcc -o key key.c
modules_install:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules_install
clean:
rm -rf *.ko *.o .tmp_versions
.mod.c modules.order Module.symvers .
.cmd
else
obj-m:=key.o
endif
root@maroard:~# ./key_test
—script.bin key get ok,value:1—-
key irq Interrupt
==IRQ_EINT22=
key irq Interrupt
==IRQ_EINT22=
key irq Interrupt
==IRQ_EINT22=
key irq Interrupt
==IRQ_EINT22=
key irq Interrupt
==IRQ_EINT22=
key irq Interrupt
==IRQ_EINT22=
key irq Interrupt
==IRQ_EINT22=
key irq Interrupt
==IRQ_EINT22=
key irq Interrupt
==IRQ_EINT22=
^Ckey irq Interrupt
Other Interrupt
key close—-
root@maroard:~#
root@maroard:~#
/* EINT type PIO controller registers */
/* EINT type defines */
static int int_cfg_addr = {PIO_INT_CFG0_OFFSET,
PIO_INT_CFG1_OFFSET,
PIO_INT_CFG2_OFFSET,
PIO_INT_CFG3_OFFSET};
/* Setup GPIO irq mode (FALLING, RISING, BOTH, etc */
})
/* Enable GPIO interrupt for pin */
})
/* Disable GPIO interrupt for pin */
})
/* Set GPIO pin mode (input, output, etc)
/
/
GPIO port has 4 cfg 32bit registers (8 pins each)
/
/
First port cfg register addr = port_num * 0x24 */
})
static script_gpio_set_t info;
static unsigned key_handler1;
static unsigned key_handler2;
static struct class *key_class;
static struct device *key_device;
static unsigned int key_major;
static unsigned int key_value;
static void *__iomem gpio_addr = NULL;
static int key_open(struct inode *inode, struct file *filp);
static ssize_t key_read (struct file *, char __user *, size_t, loff_t *);
static ssize_t key_write (struct file *filp, const char __user *buf, size_t len, loff_t *off);
static int key_close(struct inode *inode, struct file *filp);
struct file_operations key_operations = {
.owner = THIS_MODULE,
.open = key_open,
.read = key_read,
.write = key_write,
.release = key_close,
};
struct key_str{
char *name;
int val;
};
struct key_str g_key_str={{“key1”,0x1},{“key2”,2}};
static irqreturn_t key_irq_handler1(int irq, void *dev_id)
{
int err;
int reg_val = 0;
int ret_val = 0;
}
static irqreturn_t key_irq_handler2(int irq, void *dev_id)
{
}
static ssize_t key_read (struct file *file, char __user *buf, size_t len, loff_t *off)
{
unsigned int value = 0;
value = copy_to_user(buf,&key_value,4);
}
static int key_open(struct inode *inode, struct file *filp)
{
int err = 0;
int key_test_enabled = 0;
int ret = 0;
}
static ssize_t key_write (struct file *filp, const char __user *buf, size_t len, loff_t *off)
{
}
static int key_close(struct inode *inode, struct file *filp)
{
SUNXI_MASK_GPIO_IRQ(gpio_addr,IRQ_EINT22);
SUNXI_MASK_GPIO_IRQ(gpio_addr,IRQ_EINT23);
}
static int __init key_init(void)
{
key_major = register_chrdev(0, “key_chrdev”, &key_operations);
}
static void __exit key_exit(void)
{
if (gpio_addr) {
iounmap(gpio_addr);
}
}
module_init(key_init);
module_exit(key_exit);
MODULE_DESCRIPTION(“Driver for key”);
MODULE_AUTHOR(“wit_yuan”);
MODULE_LICENSE(“GPL”);
ifeq ($(KERNELRELEASE),)
KERNEL_DIR=/home/wityuan/Downloads/MarsBoard-A20-Linux-SDK-V1.2/linux-sunxi
PWD=$(shell pwd)
modules:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
arm-linux-gnueabihf-gcc -o key key.c
modules_install:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules_install
clean:
rm -rf *.ko *.o .tmp_versions
.mod.c modules.order Module.symvers .
.cmd
else
obj-m:=key.o
endif
int main(int argc,char *argv)
{
int fd;
int val;
fd = open(“/dev/key_device”,O_RDWR);
if(fd
printf(“—open file error—-\r\n”);
return -1;
}
}
/* EINT type PIO controller registers */
/* EINT type defines */
static wait_queue_head_t key_data_avail;
static unsigned int key_done = 0;
static int int_cfg_addr = {PIO_INT_CFG0_OFFSET,
PIO_INT_CFG1_OFFSET,
PIO_INT_CFG2_OFFSET,
PIO_INT_CFG3_OFFSET};
/* Setup GPIO irq mode (FALLING, RISING, BOTH, etc */
})
/* Enable GPIO interrupt for pin */
})
/* Disable GPIO interrupt for pin */
})
/* Set GPIO pin mode (input, output, etc)
/
/
GPIO port has 4 cfg 32bit registers (8 pins each)
/
/
First port cfg register addr = port_num * 0x24 */
})
static script_gpio_set_t info;
static unsigned key_handler1;
static unsigned key_handler2;
static struct class *key_class;
static struct device *key_device;
static unsigned int key_major;
static unsigned int key_value;
static void *__iomem gpio_addr = NULL;
static int key_open(struct inode *inode, struct file *filp);
static ssize_t key_read (struct file *, char __user *, size_t, loff_t *);
static ssize_t key_write (struct file *filp, const char __user *buf, size_t len, loff_t *off);
static int key_close(struct inode *inode, struct file *filp);
struct file_operations key_operations = {
.owner = THIS_MODULE,
.open = key_open,
.read = key_read,
.write = key_write,
.release = key_close,
};
struct key_str{
char *name;
int val;
};
struct key_str g_key_str={{“key1”,0x1},{“key2”,2}};
static irqreturn_t key_irq_handler1(int irq, void *dev_id)
{
int err;
int reg_val = 0;
int ret_val = 0;
}
static irqreturn_t key_irq_handler2(int irq, void *dev_id)
{
}
static ssize_t key_read (struct file *file, char __user *buf, size_t len, loff_t *off)
{
unsigned int value = 0;
}
static int key_open(struct inode *inode, struct file *filp)
{
int err = 0;
int key_test_enabled = 0;
int ret = 0;
}
static ssize_t key_write (struct file *filp, const char __user *buf, size_t len, loff_t *off)
{
}
static int key_close(struct inode *inode, struct file *filp)
{
SUNXI_MASK_GPIO_IRQ(gpio_addr,IRQ_EINT22);
SUNXI_MASK_GPIO_IRQ(gpio_addr,IRQ_EINT23);
}
static int __init key_test_init(void)
{
key_major = register_chrdev(0, “key_chrdev”, &key_operations);
}
static void __exit key_test_exit(void)
{
if (gpio_addr) {
iounmap(gpio_addr);
}
}
module_init(key_test_init);
module_exit(key_test_exit);
MODULE_DESCRIPTION(“Driver for key”);
MODULE_AUTHOR(“wit_yuan”);
MODULE_LICENSE(“GPL”);
ifeq ($(KERNELRELEASE),)
KERNEL_DIR=/home/wityuan/Downloads/MarsBoard-A20-Linux-SDK-V1.2/linux-sunxi
PWD=$(shell pwd)
modules:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules
arm-linux-gnueabihf-gcc -o key key.c
modules_install:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules_install
clean:
rm -rf *.ko *.o .tmp_versions
.mod.c modules.order Module.symvers .
.cmd
else
obj-m:=key.o
endif
int main(int argc,char *argv)
{
int fd;
int val;
fd = open(“/dev/key_device”,O_RDWR);
if(fd
printf(“—open file error—-\r\n”);
return -1;
}
linux下jlink-linux-arm怎么安裝
1.首先要安裝libu: sudo aptitude install libu-dev
JLink要求64位系統(tǒng)要由32位的libu,官方提示后續(xù)版本會(huì)修正此問(wèn)題(很多系統(tǒng)默認(rèn)已安裝)。
2.下載并安裝
(1)到segger官網(wǎng)下載JLink for Linux 驅(qū)動(dòng):
(2)解壓JLink_Linux_XXX.tgz(XXX代表相應(yīng)版本)
(3)執(zhí)行以下命令安裝delivered shared library:
sudo cp libjlinkarm.so.* /usr/lib
sudo ldconfig
執(zhí)行sudo ldconfig時(shí)可能會(huì)出現(xiàn)此錯(cuò)誤:/usr/lib/libjlinkarm.so.4 is not a symbolic link,可能是由于符號(hào)連接文件拷貝以后屬性變化乎攜,需要重新建立連接:
cd /usr/lib
sudo rm -rf libjlinkarm.so.4
ls libjlinkarm.so.4* (查看當(dāng)前系統(tǒng)使用的版本)
ln -s libjlinkarm.so.4.XXX libjlinkarm.so.4 (XXX代表相應(yīng)版本)
這時(shí)再執(zhí)行sudo ldconfig就行了。
(4)執(zhí)行sudo cp 45-jlink.rules /etc/udev/rules.d/,確保當(dāng)前用戶(hù)在plugdev用戶(hù)組中,執(zhí)行命令sudo useradd -G plugdev XXX(XXX代表你的用戶(hù)名)。
【如果用戶(hù)組plugdev不存在,需要按以下步驟建立:
sudo groupadd plugdev創(chuàng)建用戶(hù)組
sudo usermod -a -G plugdev XXX 添加用戶(hù)
然后重啟完成添加?!?/p>
(5)進(jìn)入JLink文件夾,執(zhí)行JLinkExe。
若出現(xiàn)此錯(cuò)誤:libreadline.so.5: cannot open shared object file: No such file or directory,32位系統(tǒng)參照網(wǎng)上通用方法解決。64位系統(tǒng)安裝sudo aptitude install lib32readline5即可解決(若lib32文件夾下已有l(wèi)ibreadline.so.5符號(hào)連接文件,需刪除后再安裝)。
(6)為方便使用,可在PATH路徑中創(chuàng)建JLinkExe的符號(hào)連接:
sudo ln -s /opt/JLink_Linux_V462a/JLinkExe /usr/bin/JLinkExe
這樣在主文件夾中輸入JLinkExe就能調(diào)出程序。
注意:(1)要獲得root權(quán)限來(lái)運(yùn)行sudo jlink,否則會(huì)出現(xiàn)問(wèn)題:Can not connect to J-Link via USB.
(2)系統(tǒng)啟動(dòng)過(guò)程中出現(xiàn)invalid rule:/etc/udev/rules.d/45-jlink.rules,需要修改該文件,將BUS!=”u”刪除或注釋掉,然后重啟就可以了,不影響使用。
3.使用JLink
在J-Link>輸入”?”,即給出命令列表。我在使用過(guò)程中,總體覺(jué)得Linux下JLink不夠成熟,主要表現(xiàn)在資料太小、功能不易用、操作成功與否不提示(當(dāng)然不排除不熟練的原因)。
3.1 下載loadbin
loadbin用于將二進(jìn)制文件下載行頃戚到目標(biāo)存儲(chǔ)器,語(yǔ)法如下:
Syntax: loadbin , //Load binary file into target memory
下載之前需要設(shè)置下目標(biāo)版的處理器,否則無(wú)法正常燒寫(xiě),我的型號(hào)是STM32F103R6,但在指定的時(shí)候只指定為STM32F103RB,如下:
J-Link>exec device = STM32F103RB
有個(gè)麻煩,下載完沒(méi)有明顯提示成功與否,可以通過(guò)這樣解決:在PC通過(guò)命令xxd查看待下載文件,下載進(jìn)去通過(guò)JLink命令mem查看,判斷這兩者是否一樣(只比較前面若干字節(jié)即可),若一樣,則表示燒寫(xiě)成功。舉個(gè)例子,把/bin/cp文件燒到檔陵板子:
關(guān)于linux v1.2 arm的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
成都服務(wù)器托管選創(chuàng)新互聯(lián),先上架開(kāi)通再付費(fèi)。
創(chuàng)新互聯(lián)(www.cdcxhl.com)專(zhuān)業(yè)-網(wǎng)站建設(shè),軟件開(kāi)發(fā)老牌服務(wù)商!微信小程序開(kāi)發(fā),APP開(kāi)發(fā),網(wǎng)站制作,網(wǎng)站營(yíng)銷(xiāo)推廣服務(wù)眾多企業(yè)。電話(huà):028-86922220
分享名稱(chēng):Linux v1.2成功移植到ARM平臺(tái) (linux v1.2 arm)
分享網(wǎng)址:http://m.5511xx.com/article/ccoioce.html


咨詢(xún)
建站咨詢(xún)
