This article was written a bit slowly because I had to figure out some details, but I will write it in more detail.
1 /*
2************************************************ ************************
3 *
4 * CPU_init_critical registers
5 *
6 * setup important registers
7 * setup memory timing
8 *
9************************************************ ************************
10 */
11 /*
12 * we do sys-critical inits only at reboot,
13 * not when booting from ram!
14 */
15 cpu_init_crit:
16 /*
17 * When booting from NAND - it has definitely been a reset, so, no need
18 * to flush caches and disable the MMU
19 */
20 #ifndef CONFIG_NAND_SPL
twenty one /*
22 * flush v4 I/D caches
twenty three */
24 mov r0, #0 // Clear r0 register. The following three coprocessor operations will be explained in detail later.
25 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
26 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
27
28 /*
29 * disable MMU stuff and caches
30 */
31 mrc p15, 0, r0, c1, c0, 0
32 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
33 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
34 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
35 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
/*------------------------------------------------ -------------------------- */
36 /* Prepare to disable the MMU */
37 adr r1, mmu_disable_phys //Get the address of mmu_..., that is, the address of line 55
38 /* We presume we're within the first 1024 bytes */
39 and r1, r1, #0x3fc //Only keep bits [9:2]
40 ldr r2, _TEXT_PHY_BASE //_TEXT_PHY_BASE --> CONFIG_SYS_UBOOT_BASE
//The previous article has analyzed its two possible addressing methods.
//A problem arises here: SDRAM is initialized in lowlevel_init, so where is the program running at this time?
//Answer later~,~
41 ldr r3, =0xfff00000
42 and r2, r2, r3 //Only keep [32:20] bits, that is, save the first address of different fetches
43 orr r2, r2, r1 //After taking or, the register already contains two parts:
44 b mmu_disable //r2 is the first address + offset address (mmu_diable_phys)
//From the final implementation point of view, this code is a meaningless operation
/*------------------------------------------------ ---------------------------- */
45
46 .align 5 //.align here is aligned according to 2^5 = 32, which is 4 bytes here
//Different from ALIGN(4) in .lds file, 4 in lds file means 4 bytes
47 /* Run in a single cache-line */
48 mmu_disable:
49 mcr p15, 0, r0, c1, c0, 0 //coprocessor, we will talk about it later
50 nop
51 nop
52 mov pc, r2
53 #endif
54
55 mmu_disable_phys:
56 /* Peri port setup */
57 ldr r0, =0x70000000
58 orr r0, r0, #0x13 //The following is still the coprocessor. Let's finish their functions one by one.
59 mcr p15,0,r0,c15,c2,4 @ 256M (0x70000000 - 0x7fffffff)
60
61 /*
62 * Go setup Memory and board specific bits prior to relocation.
63 */
64 bl lowlevel_init /* go setup pll,mux,memory */
1. First, for an introduction to the coprocessor, please refer to the following website
http://blog.csdn.net/genglei1022/article/details/5712843
Let's go back to our code segment. To understand the coprocessor, we first need to understand two instructions.
MCR{cond} coproc, opcode1, Rd, CRn, CRm{, opcode2}
MRC{cond} coproc, opcode1, Rd, CRn, CRm{, opcode2}
//in
//coproc(essor) is the coprocessor, the standard name is pn, n = 1 ~ 15 corresponds to CPn
//opcode1 is the coprocessor behavior opcode, which is always 0, otherwise the coprocessor status is uncertain
//Rd ARM register, CRn target register, CRm additional register, set to c0 if not used
//Provide additional information such as the register version number or access type to distinguish different physical registers with the same number
// You can omit
Next comes the coprocessor.
CP15 is a system control coprocessor register used to connect to the page table descriptor in memory and is also used to determine the operation of the MMU.
The first two MCRs encountered here are:
24 mov r0, #0 // clear r0 register
//Move to Coprocessor frem Register, the meaning of MCR is similar to the following sentence
25 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
26 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
Two registers c7 and c8 appear here.
Register number Basic function Function in MMU
c7 controls cache and write cache, same as left
c8 Storage Protection and Control TLB Control
Here is a powerful website that introduces the various parts of the chip in detail.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/ch03s02s01.html
Then let me tell you how to check the relevant storage information:
1. Find the chip. Here I use ARM1176-JZF-S
2. Now we are looking for the coprocessor unit System Control Coprocessor
3. What we are looking for now is the coprocessor register System control processor registers
4. Finally, you can check the register list in Register allocation
5. If you want to know the actual function of a register, such as our register operation bit here
25 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
So what we are looking for should be
CRn Op1 CRm Op2 Register or operation
c7 0 c7 0 Invalidate Both Caches
This line actually contains the information we want to know about the coprocessor operation. If you want to learn more, click the link at the end of the line.
Here is an excerpt of c7's function
The purpose of c7 is to:
control these operations:
clean and invalidate instruction and data caches, including range operations
prefetch instruction cache line
Flush Prefetch Buffer
flush branch target address cache
virtual to physical address translation.
implement the Data Synchronization Barrier (DSB) operation
implement the Data Memory Barrier (DMB) operation
implement the Wait For Interrupt clock control function.
Those who can read English should understand
Line 25 means clearing and disabling the instruction and data caches, which has the same meaning as the comments below.
Line 26 means disabling TLB.
31 mrc p15, 0, r0, c1, c0, 0
//Read Control Register configuration data
49 mcr p15, 0, r0, c1, c0, 0
//Write Control Register configuration data
59 mcr p15,0,r0,c15,c2,4
//Peripheral Port Memory Remap
From now on, in the code segment, the implementation of each assembly instruction will not be explained in detail, but will be explained by module.
However, some difficult points will still be analyzed in detail.
2. Code running before SDRAM initialization
To understand how the code runs, you first need to understand ARM's on-chip memory system.
Here we use the XIP (eXecute In Place) standard to distinguish:
Support XIP: NOR flash, mDDR (mobile DDR);
XIP is not supported: NAND flash.
In terms of speed, NOR flash > mDDR > NAND flash.
Knowing this, let's contact the development board to break it down:
NOR flash is used as internal execution memory and is responsible for the initialization code execution of the system (such as start.o);
mDDR is the conventional memory, namely SDRAM, which is the main operating environment of the code;
As a storage device, NAND flash can be regarded as the hard disk on our PC.
It is easy to understand here, SDRAM is initialized in lowlevel_init, before SDRAM is initialized, the code is executed in NOR flash.
Next, let's solve the problem of initialization order left just now:
40 ldr r2, _TEXT_PHY_BASE
In this sentence, what exactly does _TEXT_PHY_BASE store?
Let's disassemble it first.
arm-linux-objdump -D -S -t start.o
//Add -t to see the location of the code segment
00000044 <_TEXT_PHY_BASE>:
44: 57e00000 .word 0x57e00000
...
ldr r2, _TEXT_PHY_BASE
8c: e51f2050 ldr r2, [pc, #-80] ; 44 <_TEXT_PHY_BASE>
Obviously, the _TEXT_PHY_BASE here is 0x57e00000!
But let's think about it, lowlevel_init is still behind, SDRAM has not been initialized!
So we cannot call this address, but we can clearly see it here.
What you see with your eyes is not necessarily true.
Here we introduce a new concept to explain this problem: running address independence.
First, the place of reference:
http://blog.sina.com.cn/s/blog_4a9fb5cf01008d8u.html~type=v5_one&label=rela_nextarticle
Just read the last part.
As running code, whether it is the bootloader or kernel initialization code, there will always be a period of weakness: the code is too long and the space is too short.
In uboot, it is before SDRAM initialization, and in kernel, it is before MMU enabling.
During this weak period, the addressing space of the code is very limited, and the predetermined location during the compilation process may cause addressing errors.
Therefore, the need for address independence arises, which is mainly manifested in the need to limit the addressing range of this code to our NOR flash and not disrupt code execution.
At this point, let's understand the essence of 0x57e00000 here
00000044 <_TEXT_PHY_BASE>:
44: 57e00000 .word 0x57e00000
...
ldr r2, _TEXT_PHY_BASE
8c: e51f2050 ldr r2, [pc, #-80] ; 44 <_TEXT_PHY_BASE>
If our SDRAM is enabled, then this address is actually the starting address where uboot.bin is placed.
However, at this time, uboot.bin is placed in NOR flash, so the starting point should be 0x00000000.
Following this logic, the result is correct. The execution of that section of code is "optional", which is why many people choose to delete it when modifying the code.
Previous article:s3c6410 SD card boot Secure mode
Next article:S3C6410 bare metal - external interrupt program
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Why software-defined vehicles transform cars from tools into living spaces
- How Lucid is overtaking Tesla with smaller motors
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Three steps to govern hybrid multicloud environments
- Three steps to govern hybrid multicloud environments
- Microchip Accelerates Real-Time Edge AI Deployment with NVIDIA Holoscan Platform
- Microchip Accelerates Real-Time Edge AI Deployment with NVIDIA Holoscan Platform
- 【ST NUCLEO-H743ZI Review】USB MSC Function Test
- WiFi indoor positioning technology and its evolution that has triggered the Internet of Things application
- Help: Does anyone have a power supply design that complies with industry design standards IEC61010, IEC60950?
- [Silicon Labs BG22-EK4108A Bluetooth Development Evaluation] + Development Board Firmware Upgrade
- Assembly Language (4th Edition)
- Gaoyun FPGA GW1N-4B Marquee Experiment
- Tell us your tips on using KICAD
- Number monitoring of moving objects
- The role of capacitors
- MSP430 MCU Development Record (19)