Detailed explanation of Uboot transplantation on S3C2440 (VI)

Publisher:SparkleMagicLatest update time:2016-06-14 Source: eefocusKeywords:S3C2440 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
1. Transplantation Environment
  • Host: VMWare--Fedora 9

  • Development board: Mini2440--64MB Nand, Kernel: 2.6.30.4

  • Compiler: arm-linux-gcc-4.3.2.tgz

  • u-boot:u-boot-2009.08.tar.bz2

2. Transplantation Steps

10) u-boot uses tftp service to download the kernel and uses nfs service to mount nfs file system.
Knowledge points:
  1. Installation, configuration and testing of tftp service;

  2. Installation, configuration and testing of nfs service;

  3. Parameter passing from u-boot to kernel (key point).

We know that the benefit of using tftp to download the kernel and using nfs to mount the file system is that when we recompile the kernel or file system, we do not need to burn these image files to the flash again. Instead, we put these image files in the main directory of the tftp or nfs service of the development host and load them through the network. We do not need to burn them to the flash frequently. This can protect the service life of the flash and facilitate the debugging of the kernel or file system to improve the development efficiency. It can be seen that it is a very meaningful thing to let u-boot realize this function.

It is very simple to implement such a function, and there is a lot of information on the Internet. However, there are many details that can lead to failure if you don't pay attention to them. Here I will describe the process of my implementation and analyze some problems.

  • Installation, configuration and testing of tftp service

To use the tftp service and test it, you need to install two software packages, one is the tftp server, and the other is the tftp client. The client is installed here only to test whether the tftp server is running normally on the local host to ensure that u-boot can access the tftp service (u-boot already has the function of the tftp client. In fact, tftp has been used in the previous articles to download the kernel or file system to the development board. If you have done it there, you can skip it here).

First, use the rpm command to check whether the tftp server and client have been installed on your host. If not, download the two software packages to install them or use the yum command to install them online. Yum will automatically search for the latest software package suitable for your host platform to download and install. If the host has already installed it, it will prompt that the latest version of the software package has been installed. As shown in the figure below:



    		    Detailed explanation of Uboot transplantation on S3C2440 (VI)

Configuring the tftp server mainly involves configuring the home directory and access rights of tftp. Since the tftp service depends on the xinetd service, its configuration files are usually located in the /etc/xinetd.d/ directory after the tftp service is installed:

  • Installation, configuration and testing of nfs service

As root, enter setup in the console and select nfs service in the system service options, as shown below: 650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/1032542.png" style="padding:0px;margin:0px;border:0px;" />



    		    Detailed explanation of Uboot transplantation on S3C2440 (VI)

When configuring the shared home directory of the NFS server, also pay attention to the permission issue:

  • Parameter passing from u-boot to kernel

We know that there is a Default kernel command string parameter item in the kernel configuration option Boot options, and there is also a bootargs parameter item in the u-boot parameter. They are both used for kernel startup, so what is the difference between them? Which one is used when the kernel is started? The two parameter items are shown in the following figure (the parameters in the kernel specify that the file system is mounted from the Flash partition of the development board, and the parameters in the u-boot specify that the file system is mounted from NFS):



    		    Detailed explanation of Uboot transplantation on S3C2440 (VI)



    		    Detailed explanation of Uboot transplantation on S3C2440 (VI)

In fact, the parameters in the kernel are provided by default by the kernel and are specified during kernel configuration, while those provided by u-boot are passed to the kernel when u-boot is started to replace the parameters provided by the kernel. So when u-boot does not provide the bootargs parameter, the kernel starts with the parameters specified during kernel configuration, and when u-boot provides the bootargs parameter, it uses the u-boot parameters.

So, how does u-boot pass parameter information to the kernel? And how does the kernel receive the parameters passed by u-boot? This involves a little knowledge of ARM registers.

We know that ARM has 7 working modes and 37 registers (31 general registers and 6 status registers), as shown below:
650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/1032545.png" style="padding:0px;margin:0px;border:0px;" />

The conversion between ARM working modes is carried out by using these registers, and the transmission of u-boot parameters also uses three general registers R0, R1 and R2. I will not talk about ARM working modes and registers here, and will talk about them later. Here you can understand that u-boot stores the parameters in these three registers when starting, and then takes out the parameters in the registers when the kernel starts. Of course, they are not so simple operations. Let's look at the code and analyze them one by one.

First, let's analyze how u-boot processes and sends the parameters to be passed, and what are the parameters that u-boot wants to pass? In addition to the most easily known bootargs (kernel commandline) parameter item, the parameters to be passed include MACH_TYPE (what we call machine code), system root device information (flags, page size), memory information (starting address, size), RAMDISK information (starting address, size), and compressed RAMDISK root file system information (starting address, size). It can be seen that there are many parameters to be passed. At this time, u-boot provides a method called parameter linked list (tagged list) to organize these parameters. The linked list structure is defined in: include/asm-arm/setup.h, and the implementation of the linked list organization is in lib_arm/bootm.c:
650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/1032546.png" style="padding:0px;margin:0px;border:0px;" />650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/1032547.png" style="padding:0px;margin:0px;border:0px;" />

We can see that the organization of the linked list is implemented by a series of functions. U-boot stipulates that the linked list must start with the ATAG_CORE tag and end with the ATAG_NONE tag. In the middle are some parameter tag items, which can be reflected in the code. Then in these functions there is a bd parameter which is crucial, it is a bd_info type structure, defined in include/asm-arm/u-boot.h, and this structure is referenced by a global_data type structure, defined in include/asm-arm/global_data.h, as follows:
650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/1032548.png" style="padding:0px;margin:0px;border:0px;" />650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/1032549.png" style="padding:0px;margin:0px;border:0px;" />
So, what is the bd parameter used for? From the definition, we can know that bd records the machine code, the address of the u-boot parameter list in the memory and other information. Then, where is it recorded? It is recorded in the initialization code of our own development board, such as: board/samsung/my2440/my2440.c650
) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/10325410.png" style="padding:0px;margin:0px;border:0px;" />

Note: bd_t is referenced by gd_t, and in global_data.h we can see that u-boot defines a global pointer variable *gd of gd_t, so here we can directly use gd to set bd.

OK, let's analyze how the parameter list is passed. The series of functions that organize the parameter list are called in a function called do_bootm_linux, which is also defined in lib_arm/bootm.c.
650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/10325411.png" style="padding:0px;margin:0px;border:0px;" />

From this function, we can see that the support of the two macros CONFIG_SETUP_MEMORY_TAGS and CONFIG_CMDLINE_TAG is required to make the parameter passing effective, so they need to be defined in include/configs/my2440.h. It turned out that I didn't define them, and there was a problem when using NFS to mount the file system. At the same time, theKernel function pointer is the key to u-boot parameter passing. We know that when a function is executed in memory, it is actually an address. In the code, this function pointer is first pointed to the kernel's entry address, and finally 0, the machine code and the address of the u-boot parameter item in memory are brought to this entry address. Therefore, when executing this entry address, that is, when the kernel is started, these three parameters can be received. So, how did this entry address (kernel startup address or kernel entry address) come from, who specified it, and how much is it? Looking at the code, it is obtained from the member ep of a bootm_headers_t type structure, and this structure is passed from the place where do_bootm_linux is called. bootm_headers_t is defined in include/image.h and do_bootm_linux is called in common/cmd_bootm.c as follows:
650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/10325412.png" style="padding:0px;margin:0px;border:0px;" />650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/10325413.png" style="padding:0px;margin:0px;border:0px;" />
From the code, we can clearly see that the member ep of bootm_headers_t is assigned a value, but it is still not intuitive enough to know what the entry address is. We only know that it is obtained from legacy_hdr_os_copy in bootm_headers_t using the image_get_ep function, so where is it assigned a value? It turns out that it is in the image_set_ep function, which is defined in tools/mkimage.c as follows:
650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/10325414.png" style="padding:0px;margin:0px;border:0px;" />
Let's think about it again, what is this mkimage.c used for? It turns out that it is used to create the u-boot format kernel - uImage. Remember how to use mkimage to create uImage? It is mentioned in "Detailed Explanation of Porting u-boot-2009.08 on 2440 (IV)" as follows:

mkimage [-x]-A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image

Options:
-A: set architecture to 'arch' // used to specify the CPU type, such as ARM
-O: set operating system to 'os' // used to specify the operating system, such as Linux
-T: set image type to 'type' // used to specify the image type, such as Kernel
-C: set compression type 'comp' // specify the compression type
-a: set load address to 'addr' (hex) // specify the image load address
-e: set entry point to 'ep' (hex) // kernel entry address, generally the image load address + 0x40 (information header size)
-n: set image name to 'name' // image name in the header structure
-d: use image data from 'datafile' // image file name without header information
-x: set XIP (execute in place) // set execution location

For example:
mkimage -n 'linux-2.6.30.4'-A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage uImage.img

Haha, I believe you have seen the light at this moment! This entry address is 0x30008000, which is one of the reasons why u-boot must use the uImage format to start the kernel. Note: There is a kernel entry address 0x30008000, and it is mentioned above that a u-boot parameter list in the memory address 0x30000100, imagine what will happen if the kernel entry address specified here covers the address of the parameter list?

Well, by looking at each step above from bottom to top, you can know the entire process of transferring u-boot parameter items on the u-boot side. Then, let's analyze how u-boot parameter items are received on the kernel side.

The kernel startup process is shown in the following figure:
650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/10325415.png" style="padding:0px;margin:0px;border:0px;" />
In the file arch/arm/boot/compressed/head.S, start is the starting point of zImage, and some of the code is as follows:

start:
......

.word 0x016f2818 @ Magic numbers to help the loader
.word start @ absolute load/run zImage address
.word _edata @ zImage end address
1:mov r7, r1 @ save architecture ID
mov r8, r2 @ save atags pointer
..... .

wont_overwrite: mov r0, r4
mov r3, r7
bl decompress_kernel
b call_kernel

......

call_kernel: bl cache_clean_flush
bl cache_off
mov r0, #0 @ must be zero
mov r1, r7 @ restore architecture number
mov r2, r8 @ restore atags pointer
mov pc, r4 @ call kernel

......

First, save r1 (machine code) and r2 (physical address of parameter list in kernel) passed by u-boot to ARM registers r7 and r8 respectively, and then pass r7 as a parameter to decompression function decompress_kernel(), in which r7 is passed to global variable __machine_arch_type, and then restore r7 and r8 to r1 and r2 before jumping to vmlinux entry.

In the arch/arm/kernel/head.S file, part of the code for the kernel vmlinux entry is as follows:

ENTRY(stext)
setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode @ andirqs disabled
mrc p15, 0, r9, c0, c0 @ get processor id
bl __lookup_processor_type @ r5=procinfo r9=cpuid
movs r10, r5 @ invalid processor ( r5=0)?
beq __error_p @ yes, error 'p'
bl __lookup_machine_type @ r5=machinfo
movs r8, r5 @ invalid machine (r5=0)?
beq __error_a @ yes, error 'a'
bl __vet_atags
bl __create_page_tables

......

First, get the type of ARM kernel from the ARM special register (CP15), and check whether there is this ARM kernel type from the processor kernel descriptor (proc_info_list) table (__proc_info_begin—__proc_info_end). If not, exit with an error. The processor kernel descriptor is defined in include/asm-arm/procinfo.h, and the specific function is implemented in arch/arm/mm/proc-xxx.S. Various processor kernel descriptors are combined into a table during the compilation and linking process. Then check whether there is the machine code specified by the r1 register from the machine description (machine_desc) table (__mach_info_begin—__mach_info_end). If not, exit with an error. This also explains why the machine code specified in u-boot must be consistent with that specified in the kernel, otherwise the kernel cannot be started. The machine number mach_type_xxx is described in the arch/arm/tools/mach-types file. Each machine descriptor includes a unique machine number. The machine descriptor is defined in include/asm-arm/mach/arch.h and implemented in the arch/arm/mach-xxxx folder. During the compilation and linking process, different machine descriptors based on the same processor are combined into a table. For example, the machine descriptor of the S3C2440 processor with machine code 1008 is as follows:

MACHINE_START(SMDK2440,"SMDK2440")
/* Maintainer: Ben Dooks */
.phys_io = S3C2410_PA_UART,
.io_pg_offst =(((u32)S3C24XX_VA_UART)>> 18)& 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100, //Note: This address corresponds to the physical address of the parameter list in memory in u-boot

.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer =&s3c24xx_timer,
MACHINE_END

Finally, the MMU is turned on and the system is initialized by jumping to the start_kernel() function in init/main.c. Part of the code of the start_kernel() function is as follows:

asmlinkage void __init start_kernel(void)
{
......
setup_arch(&command_line);
......
}

The function setup_arch is implemented in arch/arm/kernel/setup.c. Some of the code is as follows:

void __init setup_arch(char**cmdline_p)
{
......
setup_processor();
mdesc = setup_machine(machine_arch_type);
......
parse_tags(tags);
......
}

The setup_processor() function finds the matching descriptor from the processor kernel descriptor table and initializes some processor
variables. The setup_machine() returns the machine descriptor with the machine number (assigned in the decompression function decompress_kernel) as a parameter. The physical address of the kernel parameter is obtained from the machine descriptor and assigned to the tags variable. Then the parse_tags() function is called to analyze the kernel parameter list and pass each parameter value to the global variable. In this way, the kernel receives the parameters passed by u-boot.

  • TFTP downloads the kernel and NFS mounts the file system

OK, the tftp service and nfs service are ready, and the parameter transfer from u-boot to kernel is also OK. Next, we need to set the parameter items in the u-boot environment variable and the kernel configuration options so that it can use tftp to automatically download the kernel and automatically mount the nfs file system through the network. The u-boot environment variable settings are as follows:
650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/10325416.png" style="padding:0px;margin:0px;border:0px;" />

The bootcmd parameter item uses tftp to download the uImage in the host tftp main directory to the 0x31000000 position in the development board SDRAM, and then uses the bootm command to execute the boot kernel startup.

The bootargs parameter is the command line parameter for kernel startup. u-boot passes this parameter to the kernel and mounts the file system through nfs. Here you must pay attention to the settings of serverip and ipaddr (that is, the server IP or the development host IP and the development board IP). In addition, please note that the kernel must also configure the corresponding options to use nfs, as follows:

File systems --->
Network File Systems --->
<*> NFS file system support ## Required
[*] Provide NFSv3 client support ## Optional
[*] Root file system on NFS ## Required
Networking -- ->
[*] Networking support
Networking options --->
[*] IP: kernel level autoconfiguration ## Required

The results are as follows:

a. Download the kernel through tftp and start the kernel:
650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/10325417.png" style="padding:0px;margin:0px;border:0px;" />

b. The command line parameters passed by u-boot are received by the kernel:
650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/10325418.png" style="padding:0px;margin:0px;border:0px;" />

c. The kernel mounts the file system through nfs:
650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/10325419.png" style="padding:0px;margin:0px;border:0px;" />

d. Check the mounted nfs file system and find that it is completely consistent with the file system in the host nfs server's main directory, indicating success!
650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/10325420.png" style="padding:0px;margin:0px;border:0px;" />

[root@localhost home]# vi /etc/exports //If this file does not exist, create it and add the following line of configuration information. Note that the format must be correct, otherwise the service will not work properly.

/home/filesystem *(rw,no_root_squash,sync)

Note: "/home/filesystem" is the home directory of the NFS server. Pay attention to the permissions of the directory.

"*" means all IP addresses can access the NFS home directory

"rw" means read and write

"no_root_squash" means that if the user who logs in to the NFS host is a ROOT user, he has ROOT permissions

"sync" means synchronization

[root@localhost home]# service nfs restart //Restart the NFS service to make the configuration file take effect

Test whether the NFS service is normal. Put the prepared file system into the NFS home directory as follows:

[root@localhost home]# ls /home/filesystem/
bin dev home lib mnt root sum100 tmp var
debug etc hostname linuxrc proc sbin sys usr
[root@localhost home]#

//Test the NFS service locally on the host, mount the file system under the NFS home directory to the /mnt directory, 192.168.1.101 is the host IP

[root@localhost home]#mount -o nolock -t nfs 192.168.1.101:/home/filesystem /mnt

You can see that the contents of the /mnt directory are exactly the same as those of the NFS home directory /home/filesystem, indicating that the NFS service is normal:
650) this.width=650;" src="http://www.embeddedlinux.org.cn/uploads/allimg/130316/10325421.png" style="padding:0px;margin:0px;border:0px;" />

[root@localhost home]# vi /etc/xinetd.d/tftp

service tftp
{
disable = no
socket_type = dgram
protocol = udp
wait = yes
user = root
server =/usr/sbin/in.tftpd
server_args = -s /home/tftp-root -c //Mainly modify here to specify the home directory of the tftp server. The -c option means that files can be created
per_source = 11
cps = 100 2
flags = IPv4
}

Create the tftp server home directory just specified, and also pay attention to the read and write permissions of the home directory:

[root@localhost home]#mkdir /home/tftp-root
[root@localhost home]#chmod 777 /home/tftp-root

Start and test the tftp service:

[root@localhost home]#service xinetd restart //Restarting the xinetd service will start all its services, including the tftp service
[root@localhost home]#service iptables stop //Turn off the firewall
[root@localhost home]#tftp host IP address
tftp>get the file to be downloaded

tftp>put the file to upload

tftp>q
[root@localhost home]#


Keywords:S3C2440 Reference address:Detailed explanation of Uboot transplantation on S3C2440 (VI)

Previous article:Detailed explanation of ucosii transplantation on stm32 5
Next article:Detailed explanation of Uboot transplantation on S3C2440 (V)

Recommended ReadingLatest update time:2024-11-16 15:04

1.9.4_ADC and touch screen_S3C2440 touch screen interface_P
From the previous section, we know that the detection of touch screen presses and the calculation of touch point coordinates are accomplished through the five switches S1 to S5. By controlling the opening and closing of the five switches at different times, the XY coordinates of the touch point can be obtained. Chec
[Microcontroller]
1.9.4_ADC and touch screen_S3C2440 touch screen interface_P
14. S3C2440 bare metal - MMU
14.1 MMU Introduction 14.1.1 MMU Features   The Memory Management Unit (MMU) is responsible for mapping virtual addresses to physical addresses and provides hardware-based memory access permission checks. Today's multi-user, multi-process operating systems use MMU to allow each user process to have its own independen
[Microcontroller]
14. S3C2440 bare metal - MMU
S3C2440 character device driver LED driver_writing and compiling (II)
app: open , read , write Driver: led_open, led_read, led_write Driver framework: 1. Write: led_open, led_read 2. How to tell the kernel? a. Define a file_operations b. Tell the kernel about this structure: register_chrdev(major,name,file_operations) c. Who calls it (register_chrdev) Driver entry func
[Microcontroller]
S3C2440 character device driver LED driver_writing and compiling (II)
S3c2440ARM exception and interrupt system detailed explanation 6---key interrupt program example overview and initialization
In the previous video, we gave an example of a mother being interrupted by sound while reading. There are many sources of distant sound. The sound is transmitted to the ear and then to the brain. The whole process involves the sound source, the ear and the brain. In order to ensure that the mother's reading process ca
[Microcontroller]
S3c2440ARM exception and interrupt system detailed explanation 6---key interrupt program example overview and initialization
ARM Linux S3C2440 Interrupt Analysis
Hardware: S3C2440 is an arm920T architecture. Let's first review the interrupt controller principles and related hardware architecture in s3c2440. Interrupt Controller: The interrupt controller of S3c2440A has 60 interrupt sources, such as DMA interrupt, UART interrupt, IIC interrupt, etc. The 60 inte
[Microcontroller]
ARM Linux S3C2440 Interrupt Analysis
s3c2440 bare metal - abnormal interrupt 5 - irq timer interrupt
I have talked about the s3c2440 clock system before. After looking at the clock system and then looking at the timer interrupt, it will be better to combine and apply the knowledge points learned. S3c2440 has 2 types of timers: 1.Watchdog watchdog timer 2.PWM pulse modulated timer The following is a deta
[Microcontroller]
Building a solar tracking system based on 32-bit ARM embedded microcontroller S3C2440
  Based on the principle of computer vision, an embedded image processing platform is built with an ARM microcontroller as the core to achieve real-time tracking of the sun. The system uses a CMOS image sensor to collect solar images, calculates the solar angle through a microcontroller, and controls the turntable thr
[Microcontroller]
Building a solar tracking system based on 32-bit ARM embedded microcontroller S3C2440
S3C2440 timer settings
In the previous articles, whenever the program needed to delay, we used loop statements to achieve it. The delay of this method is simple, but it is not very accurate, which means that the exact delay for a period of time cannot be obtained. Therefore, this method cannot be used when precise delay is required. This is
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号