Linux v1.2成功移植到ARM平台 (linux v1.2 arm)

Linux v1.2 Successfully Ported to ARM Platform

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.

相关问题拓展阅读:

  • ARM linux内核启动时几个关键地址
  • 四 . 树莓派A20 GPIO中断程序编写(1基本处理)
  • linux下jlink-linux-arm怎么安装

ARM linux内核启动时几个关键地址

1.内核启动地址

ZTEXTADDR

解压代码运行的开始地址。没有物理地址和虚拟地址之分,因为此时MMU处于关闭轮渗状态。这个地址不一定时RAM的地址,可以是支持读写寻址的flash等存储中介。

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中说的很明确

#

# 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

内核启动在RAM中的地址。压缩的内核映像被解压到这个地址,然后执行。

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.

一般定义在项目目录下,比如:

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)

四 . 树莓派A20 GPIO中断程序编写(1基本处理)

关于按键,在DVK521上为:

我又从一份数据手册中看到,PI7,PI8,PI9是没有外部中断功能的。如下图所示:

还好,目前的按键是通过短接帽来连接PI7

PI9的,那么可以将短接帽拿掉,使用杜邦线连接PI10

PI12。

现在我将Key2连接到PI10上。那么KEY2的中断引脚为EINT22。

配置sys_config.fex文件:

现在使用的树莓派A20,是一个双核A7的芯片,而这个属于P架构,中断处理方式也已经和原先的理念大有不同。所以还是要知道关于linux的中断原理,可以从网络中获取相关历史性技术知识。

从A20的数据手册中,可以看到外部中断数到了EINT31。也就是说PIO中断功能有32个。

下面列出的API函数是在 \linux-sunxi\arch\arm\plat-sunxi\Sys_config.c中。

1.gpio_request_ex(),获取sys_config.fex中设置的中断IO口。

2.gpio_set_one_pin_io_status(),设置为输入状态。

3.gpio_set_one_pin_pull(),设置输入引脚的上下拉状态。

4.request_irq()注册中断函数。

request_irq()函数:

之一个参数为SW_INT_IRQNO_PIO,表示是外部并尺端口的中断号。

第二个参数为中断处理函数名。

第三个参数为中断方式,如IRQ_TYPE_EDGE_RISING,上升沿触发,而IRQ_TYPE_EDGE_FALLING则是下降沿触发,IRQF_SHARED为共享。

第四个参数为中断名。

第五个参数为中断传递的数据。

1.获取IO中断源信息

由于内核使用的是虚拟地址寻址硬件地址,获取中断源就需要将IO硬件地址空间映射到虚拟地址上。可以使用ioremap(PIO_BASE_ADDRESS, PIO_RANGE_SIZE)进行映射。

2.屏蔽中断源

a.读取中断源寄存器的状态,可以使用readl(映射的IO地址 + PIO_INT_STAT_OFFSET);

b.判断对应的中断,使用writel(reg_val&(1

写到这里,本应该很顺利,可是,在驱动程序加载进内核的时候,明显是报错。错误我就不贴出来了,可是我可以将中断信息附上:

从这里,可以看出来,PIO中断号60已经注册进内核了。我们现在使用的一个IO中断是被包含在里面的。所以,需要在内核中找到sunxi-gpio是怎么去注册中断,而我们就需绝兆高要将我们的中断程序内容附加到已经注册的中断上去。

在 maroard\maroard-a20-linux-sdk-v1.2\linux-sunxi\drivers\gpio\Gpio-sunxi.c中我们可以找到函数:

里面最重要的函数是:

最终调用的是:

然而,它又被赋值了:

在一定程度的意义上,gpio-sunxi.c已经猜御将中断基本处理做好了,我们要做的只是和它共享中断。

sys_config.fex文件配置如下:

从上面的实验中,已经发现在request_irq中设置边沿等等触发,在安装ko文件的时候,都会报错,从这里看出,在共享中断的时候,是不允许设置其他的内容的。那么,只能去找A20寄存器中关于io口中断的设置。在这些设置已经设置好的情况下,中断应该就能响应了。这里贴出一个比较简单的驱动程序:

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位系统要由32位的libu,官方提示后续版本会修正此问题(很多系统默认已安装)。

2.下载并安装

(1)到segger官网下载JLink for Linux 驱动:

(2)解压JLink_Linux_XXX.tgz(XXX代表相应版本)

(3)执行以下命令安装delivered shared library:

sudo cp libjlinkarm.so.* /usr/lib

sudo ldconfig

执行sudo ldconfig时可能会出现此错误:/usr/lib/libjlinkarm.so.4 is not a symbolic link,可能是由于符号连接文件拷贝以后属性变化乎携,需要重新建立连接:

cd /usr/lib

sudo rm -rf libjlinkarm.so.4

ls libjlinkarm.so.4* (查看当前系统使用的版本)

ln -s libjlinkarm.so.4.XXX libjlinkarm.so.4 (XXX代表相应版本)

这时再执行sudo ldconfig就行了。

(4)执行sudo cp 45-jlink.rules /etc/udev/rules.d/,确保当前用户在plugdev用户组中,执行命令sudo useradd -G plugdev XXX(XXX代表你的用户名)。

【如果用户组plugdev不存在,需要按以下步骤建立:

sudo groupadd plugdev创建用户组

sudo usermod -a -G plugdev XXX 添加用户

然后重启完成添加。】

(5)进入JLink文件夹,执行JLinkExe。

若出现此错误:libreadline.so.5: cannot open shared object file: No such file or directory,32位系统参照网上通用方法解决。64位系统安装sudo aptitude install lib32readline5即可解决(若lib32文件夹下已有libreadline.so.5符号连接文件,需删除后再安装)。

(6)为方便使用,可在PATH路径中创建JLinkExe的符号连接:

sudo ln -s /opt/JLink_Linux_V462a/JLinkExe /usr/bin/JLinkExe

这样在主文件夹中输入JLinkExe就能调出程序。

注意:(1)要获得root权限来运行sudo jlink,否则会出现问题:Can not connect to J-Link via USB.

(2)系统启动过程中出现invalid rule:/etc/udev/rules.d/45-jlink.rules,需要修改该文件,将BUS!=”u”删除或注释掉,然后重启就可以了,不影响使用。

3.使用JLink

在J-Link>输入”?”,即给出命令列表。我在使用过程中,总体觉得Linux下JLink不够成熟,主要表现在资料太小、功能不易用、操作成功与否不提示(当然不排除不熟练的原因)。

3.1 下载loadbin

loadbin用于将二进制文件下载行顷戚到目标存储器,语法如下:

Syntax: loadbin , //Load binary file into target memory

下载之前需要设置下目标版的处理器,否则无法正常烧写,我的型号是STM32F103R6,但在指定的时候只指定为STM32F103RB,如下:

J-Link>exec device = STM32F103RB

有个麻烦,下载完没有明显提示成功与否,可以通过这样解决:在PC通过命令xxd查看待下载文件,下载进去通过JLink命令mem查看,判断这两者是否一样(只比较前面若干字节即可),若一样,则表示烧写成功。举个例子,把/bin/cp文件烧到档陵板子:

关于linux v1.2 arm的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

香港服务器首选树叶云,2H2G首月10元开通。
树叶云(shuyeidc.com)提供简单好用,价格厚道的香港/美国云服务器和独立服务器。IDC+ISP+ICP资质。ARIN和APNIC会员。成熟技术团队15年行业经验。

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/196640.html<

(0)
运维的头像运维
上一篇2025-04-03 13:22
下一篇 2025-04-03 13:24

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注