In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)06/01 Report--
This article is about how to transplant Linux on STM32, the editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article.
When I first moved from hardware to embedded software, I didn't have the slightest preparation. As soon as they entered the post, the leader explained a very difficult task-transplanting linux on stm32!
In an instant, I was confused. I couldn't get on my head. I collected information first. I used to run linux on the board of ok6410, but now it is transplanted on stm32. I used to play with stm32, but I messed with it when I was a graduate student. But now I haven't recovered from the hardware of grasping iron, so I turn to the development of embedded software. What is more troublesome is that stm32 does not have MMU! No MMU! I looked for it. Well, there's a uClinux!
So began to learn a variety of related knowledge, understand that the startup of linux is generally the root file system of the u-boot liunx kernel, then first do a u-boot based on stm32, initialize the clock, peripherals, interrupts and so on. I feel good after watching the video of teacher Wei Dongshan. I understand a lot, from ignorance to a little understanding.
Migrate u-boot to stm32f407
In fact, to put it bluntly, u-boot is a bare-board program, which has the same nature as running horse lanterns and serial communication, while the bare-board program has learned a lot from the stm32 development board of the punctual atom, and I have accumulated a little bit in the graduate stage. First of all, I refer to the program written by the great god who wrote this blog article with reference to http://www.cnblogs.com/fozu/p/3618076.html. I wrote this article very well, and later I analyzed the kernel and benefited a lot. This program is not a u-boot program, but the function is the same as initializing the clock, peripherals. * pass kernel parameters and jump to the kernel. , at the beginning of compiling this program with keil, the result is a bunch of errors, the board that others use is different from the board you use, the led lights and serial ports of hardware may be connected differently, for example, people use serial port 1, you use serial port 2, and the lack of some header files will cause errors, so it takes a while to modify them according to their own reality, and it takes a while to wipe out all the errors and compile successfully.
The board used at this time is that stm32f103,ST released the u-boot and Uclinux kernels supporting it as early as 2008 (the leader bought extra, saying that I had to modify the uClinux kernel that supports stm32f407), but only the Uclinux kernel had source code, and u-boot gave an embarrassment to the hex file. in fact, the architecture of cortx m3 was very different from that of cortx M4, so it would be very difficult for me to modify it. Working alone again, annoying, there is no way to do it! Then get stm32f103 first, copy the bootstrap program that compiled without error before, copy it into the officially provided uClinux kernel at the 0x08003000 location of stm32, as soon as you boot, connect the serial port, open the serial port assistant, and see that there is nothing.
What's wrong with it? Think about it carefully, first of all, to see if the step of jumping to the kernel is successful, then first verify this step, referring to the atomic IAR jump process, compiled a racing lantern jump program, that is, the boot program has not changed, handcuffed to the address 0x08000000, while the racing lantern program is handcuffed to 0x08003000, if the led light is turned off, it means that the jump is correct, so as soon as it starts, the light is not on. After careful investigation, it is found that it is a jump function, and the bootstrap program is written with reference to the u-boot source code, in which the function uses a function pointer to assign an address (0x08003000), and jumps to the past. After two days of twists and turns on the atomic program modification, the light can be turned on and off. I don't know what the problem is now, but at least I can jump now.
Then copy the kernel to 0x08003000, once started, the serial assistant still does not have any output, which is really annoying and depressing, and stm32f103 still wants to do stm32f407. After that, we began to look for reasons, revise all kinds of changes, and lead all kinds of urging, doing this and that between the two boards of stm32f103 and stm32f407. During the break, we looked at teacher Wei's video and looked for materials to see what inspiration we had, but there was still no progress.
Later, I found on the Internet that a buddy actually succeeded in transplanting u-boot on stm32f407, and there was a startup picture to be posted, so I thought, why can't I? So continue to look, and finally found the u-boot source code on the Internet, according to their own stm32f407 board to modify the serial port, clock, etc., install the corresponding cross-compile chain, pay attention to the arm-non-eabi without linux, because the bare board program has nothing to do with linux, and then a run, and finally in the serial port assistant to see the long-lost u-boot startup map, ecstasy! When I think about the days when I really grew up under pressure, I feel that my technology has improved a lot.
As soon as the leader came over, he saw that there was u-boot. That is to say, to add an external SRAM driver to run the linux kernel, this sram is only 512K, is it so small that it can run the linux kernel? This is later, first add the sram driver to the u-boot.
First refer to the atomic sram program to modify and try to try, the results can be run but write and read, there are always errors in the data of several addresses, so I have been thinking hard about the possibility that the external SRAM driver uses stm32's FSMC configuration, which has btcr register settings, divided into bcr and btr settings, atomic development board uses 1M16 bit, while mine is 512k8 bit In the btr register setting, it should be set to 8 bits instead of 16 bits, so set the relevant position 0, which makes the data normal.
The next step is to add the driver of sram to u-boot. This u-boot is well written, but it is configured with external 8m SDRAM, so I will add the code to configure sram on the function of sdram_init () and delete all the code that originally configured sdram. After two days of writing and modifying successfully, once booted, the serial assistant outputs startup information normally, verifies whether the sram driver is feasible with u-boot 's md and mw instructions, and also encounters some problems, such as writing ff,md in the first 100 addresses to check that there are several address data that are not correct, not displaying ff, and using the previous sram bare board program. If you think that the software program must be no problem, that is the hardware problem. Fortunately, I worked on the hardware for a period of time, otherwise I was cheated by the company's hardware engineer. After careful inspection with a multimeter, I found that several data lines in sram were falsely soldered. No wonder the data was wrong. Take the iron and drag it, OK! The data is normal, uh-huh! Want to become a qualified embedded software engineer or the combination of software and hardware, can not be separated from the hardware ah!
good! So far, the u-boot based on stm32f407 has been successfully transplanted, plus the external 2m SRAM driver (later, the 512K was upgraded to 2m, because the kernel memory was not enough to run to half of the kernel panic, which is later on), the previous u-boot boot diagram. Life * article in the CSDN blog, I hope that in the future I will continue to learn and improve my technology, and work hard!
Migrate uClinux kernel to stm32f407
The above introduced the first transplantation of stm32f407-based u-boot, the following will talk about the most difficult part of porting stm32f407 kernel, this kernel source code I also found on the Internet, see the introduction is modified by foreign gods, really thank this god, there are actually a lot of resources on the Internet, to be good at mining, good at searching.
I unwittingly down the kernel code. When I first got the code, I didn't have much confidence in running uClinux on stm32f407. First, I didn't have the information on stm32f407 running uClinux on the Internet (at least I haven't found it). On the Internet, they all have a bad attitude about running uClinux on stm32. Indeed, stm32 runs the uClinux system, resources are somewhat scarce, while the flash inside stm32f407 only has 1m of space, of which u-boot accounts for 128K, so the kernel is stored in 0x08020000. The remaining 900k of space is used, and my board and external 2m SRAM, but what is more fatal is that the code is based on stm32f429 uClinux. Many people have successfully run it on stm32f429, but have never succeeded in stm32f407, but I have no way out. I have no choice but to change it blindly because of the project needs and leadership requirements. In fact, it is much better for stm32f103 to be changed into stm32f429. At least the architecture of stm32f429 is roughly the same as that of stm32f407 (internal storage and clock and gpio are slightly different), so I changed it according to the board in my hand. During this period, I encountered a lot of problems and thought of giving up, but at least I stuck to it. I read a lot of books, checked a lot of materials, and learned a lot of things about u-boot and kernel code.
Special thanks to Mr. jserv. I sent him several emails when I was desperate. He answered two very important questions and suggested that the external 512K be replaced with at least 2m SRAM, otherwise the kernel would really not be able to run, kernel panic in the middle of the run. .
Then it is for stm32f407 to modify the kernel code, stm32f429 uses serial port 3, I use serial port 1, change! The clock is wrong, change it! Storage address is different, change! stm32f429 not only has external SRAM, space 8m also has NOR flash, rich and powerful, resources are used casually, unlike my stm32f407 only external 2m SRAM (leaders say hardware is like that, cost-saving, speechless.) Fortunately, the uClinux code is run in the way of XIP, that is, the code snippet is executed locally in the internal flash, and the data segment and the rest of the bss segment are run on the sram, so there is enough space.
In the meantime, there are also such problems:
Stuck for a week, I was puzzled at that time. When I created the cache, there was a kernel error that could not run any longer. I carefully compared the uClinux source code of stm32f103 and found no errors. There was no progress for more than a week, and I panicked about the kernel panic. Fortunately, the leader did not urge me after knowing the situation, but bought me a copy of "ARM Linux Kernel Source Code Analysis" and told me to study it carefully and solve the problem. So I read the article about building kmem cache. The source code of the linux kernel is so complex that I have a big head. Later, I think this is not a solution. Is it another hardware problem? Because the original sram was upgraded from 512k to 2m, the hardware engineer of the company changed it again, so I used an electric soldering iron to weld the stm32 chip, sram chip, and the pull-up resistor between them again. As soon as I was powered on, it worked normally to the next step. Alas, the sram driver that transplanted u-boot before was also a hardware trick for me. I can't believe how long I will be trapped if I don't know anything about hardware.
Then he was fooling around, and it took nearly two months, and it was like this:
-I was lucky to think about it.
The next problem should be the lack of the root file system, this uClinux code is originally equipped with the root file system, is romfs, but there is not enough storage space.
The root file system of uClinux could not be mounted because the root file system originally configured by the system is romfs, which is based on stm32f429. The internal flash storage space of stm32f429 has 2m flash storage space, which occupies more than 300m kB. This storage is obviously sufficient, but for stm32f407, its internal flash storage space is 1m, so storage space is not enough (u-boot takes up space 0x08000000-0x08020000, kernel space is about 0x08020000-0x080BB000. About 620 KB, so there is only about 250 KB of space left for the root file system), so according to this situation, I think it is necessary to build another initramfs that takes up less memory space as the root file system of uClinux to mount.
Build the initramfs root file system of stm32f407-uClinux
As mentioned above, when the kernel runs to free init memory:8k, it is stuck and cannot go on. After consulting the relevant information, it is speculated that it is caused by the lack of the root file system. The original kernel source code is a bin file with a root file system, which is romfs but no source code. As mentioned earlier, my current project uses stm32f407, and the internal flash capacity and external SRAM are not enough to copy into the original romfs and hang it as the root file system to use.
The next step is to find an economical and applicable file system as the root file system of the kernel. Looking up the relevant information on the Internet, we can see that YAFFS2 supports nandflash,jffs supports nor flash, which does not seem to be applicable to the stm32f407 in my hand. So I carefully studied the source code of stm32f103 and found that there are two ways to start it. One is to use iniramfs as the root file system and xip to start. In the case of only 512k of internal flash in stm32f103, Uclinux is actually running, and the other is that jfss2 is hung on the external nor flash. Obviously, in this case, I can only refer to * *, using initramfs as the root file system. So start building initramfs-related files. Take a closer look at the kernel configuration of stm32f103 XIP boot mode: make menuconfig, CONFIG_INITRAMFS_SOURCE= "initramfs-filelist" and initramfs-filelist under Uclinux/linux-2.6.x. Open it and look like this:
At first, I couldn't understand the meaning of shell. I found an article on the Internet and wrote it clearly. Copy it and learn:
Compile initramfs into the kernel
The easiest way to use initramfs is to replace the empty one in the kernel with the already made cpio.gz. This is naturally supported by 2.6kernel, so you don't have to make any special settings.
There is a CONFIG_INITRAMFS_SOURCE (I.E. General setup- > Initramfs source file (s) in menuconfig) in kernel's config option. This option points to all the files you need to package initramfs with the kernel. By default, this option is left blank, so the initramfs is empty after the kernel is compiled, which is the case where rootfs does nothing.
CONFIG_INITRAMFS_SOURCE can be an absolute path or a relative path starting from kernel's top build dir (where you typed in build or make). There are three kinds of targets you can point to: a cpio.gz that has been done, a folder that has all the contents ready for making cpio.gz, or a configuration file for text. The third way is the most flexible. Let's introduce these three methods in turn.
1) use a cpio.gz file that has been made
If you already have your own initramfs_data.cpio.gz file (because you created it yourself, or saved the cpio.gz file produced by a previous kernel build), you can point CONFIG_INITRAMFS_SOURCE at it and the kernel build will autodetect the file type and link it into the resulting kernel image.
You can also leave CONFIG_INITRAMFS_SOURCE empty, and instead copy your cpio.gz file to usr/initramfs_data.cpio.gz in your kernel's build directory. The kernel's makefile won't generate a new archive if it doesn't need to.
Either way, if you build a kernel like this you can boot it without supplying an external initrd image, and it'll still finish its boot by running your init program out of rootfs. This is packaging method # 2, if you'd like to try it now.
2) assign a file or folder to the kernel
If CONFIG_INITRAMFS_SOURCE points to a directory, the kernel will archive it up for you. This is a very easy way to create an initramfs archive, and is method # 3.
Interestingly, the kernel build doesn't use the standard cpio command to create initramfs archives. You don't even need to have any cpio tools installed on your build system. Instead the kernel build (in usr/Makefile) generates a text file describing the directory with the script "gen_initramfs_list.sh", and then feeds that descript to a program called "gen_init_cpio" (built from C source in the kernel's usr directory), which create the cpio archive. This looks something like the following:
Scripts/gen_initramfs_list.sh $CONFIG_INITRAMFS_SOURCE > usr/initramfs_list
Usr/gen_init_cpio usr/initramfs_list > usr/initramfs_data.cpio
Gzip usr/initramfs_data.cpio
To package up our hello world program, you could simply copy it into its own directory, name it "init", point CONFIG_INITRAMFS_SOURCE at that directory, and rebuild the kernel. The resulting kernel should end its boot by printing "hello world". And if you need to tweak the contents of that directory, rebuilding the kernel will re-package the contents of that directory if anything has changed.
The downside of this method is that it if your initramfs has device nodes, or cares about file ownership and permissions, you need to be able to create those things in a directory for it to copy. This is hard to do if you haven't got root access, or are using a cross-compile environment like cygwin. That's where the fourth and final method comes in.
3) use the configuration file initramfs_list to tell the kernel where initramfs is
This is the most flexible method. The kernel's gen_initramfs_list.sh script creates a text description file listing the contents of initramfs, and gen_init_cpio uses this file to produce an archive. This file is a standard text file, easily editable, containing one line per file. Each line starts with a keyword indicating what type of entry it describes.
The config file to create our "hello world" initramfs only needs a single line:
File / init usr/hello 500 00
This takes the file "hello" and packages it so it shows up as / init in rootfs, with permissions 500, with uid and gid 0. It expects to find the source file "hello" in a "usr" subdirectory under the kernel's build directory. (If you're building the kernel in a different directory than the source directory, this path would be relative to the build directory, not the source directory.)
To try it yourself, copy "hello" into usr in the kernel's build directory, copy the above configuration line to its own file, use "make menuconfig" to point CONFIG_INITRAMFS_SOURCE to that file, run the kernel build, and test boot the new kernel. Alternately, you can put the "hello" file in its own directory and use "scripts/gen_initramfs_list.sh dirname" to create a configuration file (where dirname is the path to your directory, from the kernel's build directory). For large projects, you may want to generate a starting configuration with the script, and then customize it with any text editor.
This configuration file can also specify device nodes (with the "nod" keyword), directories ("dir"), symbolic links ("slink"), named FIFO pipes ("pipe"), and unix domain sockets ("sock"). Full documentation on this file's format is available by running "usr/gen_init_cpio" (with no arguments) after a kernel build.
A more complicated example containing device nodes and symlinks could look like this:
Dir / dev 755 0 0
Nod / dev/console 644 0 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 initramfs/busybox 755 0 0
Dir / proc 755 0 0
Dir / sys 755 0 0
Dir / mnt 755 0 0
File / init initramfs/init.sh 755 0 0
One significant advantage of the configuration file method is that any regular user can create one, specifying ownership and permissions and the creation of device nodes in initramfs, without any special permissions on the build system. Creating a cpio archive using the cpio command line tool, or pointing the kernel build at a directory, requires a directory that contains everything initramfs will contain. The configuration file method merely requires a few source files to get data from, and a description file.
This also comes in handy cross-compiling from other environments such as cygwin, where the local filesystem may not even be capable of reproducing everything initramfs should have in it.
To sum up.
All four ways to provide content to rootfs have one thing in common: when kernel starts, a series of files are unzipped to rootfs, and if kernel can find the executable file "/ init" in it, kernel will run it; this means that kernel no longer cares where "root=" points to.
In addition, once the init process in initramfs is running, kernel will assume that startup is complete. Next, init will control the whole universe! It has Thunderbolt's invincible Process ID # 1 reserved for it, and it will create all the rest of the system! Also, its status will be inalienable, ahem, if PID 1 exits, the system will panic.
Next I'll introduce some other things that init programs can do in rootfs.
Footnote 1: The kernel doesn't allow rootfs to be unmounted for the same reason the same reason it won't let the first process (PID 1, generally running init) be killed. The fact the lists of mounts and processes are never empty simplifies the kernel's implementation.
Footnote 2: The cpio format is another way of combining files together, like tar and zip. It's an older and simpler storage format that dates back to the original unix, and it's the storage format used inside RPM packages. It's not as widely used as tar or zip because the command line syntax of the cpio command is unnecessarily complicated (type "man 1 cpio" at a Linux or Cygwin command line if you have a strong stomach). Luckily, we don't need to use this command.
Footnote 3: The kernel will always panic if PID 1 exits; this is unrelated to initramfs. All of the signals that might kill init are blocked, even "kill-9" which will reliably kill any other process. But init can still call the exit () syscall itself, and the kernel panics if this happens in PID 1. Avoiding it here is mostly a cosmetic issue: we don't want the panic scrolling our "Hello World!" Message off the top of the screen.
Footnote 4: Statically linking programs against glibc produces enormous, bloated binaries. Yes, this is expected to be over 400k for a hello world proram. You can try using the "strip" command on the resulting binary, but it won't help much. This sort of bloat is why uClibc exists.
Footnote 5: Older 2.6 kernels had a bug where they would append to duplicate files rather than overwriting. Test your kernel version before depending on this behavior.
Footnote 6:User Mode Linux or QEMU can be very helpful testing out initramfs, but are beyond the scope of this article.
Footnote 7: Well, sort of. The default one is probably meant to be empty, but due to a small bug (gen_initramfs_list.sh spits out an example file when run with no arguments) the version in the 2.6.16 kernel actually contains a "/ dev/console" node and a "/ root" directory, which aren't used for anything. It gzips down to about 135 bytes, and might as well actually be empty. On Intel you can run "readelf-S vmlinux" and look for section ".init.ramfs" to see the cpio.gz archive linked into a 2.6kernel. Elf section names might vary a bit on other platforms.
Obviously, stm32f103 uses the third method, in which the instructions are nothing more than setting file permissions, setting soft connections, and so on. During this period, I also learned a little bit of bash shell and gained a little bit. After understanding the truth, it was easy to follow suit. I used the second method:
1. Create the folder rootfs first, and then create directories such as bin, dev, etc, proc, sys and so on under this folder.
2. Compile busybox and copy the generated bin file to rootfs/bin
3. Create a new linuxrc file, set the permission chmod 777, and then add init=/linuxrc to the parameters passed from u-boot to the kernel.
4. In the dev directory, add the device node, otherwise there will be no output information!
1 mknod-m 666 console c 5 1
2 mknod-m 666 null c 1 3
5. CONFIG_INITRAMFS_SOURCE= "the absolute path to the folder you just built" on the kernel make menuconfig
When compiling the kernel, initramfs is compiled directly with the kernel, and there is no need to separate a copy of the bin file, which is convenient to start. You can see the relevant display information in the serial port debugging assistant:
To talk about my own feelings, although it is convenient and practical to use the initramfs root file system, there is a disadvantage that it is only read but not written, which is very disadvantageous to the development. the leader said that he would add a spi flash and then mount a root file system in it (can spi flash hang jfss2?). That's in the future. At present, with my technical level, I can only do this, after adding the root file. Stm32 internal flash still has more than 200k storage space, should be able to add some drivers and applications, then my task is to write simple drivers and applications, well, I have to continue to study and work hard.
The above is how to transplant Linux on STM32. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.