当前位置:首页 > 娱乐

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

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

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

上一篇

中国首富都是几两的命 新中国首富诞生,身价达4000亿,相当于2.3个王兴,3.6个王健林

下一篇

蒋勤勤与闺蜜晒孕照 身姿依旧曼妙 闺蜜情谊惹人羡

csv文件 Python对CSV文件的处理

  • csv文件 Python对CSV文件的处理
  • csv文件 Python对CSV文件的处理
  • csv文件 Python对CSV文件的处理
范冰冰维权案新进展 已启动强制执行申请程序 仍在依法取证备诉

范冰冰维权案新进展 已启动强制执行申请程序 仍在依法取证备诉

范冰冰范冰冰6月19日晚,北京兴泉律师事务所发布案情报告称,范冰冰名誉权保护18起案件正在依法审理中,1起案件(被告:微博用户“秦岭二月”,实名:陈永鹏)已于2018年6月19日启动强制执行申请程序。针对近期网上出现的一批涉嫌侵犯范冰冰名誉权的虚假信息,律师事务所也在收集证据,准备依法提起诉讼。...

印记者疑将机密文件给中国被捕 还原事发经过及背后原因!

因为这两天因向中国提供机密文件而被捕的印度记者在网上的关注度相当高,所以很多朋友可能也会关注因向中国提供机密文件而被捕的印度记者。当然,他们中的一些人不太了解因向中国提供机密文件而被捕的印度记者,所以没关系。如果你想知道印度记者现在因向中国提供机密文件而被捕,你可以点击下面的点击了解。...

富二代是什么意思 程序员们,知道这是什么意思吧

富二代是什么意思 程序员们,知道这是什么意思吧

那年,我第一次带女朋友去我家吃饭。我女朋友不喜欢吃大蒜。她不小心抓到一个大蒜,咬了一口。她不停地去厕所,吐了...我妈很不高兴,对我女朋友说:“我做的菜不好吃吗?”女朋友摸着她胖乎乎的肚子说:“我可能有!”...然后,我妈妈笑了笑,给了她桌上一半的菜... 嫂子做晚饭,弟弟在厨房帮忙切菜。突...

坤音斥音悦台违约:将启动司法程序 保障合法权益

坤音斥音悦台违约:将启动司法程序 保障合法权益

尹坤发表了一份声明27日晚,尹坤娱乐发表声明,谴责悦泰违约,称其未按合同约定支付ONER专辑销售金额,并将超过1000万的销售金额挪作他用。而且没有进行物流公司的成本结算,导致部分专辑没有发行,侵犯了消费者的合法权益。声明最后,尹坤表示,银悦泰的违约行为给己方和消费者造成了各方面的巨大损失,己方强烈谴责其行为...

2021年中央一号文件发布 37次提到乡村振兴 还原事发经过及背后原因!

2021年中央一号文件发布 37次提到乡村振兴 还原事发经过及背后原因!

2月21日,《中共中央国务院关于全面推进乡村振兴加快农业农村现代化的意见》,即2021年中央一号文件正式发布。这是我国“十四五”时期的第一份中央一号文件,也是一号文件持续第十八年聚焦“三农”议题。...

中央一号文件强调打赢种业翻身仗 对此大家怎么看?

中央一号文件强调打赢种业翻身仗 对此大家怎么看?

目前,我国农作物良种覆盖率在96%以上,自主选育品种面积占比超过95%,尤其是水稻、小麦两大口粮作物品种实现完全自给。中国农业科学院作物科学研究所副所长刘录祥表示,目前我国进口六、七万吨种子看起来很多,但跟全年国家20亿亩的粮食生产面积来比,它的比重微不足道,0.1%都不到。截至2019年底,我国自主研发的蔬菜品种已经达到69个。...

中央一号文件强调打赢种业翻身仗!蔬菜洋种子依赖症已大大改善

  • 中央一号文件强调打赢种业翻身仗!蔬菜洋种子依赖症已大大改善
  • 中央一号文件强调打赢种业翻身仗!蔬菜洋种子依赖症已大大改善
  • 中央一号文件强调打赢种业翻身仗!蔬菜洋种子依赖症已大大改善