Linux migration account

Source: Internet
Author: User
Tags uncompress

Linux migration account

First of all, it depends on whether the kernel Linux of the chip is supported. If not, the workload will be extremely heavy. Give up.
If the CPU-core Linux supports port Linux, the driver is mainly implemented based on the peripheral modules integrated by the SOC.
The following uses an arm926ejs chip as an example to transplant it on Linux 26.22.5.
Assume that the chip is called mychip.
Step 1: Establish the environment:
1. Add your chip support to the config file
A) mkdir ARCH/ARM/mach_mychip. Add the kconfig and makefile files.
Modify ARCH/ARM/kconfig:
Menu "system type"
Choice
Prompt "arm system type"
Default arch_mychip
Config arch_mychip
Bool "my chip"
Select arm_amba
Help
This enables support for mychip
-------
Source "arch/ARM/Mach-mychip/kconfig"
In this way, make menuconfig arch = arm will show your chip.
B) In ARCH/ARM/MM/kconfig
# Arm926t
Config cpu_arm926t
Depends on --- | arch_mychip
Deafult if ...... | arch_mychip
In this case, your chip belongs to arm 926.
C) create a directory Mach-mychip under include/ASM-arm /.
Modify ARCH/ARM/makefile and add:
Machine-$ (config_arch_mychip): = mychip
In this way, when your chip is selected, the include/ASM-arm/. Arch link will be linked during compilation.
Include/ASM-arm/arch-mychip
2. CPU Configuration
A) In ARCH/ARM/tools, add the chip ID to mach_types.
B) configure the starting physical address and clock frequency of the CPU.
Compile
The files ASM/ARCH/memory. H, ASM/ARCH/Timex. h are not found.
Create include/ASM-arm/arch-mychip/memory. h
# Define phys_offset ul (0x60000000)
This is based on the address space of the chip SDRAM. For example, the address space of the chip I use is 6000 0000-67ff FFFF 128 M.
# DEFINE _ DEFINE _to_bus (x) _ DEFINE _to_phys (X)
# DEFINE _ bus_to_virt (x) _ phys_to_virt (X)
The two are: virtual view <-> DMA view memory address translations
Create include/ASM-arm/arch-mychip/Timex. h
# Define clock_tick_rate (50000000/16)
In Linux, macro clock_tick_rate is used to indicate the frequency of the input clock pulse.
In Linux, the number of clock interruptions in one second is represented by Hz. For arm # define Hz 100, that is, 10 ms, the clock is interrupted once,
In Linux, macro latch is used to define the value to be written to the counter. The number of clock cycles generates a clock interruption. Obviously latch should be calculated by the following formula:
Latch = (number of clock cycles within 1 second) hour (number of clock interruptions within 1 second) = (clock_tick_rate) hour (HZ)
C) Configure vmalloc Virtual Address Allocation
Compile
The following error occurs when ASM/ARCH/vmalloc. H is missing:
Create include/ASM-arm/arch-mychip/vmalloc. h
# Define vmalloc_end (page_offset + 0x18000000)
Distribution of virtual addresses starting with page_offset. Linux is divided into kernel space and user space. The kernel space is 3 GB-4 GB, so page_offset is defined as 0xc0000000
Vmalloc_end:
(To http://www.lslnet.com/linux/f/docs1/i34/big5260475.htm)
Vmalloc (see mm/vmalloc. file C) the purpose is to allow the core to be allocated in a large memory space must be a large memory (physical addresses do not need to be stored ), the addresses used by the platform are defined by vmalloc_start and vmalloc_end, which are platform-specific.
(To http://idcnews.net/html/edu/20080101/281406.html)
In Linux, The vm_struct structure is used to represent the linear address used by vmalloc. The linear address range used by vmalloc is vmalloc_start vmalloc_end. Borrow>, as shown in the following illustration:

D) configuration interruption, Io, DMA
Compile inux and port the journal account
The following three files are missing: ASM/ARCH/irqs. H, ASM/ARCH/DMA. H, ASM/ARCH/IO. h.
Create irqs. H. In this file, define nr_irqs and interrupt macros, such
# Define i2c_int 39
Mark I2C interrupt as 39, which will be useful in the program in the future
Request_irq (i2c_int ......)
Create include/ASM-arm/arch-DW/IO. H. This file mainly defines the conversion from Io address to memory address
Create include/ASM-arm/arch-DW/DMA. H. This file mainly defines some DMA aspects.
E) query the macro Implementation of the interrupt number
This is related to a specific CPU, that is, by querying the interrupt status device, it is known that the interrupt is now
Compile
Prompt missing include/ASM-arm/arch-mychip/entry-macro.S
This file is mainly low level IRQ helper macro get_irqnr_and_base. This macro obtains the IRQ interrupt number, stores it in the R0 register, and passes it as a parameter to asm_do_irq.
Add the following two macros:
. Macro get_irqnr_preamble, base, TMP
. Endm
. Macro arch_ret_to_user, tmp1, tmp2
. Endm
F) hardware. h
Compile
The system prompts that include/ASM-arm/arch-mychip/hardware. H is missing.
G) set the system idle and reset functions.
The compilation prompts that ASM/ARCH/system. H is missing:
This file mainly implements two functions: arch_idle and arch_reset.
Arch_reset configures some registers based on chips to restart the system.
3
A) after completing the preceding steps, remove all the drivers and compile the driver. If ARCH/ARM/arch-mychip/built_in.o is not found,
Add a mychip. c file to arch/ARM/arch-mychip and modify the makefile.
OBJ-Y: = mychip. c
B) Compile tool check
Compilation appears
No machine record defined
Originally at the end of arch/ARM/kernel/vmlinux. LDS:
Assert (_ proc_info_end-_ proc_info_begin), "missing CPU support ")
Assert (_ arch_info_end-_ arch_info_begin), "no machine record defined ")
This shows that our compilation tool is too old, a look, the compilation tool is arm-2006q3, 2006 3rd Quarter, indeed too old.
Upgrade to arm-2008q3, compilation still has this problem.
An error occurred while compiling. Because there is no arch.info. init area, where does this area be defined? In Linux/include/ASM-arm/Mach/arch. H, the machine_start macro definition is found:
# Define machine_start (_ type, _ name )/
Static const struct machine_desc _ mach_desc _ ###_ type/
_ Used/
_ Attribute _ (_ Section _ (".arch.info. init") = {/
. Nr = mach_type _ ##_ type ,/
. Name = _ name,
# Define machine_end/
};
Therefore, add _ enable_mmu to mychip. C.
Machine_start (XXXX, "ARM-DW ")
/* Maintainer: arm Ltd/Deep Blue Solutions Ltd */
Machine_end
XXXX is based on ARCH/ARM/tools/Mach-types
Step 2: Start the kernel
1. After starting uimage,
In the print
Start kernel ....
Later
Undefined instruction
Start kernel... is printed when you start kernel in the do_bootm_linux function of uboot/lib_arm/armlinux. C.
What about the end ???
2. The SDRAM and serial ports have been initialized in uboot, but there are also serial drivers in Linux. After the serial driver is initialized, printk can be used to print things. How can we print them before? You need to implement the putc function.
In include/ASM-arm/arch-mychip, add uncompress. h to implement the putc and flush functions.
3. The makefile. boot file is missing.
In ARCH/ARM/boot/makefile, include $ (srctree)/$ (MACHINE)/makefile. boot
Create ARCH/ARM/Mach-mychip/makefile. boot
Main definition of this file
Zreladdr-Y 0x60008000 execution address after kernel decompression (0x60000000 SDRAM base address + 0x00008000)
Params_phys-y 0x60000100 Kernel Parameter physical address (0x60000000 SDRAM base address + 0x00000100)
Initrd_phys-y initrd physical address
4 or not. Use a uimage that can be started for comparison.
Okay:
# Booting image at 62000000...
Image name: Kernel Image
Created: 2009-03-18 6:23:44 UTC
Image Type: ARM Linux kernel image (uncompressed)
Data size: 1452480 bytes = 1.4 MB
Load address: 60008000
Entry Point: 60008000
Uimage with undefined instrution:
# Booting image at 62000000...
Image name: Kernel Image
Created: 2009-03-20 9:42:06 UTC
Image Type: ARM Linux kernel image (uncompressed)
Data size: 2217548 bytes = 2.1 MB
Load address: 30008000
Entry Point: 30008000
The load address and entry point of the two are different,
This is called in the do_bootm function of common/cmd_bootm.c of uboot.
Print_image_hdr (image_header_t *) ADDR );
The uimage header is in the image_hear_t structure.
Load address should be defined as zreladdr-y 60008000 in makefile. boot. How can it be changed to 30008000? And the size is not correct. How can it be 2.1 MB?
Later, I found that I used./uimage instead of arch/ARM/boot/uimage, And./uimage is not a compressed kernel. in./makefile, I used:
$ (Cross_compile) objcopy-O Binary-R. Note-R. comment-s vmlinux. Bin
Mkimage-A $ (ARCH)-O Linux-T kernel-C none-A 30008000-e 30008000-n "kernel image giant"-D Linux. Bin uimage
, Which needs to be modified:
$ (Cross_compile) objcopy-O Binary-R. Note-R. comment-s vmlinux. Bin
Mkimage-A $ (ARCH)-O Linux-T kernel-C none-A 60008000-e60008000-n "kernel image giant"-D Linux. Bin uimage,
Switch to arch/ARM/boot/uimag
# Booting image at 62000000...
Image name: Linux-2.6.22.5
Created: 2009-03-20 10:13:20 UTC
Image Type: ARM Linux kernel image (uncompressed) // mkimage no longer compresses zimage
Data size: 1108164 bytes = 1.1 MB
Load address: 60008000
Entry Point: 60008000
OK
Start kernel ....
Why is there no more ??

How can I automatically generate an uncompressed uimage?

Why not at first, it should be compressed uimage? By default, compressed uimage is generated.
It turns out that in include/ASM-arm/Mach-mychip/uncompress. in H, Serial Port 1 is used, while Serial Port 2 is used. modify this file so that serial port 2 can be output.
After start kernel... appears
Uncompressing Linux ...................................... ................................. done, booting the kernel.
It indicates that the kernel is compressed and decompressed correctly.
If you use a non-compressed kernel, change it to./uimage. After downloading:
# Booting image at 62000000...
Image name: Kernel image giant
Created: 2009-03-23 5:42:39 UTC
Image Type: ARM Linux kernel image (uncompressed)
Data size: 2217548 bytes = 2.1 MB
Load address: 60008000
Entry Point: 60008000
OK
5. After the kernel is decompressed, or after downloading the non-compressed kernel,
Because printk was called at the beginning of start_kernel, but it was not output immediately but put in a buffer, __log_buf

After register_console is called, register_console calls release_console_sem () and release_console_sem --> call_console_drivers to print the items in the buffer.

That is to say, the printk before calling register_console is not printed, but stored in the buffer. When registering the console, the previous printing is sent immediately.

Printk after register_console can print data immediately.

So where can I call register_console?

Uart_add_one_port-> register_console
Therefore, before the UART driver is complete, there is a putstr function in Misc. C, which calls putc directly and then flush.

Or in start_kernel, try again to see where the problem is?
At the beginning of start_kernel, if putc ('C'); flush (); is not output, it indicates an error occurred before start_kernel is called.
Add the following to/init/Main. C:
# Include
Asmlinkage void _ init lawrence_debug (void)
{
Putc ('A ');
Putc ('B ');
Putc ('/N ');
Flush ();
}
Use this function to check what went wrong (asmlinkage must be used, otherwise it cannot be called in the assembly ).
Then, in./ARCH/ARM/kernel/head. S, add BL lawrence_debug to see where the program runs.
It turns out that it crashes after _ lookup_machine_type and enters _ error_a, that is, machine_type is not found,
In the head-Common.S, the input parameter of the __lookup_machine_type function is r1 (machine architecture number), which is passed in uboot.

To better understand the problem, open the config_debug_ll macro.
Http://blog.csdn.net/aaronychen/archive/2008/08/27/2838341.aspx
It seems that r1 of _ lookup_machine_type is incorrect. Change it:
_ Lookup_machine_type:
MoV R1, #0x32
ORR R1, R1, #0x400
You can find the machine. Why didn't uboot be passed in ??
6 open the config_debug_ll macro, the prompt is missing debug-macro.S,
This file is mainly used for functions such as printascii. It defines four macros.
Addruart: Get the UART address. Check the uarat1 or 2 address of the chip. There is a problem here. If MMU is not enabled, the address is easy to handle,
What if MMU is enabled? You need to provide a virtual address. The virtual address of Io is used in the following method:
In machine_start,. map_io = mychip_map_io is defined.
Mychip_map_io-> iotable_init (map_desc...). The map_desc structure defines the ing between IO addresses and virtual addresses,
In/init/main. start_kernel --> startup_arch (ARCH/ARM/kernel/setup. c) --> paging_init (in arch/ARM/MM/init. c) --> devicemaps_init --> map_io
Senduart: Sent content
Waituart: waiting
Busyuart: judge whether busy or busy is a loop
It is very easy to test this file. In head. S, BL _ error_a can check whether the file has been printed.
7. found:
LDR R13, _ switch_data @ address to jump to after
@ MMU has been enabled
Adr lr, _ enable_mmu @ return (PIC) Address
------ Go here
Add PC, R10, # procinfo_initfunc
R10 is the base address of procinfo, so add PC, R10... execute _ cpu_flush, that is, _ arm926_setup (ARCH/ARM/MM/proc_arm926.s). When this function ends with mov PC, LR will call _ enable_mmu.
_ Enable_mmu --> _ turn_mmu_on-> mov PC, R13 will call _ switch_data
No response is returned when BL _ error_a is called under _ map_switched.
In the _ turn_mmu_on function,
_ Turn_mmu_on:
MoV r0, R0
BL _ error_a is used for printing.
MCR P15, 0, R0, C1, C0, 0 @ write control Reg
MRC P15, 0, R3, C0, C0, 0 @ read ID Reg
MoV R3, r3
MoV R3, r3
BL _ error_a is not printed here
MoV PC, R13
This indicates that after MMU becomes effective, addruart will use a virtual address. What is the virtual address of Io at this time ??
According
. Phys_io = 0x05c00000, // uart2 PHY ADDR
. Io_pg_offst = (0xf0000000)> 18) & 0 xfffc, // uart2 virt ADDR
Map 5c00000 to 0xf0000000
Modify debug-macro.S
. Macro addruart, RX
MRC P15, 0,/RX, C1, C0
Tst/RX, #1 @ MMU enabled?
Moveq/RX, #0x05c00000 @ physical
Movne/RX, #0xf0000000 @ virtual
. Endm
In this way, you can print it out.
8 is defined before Main. c start_kernel:
# Define uart2_tx_1_o_levelv (* (volatile unsigned char *) 0xf0000020)
# Define uart2_tx_datav (* (volatile unsigned char *) 0xf0000028)
Static inline void putcv (int c)
{
// Wait until there is space in tx FIFO
While (uart2_tx_fifo_levelv = 0x80)
Barrier ();
Uart2_tx_datav = C;
}
Static inline void flushv (void)
{
While (uart2_tx_fifo_levelv)
Barrier ();
}
Asmlinkage void _ init lawrence_debug (void)
{
Putcv ('A ');
Putcv ('B ');
Putcv ('/N ');
Flushv ();
}
Asmlinkage void _ init start_kernel (void)
{
Char * command_line;
Extern struct kernel_param _ start ___ Param [], _ Stop ___ Param [];
Lawrence_debug ();
.....
Printed.
So far start_kernel has finally run.

Step 3: system initialization
1. The system startup process is roughly as follows:
Start_kernel:
Setup_arch ....
Init_irq --> init_arch_irq
...
Timer_init --> system_timer...
... Rest_init --> call the init call
In machine_start, there are:
. Map_io = mychip_map_io,
. Init_irq = mychip_init_irq,
. Timer = & mychip_timer,
. Init_machine = mychip_init,
In/init/main. start_kernel --> setup_arch (ARCH/ARM/kernel/setup. c) --> paging_init (in arch/ARM/MM/init. c) --> devicemaps_init --> map_io, mychip_map_io-> iotable_init (map_desc ...), the map_desc structure defines the ing between IO addresses and virtual addresses,
We use a macro io_address (include/ASM/ARCH/hardware. h)
: # Define io_address (x) & 0x0fffffff) + (x)> 4) & 0x0f000000) + 0xf0000000)
Convert x ---> 0xfx (X in 0x00000000 ~ 0x0f000000)
X ---> 0xf (x + 1 ~ F) (X is 0x10000000 ~ 0xf0000000)
The I/O addresses of our chips are both 0x00000000 ~ 0x0 f00000000, so the physical address is changed to a virtual address, but 0xf0000000 is added to the high address.
The final ing relationship is:
Other Io --> 0xf0000000 (including NAND Flash Controller, TDM ....)
SRAM ---> 0xd0000000
SDRAM ---> 0xc0000000
Nor Flash has no ing and can only be accessed through mtdblock0 and mtdblock1 ?????
Modify
. Phys_io = 0x05c00000, // uart2 PHY ADDR
. Io_pg_offst = (io_address (0x5c00000)> 18) & 0 xfffc, // uart2 virt ADDR
Map 5c00000 to 0xf5c00000
Modify debug-macro.S
. Macro addruart, RX
MRC P15, 0,/RX, C1, C0
Tst/RX, #1 @ MMU enabled?
Moveq/RX, #0x00000000 @ physical
Movne/RX, #0xf0000000 @ virtual
ORR/RX,/RX, #0x05c00000 @ uart2 offset
. Endm
In this way, it corresponds. Ence_debug can be used at any time to see where the system is running.
Defined before Main. c start_kernel:
# Define uart2_tx_1_o_levelv (* (volatile unsigned char *) 0xf5c00020)
# Define uart2_tx_datav (* (volatile unsigned char *) 0xf5c00028)
The end of setup_arch will be:
Init_arch_irq = mdesc-> init_irq;
System_timer = mdesc-> timer;
Init_machine = mdesc-> init_machine;
In ARCH/ARM/kernel/setup. c
Customize_machine --> init_machine
Arch_initcall (customize_machine );
For init_irq, the main structure is static struct irq_chip, and set_irq_handler (I, handle_level_irq );
Replace sa_interrupt with ir1__disabled in earlier versions.
Replace sa_timer with ir1__timer
Replace set_irq_chipdata with set_irq_chip_data
Timer mainly provides a system clock (tick). In this way, task switching occurs every time a tick occurs.

Step 4: add the console driver
The console driver outputs the printk information. This is the first step. In this way, you can use printk to print the program and see where it is executed.
To add a driver, use platform driver model. In arch init, use amba_device_register to add the driver to the device,
Then, use amba_driver_register in module_init to register the driver. During the driver registration process, the system compares the idtable (including ID and mask) in amba_driver with the periphid in the device to check whether the driver can match, if yes, call the probe function.
For embedded devices, the console outputs data to UART, so you only need to define the struct console mychip_console In The UART driver.
In struct uart_driver mychip_reg, add the. Cons = & mychip_console in the probe function.
Uart_add_one_port (& mychip_reg,...) will register the console.
Start the kernel
Print:
Starting kernel...
Linux version 2.6.22.5 (lawrencekang @ lawrencekang) (GCC version 4.3.2 (sourcery g ++ lite 2008q3-72) #48 wed Apr 8 17:40:52 CST 2009
CPU: ARM926EJ-S [41069265] Revision 5 (armv5tej), Cr = 00053177
MACHINE: ARM-MYCHIP
Memory Policy: ECC disabled, data cache writeback
Cpu0: D vivt write-back Cache
Cpu0: I cache: 16384 bytes, associativity 4, 32 byte lines, 128 Sets
Cpu0: D cache: 16384 bytes, associativity 4, 32 byte lines, 128 Sets
Built 1 zonelists. Total pages: 16256
Kernel command line: Root =/dev/mtdblock2 rootfstype = yaffs2 console = ttymychip0 mem = 64 m mtdparts = dwnand: 3 M (kernel), 3 M (splash),-(rootfs)
2
PID hash table entries: 256 (Order: 8, 1024 bytes)
Console: Color dummy device 80x30
Dentry cache hash table entries: 8192 (Order: 3, 32768 bytes)
Inode-Cache hash table entries: 4096 (Order: 2, 16384 bytes)
Memory: 64 MB = 64 MB total
Memory: 62616kb available (1992 K code, 155 K data, 60 k init)
Mount-Cache hash table entries: 512
CPU: Testing write buffer coherency: OK
NTFS Driver 2.1.28 [flags: R/W].
Io scheduler Noop registered (default)
Serial: mychip UART driver
Mychipb: 1: ttymychip0 at mmio 0x5c00000 (IRQ = 7) is a mychip_uart
Advanced Linux sound architecture driver version 1.0.14 (Thu May 31 09:03:25 2007 UTC ).
ALSA device list:
No soundcards found.
Drivers/RTC/hctosys. C: Unable to open RTC device (rtc0)
VFS: cannot open root device "mtdblock2" or unknown-block (0, 0)
Please append a correct "root =" Boot option; here are the available partitions:
Kernel panic-not syncing: VFS: Unable to mount root FS on unknown-block (0, 0)
Step 5: Add a NIC Driver to support NFS
From the above output, we can see that we need to mount the file system next.
In the development phase, it is best to use NFS, which requires adding a NIC Driver.
Note that sk_buffer has a Mac, H, and NH in the old version (for example 2.6.17), and becomes mac_header and network_header in the new version.
Add the NIC Driver and select NFS support (and NFS root file system) in the file system. After compilation:
.......
TCP cubic registered
Net: Registered protocol family 1
Net: Registered protocol family 17
Drivers/RTC/hctosys. C: Unable to open RTC device (rtc0)
IP-config: unable to set interface netmask (-22 ).
Looking up port of RPC 100003/2 on 172.22.1.35
Looking up port of RPC 100005/1 on 172.22.1.35
VFS: mounted root (NFS filesystem ).
Freeing init memory: 76 K
Warning: Unable to open an initial console.
Kernel panic-not syncing: No init found. Try passing init = option to kernel.
Step 6: Create the root file system
Use busybox to create rootfs and modify the startup script, that is, in/etc/init. add echo "hello" to D/RC and do nothing else. In the/etc/inittab, add: ttymychip0: respawn:-/bin/sh, ttymychip is defined in the UART driver.
After entering, you can use commands such as LS, CP, and ifconfig.
Step 7: add the SOC driver,
1) I2C driver

2) SPI driver

3) LCD Driver

4) Audio driver, which has no ASOC in earlier versions and has ASOC in 2.6.22

5) Flash Driver and local file system (Transplantation of yaffs2)
6)

3)

In the Linux kernel folder

/Arch adds a mach_xxx
/Block unchanged
/Documentation ignore
/Driver transplanted the mmc_spi method.
Driving
Dwipc
WiFi driver
USB
I2C
SPI
UART
ALSA
Nand
LCD
Interrupted ???

/Fs File System: added squashfs
/Init: do_mounts_rd.c has modified squashfs.
/IPC: UNCHANGED
/Kernel: sched. c Added DPM
/Lib: Add crc7.c crc-itu-t.c these are because the driver has added mmc_spi
/Mm unchanged
/Net is strange. Five files are modified here.
/Scripts: UNCHANGED
/Security unchanged
/Sound adds two Device Drivers
/Usr unchanged

Makefile modifies the compiler, etc.

None of the above

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.