当前位置:首页 > 科技数码

initramfs 如何在STM32上移植Linux?超详细的实操经验分享

刚从硬件转到嵌入式软件的时候,没有任何准备。一入职,领导就交代了一个非常艰巨的任务——在stm32上移植linux!

一瞬间,我傻了。我不能咬紧牙关。首先,我收集了数据。以前在ok6410的板上运行linux,现在移植到stm32上。以前玩stm32,研究生期间也在做。但是现在我从烙铁的硬件中恢复过来之前,已经转向了嵌入式软件的开发。更麻烦的是stm32没有MMU!没有MMU!找一下,好的,有个uClinux!

然后开始学习各种相关知识,了解到linux的启动一般是u-boot——“liunx内核——”根文件系统,所以首先要做一个基于stm32的U-boot,初始化时钟,外设,中断等等。看了韦东山老师的视频感觉很好,从无到有了解了很多。

将u-boot移植到stm32f407

其实说白了,u-boot就是一个裸板程序,和走马灯,串口通讯一样的性质。裸板程序从守时atom的stm32开发板学到了很多,在我的研究生阶段积累了一点。首先,我指的是写这篇博文的大神http://www.cnblogs.com/fozu/p/3618076.html,写的程序。这篇文章写得不错,后面也分析了内核。反复阅读,受益匪浅。这个程序不是u-boot程序,但是和初始化的效果一样。。最后,传递内核参数,跳转到内核。。。当初用keil编译这个程序,结果是一堆错误。别人用的板和你用的板不一样。硬件和串口的led灯可能连接方式不同。比如人家用串口1,你用串口2,缺了一些头文件,就会出错。所以根据我们自己的实际情况,花了一段时间才改正过来,最后去掉所有错误,编译成功。

这时候用的板子是stm32f103。早在2008年ST就发布了u-boot和支持它的uClinux内核(领导额外买的,说我要根据相应的要求修改支持stm32f407的Uclinux内核),但是只有Uclinux内核有源代码,u-boot给了一个十六进制文件的尴尬。其实cortx m3和cortx m4之前的架构差别很大,这样修改对我来说无疑是非常困难的。我太大了,听不进去,一个人去,做不到!然后先获取stm32f103,复制之前编译无误的引导程序,在stm32的0x08003000位置复制官方提供的uClinux内核。一旦启动,连接串口,打开串口助手,看到什么都没有。。。

怎么了?仔细想想,首先要看最后一步跳转到内核是否成功,然后先验证这一步,参考atoms的IAR跳转历史,编译一个ticker跳转程序,即引导程序不变,地址0x0800000复制,而ticker程序在地址0x08003000复制。如果led灯亮灭,说明跳转是正确的,所以开始的时候灯不亮。疯狂是怎么回事?经过仔细调查,发现是一个跳转函数。引导程序是参考u-boot源代码编写的。里面的函数被分配了一个带函数指针的地址(0x08003000),最后跳过了。经过两天对原子程序修改的辗转反侧,灯居然可以开关了。我不知道现在是什么问题,但至少现在我可以实现跳跃了。

然后把内核复制到0x08003000,一旦启动,串口助手还是没有输出,真的很烦很压抑。stm32f103无法修复,想做stm32f407。。。之后开始找原因,做修改,领导各种提醒。我是在stm32f103和stm32f407这两块板之间做的,然后休息的时候看了魏老师的视频,找资料看看有什么启发,还是没有进展。

后来在网上找了个哥们,在stm32f407上成功移植了u-boot,有启动图,就想,为什么不行?然后我继续搜索,终于在网上找到了u-boot的源代码。我根据自己的stm32f407板修改了串口和时钟,安装了相应的交叉编译链。请注意,arm-non-eabi没有linux,因为它是一个与linux无关的裸板程序。然后我就跑了,最后在串口助手里看到了久违的u-boot启动图。我欣喜若狂!想想那段时间,我真的是在压力下长大的,感觉自己的技术进步很大。

当领导过来的时候,他看到了一只u型靴。。。)说要加外部sram驱动,为了运行linux内核,SRAM只有512K,这么小能运行linux内核?这是另一个故事。首先将sram驱动程序添加到u-boot。

首先参考原子sram程序修改运行。结果可以运行,但可以重新读写。几个地址的数据总有错误。所以我一直在努力思考,想到了一种可能。stm32的FSMC配置用于驱动外部静态随机存取存储器。它有btcr寄存器设置,分为bcr和btr设置。原子开发板用1M16位,我的用512k8位。在btr寄存器设置中,它应设置为8位

下一步是给u-boot添加sram驱动。这个u-boot写的不错,但是配置了外置的8M sdram,所以我会在sdram_init()函数中加入sram配置代码,删除掉所有原来的sdram配置代码。折腾了两天,写修改成功。机器一开机,串口助手就正常输出启动信息,用u-boot的md和mw指令验证sram驱动是否可行。也有一些问题,如在前100个地址中写入ff,当md查看时有几个地址数据是错误的,没有显示ff,使用以前的sram裸板程序时也是如此。当我以为软件程序肯定没问题的时候,是硬件问题。还好硬件做了一段时间,不然被公司的硬件工程师坑了。用万用表仔细测试后,发现sram的几条数据线被虚拟焊接。怪不得数据错了。拿个烙铁拖着,好!数据正常,嗯!想成为一名合格的嵌入式软件工程师,还是要软硬件结合,不能脱离硬件!!!!

好的。到目前为止,基于stm32f407的u-boot已经移植成功,加上一个外接的2M SRAM驱动(后来512K升级到2M,因为内核内存不够内核死机死了,这是后话),最后拍了u-boot启动图。我人生中在CSDN的第一篇博文,我希望我将来能继续学习和提高我的技能并努力工作!

将uClinux内核移植到stm32f407

以上先描述了基于stm32f407的u-boot移植,下面将提到移植stm32f407内核最困难的部分。我也在网上找到了这个内核的源代码,介绍是外国大神修改的。真的很感谢这位大神,因为网上资源很多,要善于挖掘和搜索。

我不小心写下了内核代码。刚拿到代码的时候对在stm32f407上运行uClinux没有太大信心。第一,网上没有关于在stm32f407上运行uClinux的信息(至少我没找到)。都是对网上在stm32上运行uClinux态度不好。的确,stm32运行的是uClinux系统,资源稀缺。而stm32f407的内部flash只有1M 空,其中u-boot占用128K,所以内核存储在0x08020000,剩下的900k 空用,我的板外有2M SRAM,更糟糕的是得到的代码是基于stm32f429的uClinux。很多人在stm32f429上成功运行过,但从来没有在stm32f407上运行过,但我没有退路。项目需求和领导要求只能盲目改变。其实把stm32f103换成stm32f429好很多。最起码stm32f429的架构和stm32f407大致相同(内存和时钟与gpio等略有不同。),于是我按照自己的板子改了。遇到很多问题,想过放弃,但至少坚持下来了。因为赶时间看了很多书,查了很多资料,了解了很多关于u-boot和内核代码的东西。

我特别感谢jserv先生。当我无处可去时,我给他发了几封电子邮件。他回答了我两个极其重要的问题,建议外置512K至少要换成2M SRAM,不然内核真的会运行。中间,仁慌…...

然后修改stm32f407的内核代码。stm32f429用串口3,我用串口1。时钟错了,换吧!存储地址不同。换吧!Stm32f429不仅有外部SRAM,还在空之间的8M处有NOR闪存。它财大气粗,随便用资源,不像我的stm32f407,只有外置的2M SRAM(领导说硬件就是那样,节约成本,无语。。),还好uClinux代码是在XIP模式下运行的,也就是把代码段放在内部flash中本地执行,把bss段的数据段和其他段放在sram中运行,所以,空就够了。

在此期间,有这样一个问题:

我被卡住了一个星期,当时很疑惑。创建缓存时出现内核错误,无法再运行。我仔细对比了一下stm32f103的uClinux源代码,没有发现错误。一个多星期没进步,内核慌了我就慌了。还好领导了解情况后没有催我,而是给我买了一本《ARM Linux内核源代码解析》,让我好好研究一下。为了解决这个问题,我看了关于构建kmem缓存的文章。linux内核源代码太复杂,让我头大。后来我觉得这不是解决办法,又是硬件问题吗?因为原来512k的sram升级到了2M,公司的硬件工程师又修改了一遍,于是我又用电烙铁把stm32芯片、sram芯片和它们之间的上拉电阻焊接了一遍,一上电就正常运行到下一步。唉,之前移植了u-boot的sram驱动也是我的硬件坑。不知道一些硬件的时候真不敢相信。。。

然后,前后用了将近两个月,是这样的:

-我很幸运能想到它。。。

遇到的下一个问题是缺少根文件系统。这段uClinux代码本来配备了一个根文件系统,就是romfs,但是存储空不够。

UClinux的根文件系统无法挂载,因为最初配置的根文件系统是romfs,基于stm32f429。stm32f429的内部闪存在空之间是2M,romfs在空之间占用300kb以上,这显然是足够的,但是对于stm32f407来说,其内部闪存空是1M,所以这样存储的话,存储空空间不够(u-boot占用0x 0800000-0x 08020000,内核占用0x 080200000左右)所以根据这种情况,我认为有必要构建一个占用内存空的较小的initramfs作为uClinux的根文件系统来挂载。

建立stm32f407-uClinux的initramfs根文件系统

如上所述,当内核运行以释放init内存:8k时,就会卡住,无法再运行。查阅相关资料,推测是因为缺少根文件系统造成的。原内核源代码是一个带根文件系统的bin文件,是romfs但是没有源代码。如前所述,我目前的项目使用的是stm32f407,内部闪存容量和外部SRAM不足以复制这个暂停为根文件系统使用的原始romfs。

下一步是找到一个经济适用的文件系统作为内核的根文件系统。在网上查了一下相关资料,可以知道YAFFS2支持nandflash,jffs支持nor flash,好像不适合我手里的stm32f407。于是我仔细研究了stm32f103的源代码,发现它有两种启动模式。一种是使用iniramfs作为根文件系统,启动xip。在stm32f103中,当flash只有512k的时候,实际运行的是Uclinux。另一个是jfss2挂在外部nor flash上。显然我只能参考第一种方式,用INIRAMFS作为根文件系统。然后开始构建initramfs相关文件。在menuconfig中,仔细研究了stm32f103 XIP启动模式的内核配置。config _ initramfs _ source = " initramfs-filelist "而initramfs-file list位于uclinux/Linux-2.6.x下,乍一看是这样的:

一开始,我无法理解shell的含义。在网上找到一篇文章,写的很清楚。复制并学习它:

将initramfs编译到内核中

使用initramfs最简单的方法是用已经制作好的cpio.gz替换内核中的空一个。这是2.6内核自然支持的,不用做什么特殊设置。

有一个config _ initramfs _ source(即一般设置-->:menu config中的initramfs源文件).该选项指向内核打包initramfs所需的所有文件。默认情况下,这个选项会留下空,所以内核编译后,initramfs也是空,也就是前面提到的rootfs什么都不做。

Config _ initrams _ source可以是绝对路径,也可以是从内核的顶部构建目录(您键入构建或制作的地方)开始的相对路径。有三个目标:一个已经制作好的cpio.gz,一个为制作cpio.gz准备好所有内容的文件夹,或者一个文本配置文件。第三种方法最灵活。下面依次介绍这三种方法。

1)使用已经完成的cpio.gz文件

如果您已经有了自己的initramfs_data.cpio.gz文件(因为您自己创建了它,或者保存了由以前的内核构建生成的cpio.gz文件),您可以将CONFIG_INITRAMFS_SOURCE指向它,内核构建将自动检测文件类型并将其链接到生成的内核映像中。

您也可以将CONFIG_INITRAMFS_SOURCE保留为空,而是将您的cpio.gz文件复制到您的内核的构建目录中。如果不需要,内核的makefile不会生成新的存档。

无论哪种方式,如果你构建一个这样的内核,你可以在不提供外部initrd映像的情况下启动它,并且它仍然可以通过在rootfs之外运行你的init程序来完成它的启动。这是第二种包装方法,如果你现在想试试的话。

2)给内核分配一个文件或文件夹

如果CONFIG_INITRAMFS_SOURCE指向一个目录,内核将为您将其存档。这是创建initramfs归档文件的一种非常简单的方法,也是方法3。

有趣的是,内核构建没有使用标准的cpio命令来创建initramfs档案。你甚至不需要在你的内置系统上安装任何cpio工具。相反,内核构建(在usr/Makefile中)生成一个用“gen_initramfs_list.sh”描述目录的文本文件,然后将该文件馈送给一个名为“gen_init_cpio”(从内核usr目录中的C源代码构建)的程序,该程序创建了cpio档案。这看起来像下面这样:

s/gen _ INITRAMFS _ list . sh $ CONFIG _ INITRAMFS _ SOURce & gt;usr/initramfs_list

usr/gen _ init _ cpio usr/initramfs _ list & gt;usr/initramfs_data.cpio

g usr/initramfs_data.cpio

为了打包我们的hello world程序,您可以简单地将其复制到自己的目录中,将其命名为“init”,在该目录中指向CONFIG_INITRAMFS_SOURCE,然后重建内核。最终的内核应该通过打印“hello world”来结束引导。如果您需要调整该目录的内容,如果有任何变化,重建内核将重新打包该目录的内容。

这种方法的缺点是,如果您的initramfs有设备节点,或者关心文件所有权和权限,您需要能够在目录中创建这些东西,以便复制。如果您没有根访问权限,或者正在使用像cygwin这样的交叉编译环境,这是很难做到的。这就是第四种也是最后一种方法。

3)使用配置文件initramfs_list告诉内核initramfs在哪里

这是最灵活的方法。内核的gen_initramfs_list.sh创建一个文本描述文件,列出initramfs的内容,gen_init_cpio使用这个文件生成一个存档。该文件是一个标准文本文件,易于编辑,每个文件包含一行。每一行都以一个关键字开始,表示它描述的条目类型。

创建“hello world”initram fs的配置文件只需要一行代码:

file /init usr/hello 500 0

这将文件“hello”打包,使它在rootfs中显示为/init,权限为500,uid和gid为0。它希望在内核构建目录下的“usr”子目录中找到源文件“hello”。(如果您在一个不同于源目录的目录中构建ker nel,这个路径将是相对于构建目录的,而不是源目录。)

若要亲自尝试,请将“hello”复制到内核构建目录中的usr中,将上面的配置行复制到它自己的文件中,使用“make menuconfig”将CONFIG_INITRAMFS_SOURCE指向该文件,运行内核构建,并测试引导新内核。或者,您可以将“hello”文件放在其自己的目录中,并使用“s/ gen_initramfs_list.sh dirname”创建一个配置文件(其中dirname是从内核的构建目录到您的目录的路径)。对于大型项目,您可能希望使用生成初始配置,然后使用任何文本编辑器对其进行自定义。

该配置文件还可以指定设备节点(带有“nod”关键字)、目录(“dir”)、符号链接(“slink”)、命名的FIFO管道(“pipe”)和unix域套接字(“sock”)。通过在内核构建后运行“usr/gen_init_cpio”(不带参数),可以获得关于该文件格式的完整文档。

包含设备节点和符号链接的更复杂的示例如下所示:

dir /dev 755 0 0

nod/dev/console 644 0 c 5 1

nod /dev/loop0 644 0 0 b 7 0

dir /bin 755 1000 1000

slink /bin/sh busybox 777 0 0

file/bin/busybox initram fs/busybox 755 0 0

目录/进程755 0 0

dir /sys 755 0 0

dir /mnt 755 0 0

file/init init ramfs/init . sh 755 0 0

配置文件方法的一个显著优点是,任何普通用户都可以创建一个,指定所有权和权限,并在initramfs中创建设备节点,而无需对构建系统拥有任何特殊权限。使用cpio命令行工具创建一个cpio归档,或者将内核构建指向一个目录,需要一个包含initramfs将包含的所有内容的目录。配置文件方法只需要几个源文件和一个设计文件来获取数据。

这在从其他环境(如cygwin)进行交叉编译时也很方便,在这些环境中,本地文件系统甚至可能无法复制initramfs应该包含的所有内容。

综上

这四种向rootfs提供内容的方式有一个共同点:内核启动时,一系列文件被解压到rootfs,如果内核能在其中找到可执行文件“/init”,内核就会运行它;这意味着内核将不再关心“root=”指向哪里。

另外,一旦initramfs中的init进程运行,内核就会认为启动已经完成。接下来,init将控制整个宇宙!它有无敌的Process ID #1预留给它,它会创建整个系统接下来的所有部分!此外,它的地位是不可剥夺的。嗯哼,如果PID 1退出,系统会恐慌。

接下来,我将介绍一些init程序在rootfs中可以做的其他事情。

脚注1:内核不允许卸载rootfs的原因和它不会让第一个进程(PID 1,一般运行init)被杀死的原因一样。装载和进程列表从不为空的事实简化了内核的实现。

脚注cpio格式是将文件组合在一起的另一种方式,比如tar和。这是一种更古老、更简单的存储格式,可以追溯到最初的unix,它是在转速包中使用的存储格式。它不像tar或那样被广泛使用,因为cpio命令的命令行语法并不必要的复杂(如果你有强烈的兴趣,可以在Linux或Cygwin命令行中键入“man 1 cpio”)。幸运的是,我们不需要使用这个命令。

脚注3:如果PID 1退出,内核总是会死机;这与initramfs无关。所有可能杀死init的信号都被阻止,甚至“kill -9”也会可靠地杀死任何其他进程。但是init仍然可以调用exit() syscall本身,如果在PID 1中发生这种情况,内核就会死机。在这里避免它主要是一个表面问题:我们不想恐慌滚动我们的“你好世界!”屏幕顶部的消息。

脚注4:针对glibc的静态链接程序会产生庞大、臃肿的二进制文件。是的,对于hello world proram来说,这一数字预计将超过40万。您可以尝试在生成的二进制文件上使用“strip”命令,但这没有多大帮助。这种膨胀是uClibc存在的原因。

脚注5:旧的2.6内核有一个错误,他们会附加到重复的文件,而不是覆盖。在依赖此行为之前,请测试您的内核版本。

脚注6:用户模式Linux或QEMU对测试initramfs非常有帮助,但这超出了本文的范围。

脚注7:嗯,算是吧。默认的版本可能是空的,但是由于一个小错误(gen_initramfs_list.sh在没有参数的情况下运行时会抛出一个示例文件),2.6.16内核中的版本实际上包含一个“/dev/console”节点和一个“/root”目录,这两个目录不用于任何用途。它压缩到大约135字节,实际上可能是空的。在英特尔上,您可以运行“readelf -S vmlinux”并查找“init.ramfs”部分,查看链接到2.6内核的cpio.gz档案。Elf部分的名称在其他平台上可能会有所不同。

显然,stm32f103使用的是第三种方法。里面的说明无非是设置文件权限,设置软连接等。期间也学了一点bash shell,收获了一点。明白了道理之后,就好办了。我直接跟着猫画老虎。我用了第二种方法:

1.首先创建rootfs文件夹,然后在这个文件夹下创建bin,dev等,proc,sys等目录。

2.编译busybox并将生成的bin文件复制到rootfs/bin

3.创建一个新的linuxrc文件,设置权限chmod 777,然后将init=/linuxrc添加到从u-boot传输到内核的参数中

4.在dev目录中添加一个设备节点,否则不会有输出信息!

1 mknod -m 666控制台c 5 1

2 mknod -m 666 null c 1 3

5.在内核make menuconfig上,CONFIG_INITRAMFS_SOURCE= "您刚刚构建的文件夹的绝对路径"

编译内核,initramfs是直接用内核编译的,不需要单独一份bin文件,更方便启动,相关显示信息可以在串口调试助手里看到:

最后说一下自己的感受。虽然使用initramfs根文件系统方便实用,但缺点是只读不可写,非常不利于开发。领导说要加一个spi闪存,在里面挂载一个根文件系统(spi闪存能挂jfss2吗?),那是未来的事,以后再说。目前这种情况只能达到我的技术水平。添加根文件后,stm32内部闪存中有超过200k的存储空间空,所以我应该可以添加一些驱动程序和应用程序。然后我的任务就是写简单的驱动和应用。嗯,我还要继续学习,再努力。。。(本文摘自:http://blog.csdn.net/jccg89104)

1.《initramfs 如何在STM32上移植Linux?超详细的实操经验分享》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《initramfs 如何在STM32上移植Linux?超详细的实操经验分享》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/keji/1022758.html

上一篇

女司机高速停车炒股被罚 事件详情始末介绍!

下一篇

潘石屹儿子谈不捐款 没捐不让说了是么?

panli panli创始人— —潘晓:【海淘行业如何玩转微信小程序】

  • panli panli创始人— —潘晓:【海淘行业如何玩转微信小程序】
  • panli panli创始人— —潘晓:【海淘行业如何玩转微信小程序】
  • panli panli创始人— —潘晓:【海淘行业如何玩转微信小程序】

在线中英文翻译 PDF文件中英文在线翻译,PDF中英文在线翻译怎么进行

  • 在线中英文翻译 PDF文件中英文在线翻译,PDF中英文在线翻译怎么进行
  • 在线中英文翻译 PDF文件中英文在线翻译,PDF中英文在线翻译怎么进行
  • 在线中英文翻译 PDF文件中英文在线翻译,PDF中英文在线翻译怎么进行

mysql导入sql文件 mysql数据库导入导出

1.数据库导入 MySQL-uroot-p 123456-default-character-set = utf8 test 123 & lt;test123.sql 2.数据库导出 导出整个数据库MySQL dump-uroot-p 123456 test 123 & gt。test123...

中国驻休斯顿总领事回应焚烧文件 事件详情始末介绍!

中国驻休斯顿总领事回应焚烧文件 事件详情始末介绍!

7月22日,美国国务院厚颜无耻地要求中国驻休斯敦总领馆关闭,只允许三天。针对美国的这一举动,中国外交部发言人王文斌昨天在例行记者会上表示,中国对此表示强烈谴责,并敦促美国立即撤销这一错误决定。如果美国不撤销,中国肯定会做出...

星巴克正式推出微信小程序 一键调用手机号码即可注册

星巴克正式推出微信小程序 一键调用手机号码即可注册

星巴克正式推出微信小程序,这意味着用户可以分享星巴克APP的会员权限以及向特殊明星发送订单和从特殊明星接收订单等服务功能。 随着星巴克小程序在微信上的推出,全国各地的用户都可以通过扫描小程序代码或在微信上搜索“星巴克”进...

印度禁用59款中国APP 不再提供中国应用程序和服务

印度禁用59款中国APP 不再提供中国应用程序和服务

6月30日,据外媒报道,印度政府今天宣布,印度将禁止59款中国应用。为了应对安全和隐私问题,印度不再提供59种受欢迎的中文应用和服务,包括TikTok、微信和微博、QQ等。# “根据《信息技术法》第69A条,引用2009年...

考生撕毁2人答题卡 招生办回应称已按程序上报处理

考生撕毁2人答题卡 招生办回应称已按程序上报处理

7月8日上午,2020高考第二天。有网友在微博等平台发消息称,8日上午,河南平顶山市某高考考场,考生撕毁了两人的答题卡。涉及的考点是平顶山一中。 针对此事,7月8日17时许,河南省招生办回应称“已按规定办理”、“已按程序上...

除了qq 除了QQ微信网盘,我们还能怎么快捷传输文件?方法都在这

  • 除了qq 除了QQ微信网盘,我们还能怎么快捷传输文件?方法都在这
  • 除了qq 除了QQ微信网盘,我们还能怎么快捷传输文件?方法都在这
  • 除了qq 除了QQ微信网盘,我们还能怎么快捷传输文件?方法都在这