With the foundation of the previous section " Analysis of Exynos4412 Clock System ", in this section we will do some experiments related to the clock.
In fact, the IROM code of Exynos 4412 has already set the PLL. We can print out the PLL register values set by IROM through the serial port. These values are printed out like this (excerpted from "Complete Manual of Embedded Linux System Development_Based on 4412__Volume 1" by Teacher Wei Dongshan):
CLK_SRC_CPU = 0x01000001
CLK_DIV_DMC0 = 0x00111713
CLK_DIV_DMC1 = 0x01011171
CLK_SRC_TOP0 = 0x01110000
CLK_SRC_TOP1 = 0x00001000
CLK_DIV_TOP = 0x00015470
CLK_SRC_LEFTBUS = 0x00000001
CLK_DIV_LEFTBUS = 0x00000013
CLK_SRC_RIGHTBUS = 0x00000001
CLK_DIV_RIGHTBUS = 0x00000013
APLL_LOCK = 0x00000960
MPLL_LOCK = 0x00000000
EPLL_LOCK = 0x00000FFF
VPLL_LOCK = 0x00000FFF
CLK_DIV_CPU0 = 0x00773730
CLK_DIV_CPU1 = 0x00000077
APLL_CON1 = 0x00003800
APLL_CON0 = 0xA0640301
MPLL_CON1 = 0x00003800
MPLL_CON0 = 0xA0640301
EPLL_CON2 = 0x00000080
EPLL_CON1 = 0x66010000
EPLL_CON0 = 0x00600302
VPLL_CON2 = 0x00000080
VPLL_CON1 = 0x66016000
VPLL_CON0 = 0x006F0302
CLK_SRC_CPU = 0x01000001
CLK_SRC_DMC = 0x00111000
CLK_SRC_TOP0 = 0x01110000
CLK_SRC_TOP1 = 0x00001000
Now calculate the clock frequency of ARMCLK:
From the introduction of the previous section " Analysis of Exynos4412 Clock System ", we know that ARMCLK has the following calculation formula:
As shown below:
The value of the register CLK_SRC_CPU printed above is:
Hexadecimal: 0x01000001
Binary: 0000 0001 0000 0000 0000 0000 0000 0001
① BIT[0] controls the first MUX (i.e. MUXAPLL), and the bit value is 1.
② BIT[16] controls the second MUX (i.e. MUXCORE), and the value of this bit is 0.
So it can be seen that the ARMCLK clock follows the following route:
So: ARMCLK = output of MUXCORE / DIVCORE / DIVCORE2
ARMCLK = MDIV x FIN / (PDIV x 2 ^ SDIV) / (CORE_RATIO + 1) / (CORE2_RATIO + 1)
= 0x64 x 24MHz / (3 x 2^1) / (0 + 1) / (0 + 1)
= 400 MHz
This experiment involves 3 small experiments:
① 4.system_clock_disable_apll: Do not use APLL, let the CPU run at 24MHz frequency, and observe whether the LED flashing becomes slower
② 5.system_clock_apll: Reset APLL to let the CPU run at 1.4GHz and observe whether the LED flashes faster.
③ 6.system_clock_plls: Refer to the u-boot code provided by the manufacturer to set all PLLs for use in subsequent chapters
The first small experiment
Goal: Do not use APLL, let the CPU run at 24MHz frequency, and observe whether the LED flashing becomes slower
1. Program Description
We modified it based on the previous experiment, " Tiny4412 C language implementation of flowing lights ".
start.S is mostly the same, except for the addition of a function call statement:
bl system_clock_init //Call the clock initialization function
As shown below:
Startup File
The content of the link script system_clock.lds is exactly the same as key.lds in the previous experiment, only the name is changed; the content of Makefile is also mostly the same, only the name of the file inside is changed, the led.c file is exactly the same as in the LED experiment, and a new file system_clock.c is added, the code is as follows:
//CMU_CPU
#define CLK_SRC_CPU (*(volatile unsigned int *)0x10044200)
#define CLK_DIV_CPU0 (*(volatile unsigned int *)0x10044500)
#define CLK_DIV_CPU1 (*(volatile unsigned int *)0x10044504)
//CMU_DMC
#define CLK_SRC_DMC (*(volatile unsigned int *)0x10040200)
#define CLK_DIV_DMC0 (*(volatile unsigned int *)0x10040500)
#define CLK_DIV_DMC1 (*(volatile unsigned int *)0x10040504)
// CMU_TOP
#define CLK_SRC_TOP0 (*(volatile unsigned int *)0x1003C210)
#define CLK_SRC_TOP1 (*(volatile unsigned int *)0x1003C214)
#define CLK_DIV_TOP (*(volatile unsigned int *)0x1003C510)
// CMU_LEFTBUS
#define CLK_SRC_LEFTBUS (*(volatile unsigned int *)0x10034200)
#define CLK_DIV_LEFTBUS (*(volatile unsigned int *)0x10034500)
// CMU_RIGHTBUS
#define CLK_SRC_RIGHTBUS (*(volatile unsigned int *)0x10038200)
#define CLK_DIV_RIGHTBUS (*(volatile unsigned int *)0x10038500)
// locktime
#define APLL_LOCK (*(volatile unsigned int *)0x10044000)
#define MPLL_LOCK (*(volatile unsigned int *)0x10044008)
#define EPLL_LOCK (*(volatile unsigned int *)0x1003C010)
#define VPLL_LOCK (*(volatile unsigned int *)0x1003C020)
//APLL
#define APLL_CON1 (*(volatile unsigned int *)0x10044104)
#define APLL_CON0 (*(volatile unsigned int *)0x10044100)
//MPLL
#define MPLL_CON0 (*(volatile unsigned int *)0x10040108)
#define MPLL_CON1 (*(volatile unsigned int *)0x1004010c)
//EPLL
#define EPLL_CON2 (*(volatile unsigned int *)0x1003C118)
#define EPLL_CON1 (*(volatile unsigned int *)0x1003C114)
#define EPLL_CON0 (*(volatile unsigned int *)0x1003C110)
//VPLL
#define VPLL_CON0 (*(volatile unsigned int *)0x1003C120)
#define VPLL_CON1 (*(volatile unsigned int *)0x1003C124)
#define VPLL_CON2 (*(volatile unsigned int *)0x1003C128)
//Function name:
//system_clock_init
//Function: Initialize 4412 system clock
void system_clock_init(void)
{
// IROM or BL1 sets APLL,
//This program is set not to start APLL,
//Instead, use the crystal oscillator clock to experience the LED flashing becoming slower
CLK_SRC_CPU = 0x0;
}
There is nothing much to say, it is very simple. The first part is the definition of some register addresses that will be used later. The main one is the system_clock_init function below. In this function, the value of the CLK_SRC_CPU register is set to 0, so that the frequency of ARMCLK will follow the following path and be set to 24MHZ:
2. Compile and burn experiments
According to the methods introduced in the previous sections, upload the program to the server for compilation and burn it to the SD card. Power on the development board and you can clearly feel that the frequency of LED flashing is greatly reduced, indicating that the clock we set is working. I won’t post a picture here (you can’t see it even if I do).
The second small experiment
Goal: Reset APLL, let the CPU run at 1.4GHz, and observe whether the LED flashes faster
1. Program Description
The file is the same as the first small experiment, except that the system_clock_init function in the system_clock.c file is modified based on it:
//Function name: system_clock_init
//Function: Initialize 4412 system clock
//Final result: APLL=1.4GHz
void system_clock_init(void)
{
// 1. Before setting APLL, set the clock source to crystal oscillator
CLK_SRC_CPU = 0x0;
// 2. Set up APLL
// 2.1 Set lock time: PDIV=3 in APLL_CON0, so APLL_LOCK = 270x3
APLL_LOCK = 270 * 3;
// 2.2 Set the frequency division parameters
// CORE2_RATIO = 0;
// APLL_RATIO = 2;
// PCLK_DBG_RATIO = 1;
// ATB_RATIO = 6;
// PERIPH_RATIO = 7;
// COREM1_RATIO = 7;
// COREM0_RATIO = 3;
// CORE_RATIO = 0;
CLK_DIV_CPU0 = ((0<<28) | (2<<24) | (1<<20) | (6<<16) | (7<<12) | (7<<8) | (3<<4 ) | 0);
// CORES_RATIO = 5;
// HPM_RATIO = 0;
// COPY_RATIO = 6;
CLK_DIV_CPU1 = ((5 << 8) |(0 << 4) | (6));
// 2.3 Set control parameters and enable PLL
// default value
APLL_CON1 = 0x00803800;
// Set APLL's M, P, S values, APLL output = 0xAF x 24MHz / (3 x 2 ^ 0) = 1.4GHz
// Enable APLL
APLL_CON0 = (1<<31 | 0xAF<<16 | 3<<8 | 0x0);
// 3. Set up MUX and use the output of APLL
CLK_SRC_CPU = 0x01000001;
}
The comments are very clear. What needs to be noted is that after power-on, IROM sets APLL, and the CPU works on the clock provided by APLL. When we want to change APLL, we must first make the CPU work on another clock source, that is, the crystal oscillator. After setting APLL, let the CPU work on the clock provided by APLL again.
2. Compile and burn experiments
According to the methods introduced in the previous sections, upload the program to the server for compilation and burn it to the SD card. When the development board is powered on, you can clearly feel that the frequency of LED flashing has greatly increased (it flashes faster than in " Tiny4412 C language to implement flowing lights ", because the CPU was running at 400MHZ at that time, and now it runs at 1.4GHZ), which means that the clock we set is effective. I won't post a picture here (you can't see it even if I do).
The third small experiment
Goal: Refer to the u-boot code provided by the manufacturer and set up all PLLs for use in subsequent chapters
1. Program Description
The file is the same as the first small experiment, except that the system_clock_init function in the system_clock.c file is modified based on it:
// Function name:
// system_clock_init
// Function:
// Initialize the 4412 system clock
// Final Results:
// A=1400000000, M=800000000, E=96000000 V=350000000
// ARMCLK=1500000000, DMC=400000000, ACLK200=160000000
// ACLK100=100000000, ACLK160=160000000, ACLK133=133333333
void system_clock_init(void)
{
// 1. Set CMU_CPU related
CLK_SRC_CPU = 0x0; // Set the source of all MUXs in the CMU_CPU section
// 2. Set CMU_DMC related
//
CORE_TIMERS_RATIO = 0x0;
COPY2_RATIO = 0x0;
DMCP_RATIO = 0x1;
DMCD_RATIO = 0x1;
DMC_RATIO = 0x1;
DPHY_RATIO = 0x1;
ACP_PCLK_RATIO = 0x1;
ACP_RATIO = 0x3;
CLK_DIV_DMC0 = ((0x0 << 28) | (0x0 << 24) | (0x1 << 20) | (0x1 << 16) | (0x1 << 12) | (0x1 << 8) | (0x1 << 4 ) | (0x3));
CLK_DIV_DMC1 = 0x07071713;
// 3. Set CMU_TOP related
//
MUX_ONENAND_SEL = 0x0;
MUX_ACLK_133_SEL = 0x0;
MUX_ACLK_160_SEL = 0x0;
MUX_ACLK_100_SEL = 0x0;
MUX_ACLK_200_SEL = 0x0;
MUX_VPLL_SEL = 0x1;
MUX_EPLL_SEL = 0x1;
CLK_SRC_TOP0 = ((0x0 << 28) | (0x0 << 24) | (0x0 << 20) | (0x0 << 16) | (0x0 << 12) | (0x1 << 8) | (0x1 << 4 ));
CLK_SRC_TOP1 = 0x01111000;
//
ACLK_400_MCUISP_RATIO = 0x1;
ACLK_266_GPS_RATIO = 0x2;
ONENAND_RATIO = 0x1;
ACLK_133_RATIO = 0x5;
ACLK_160_RATIO = 0x4;
ACLK_100_RATIO = 0x7;
ACLK_200_RATIO = 0x4;
CLK_DIV_TOP = ((0x1 << 24) | (0x2 << 20) | (0x1 << 16) | (0x5 << 12) | (0x4 << 8) | (0x7 << 4) | (0x4));
// 3. Set CMU_LEFTBUS related
CLK_SRC_LEFTBUS = 0x10;
//
GPL_RATIO = 0x1;
GDL_RATIO = 0x3;
CLK_DIV_LEFTBUS = ((0x1 << 4) | (0x3));
// 4. Set CMU_RIGHTBUS related
CLK_SRC_RIGHTBUS = 0x10;
//
GPR_RATIO = 0x1;
GDR_RATIO = 0x3;
CLK_DIV_RIGHTBUS = ((0x1 << 4) | (0x3));
// 5. Set the locktime of each phase-locked loop (PLL)
APLL_LOCK = (0x3 * 270);
MPLL_LOCK = (0x3 * 270);
EPLL_LOCK = (0x2 * 3000);
VPLL_LOCK = (0x2 * 3000);
//
APLL_RATIO = 0x2;
CORE_RATIO = 0x0;
CORE2_RATIO = 0x0;
COREM0_RATIO = 0x3;
COREM1_RATIO = 0x7;
PERIPH_RATIO = 0x7;
ATB_RATIO = 0x6;
PCLK_DBG_RATIO = 0x1;
CLK_DIV_CPU0 = ((0x0 << 28) | (0x2 << 24) | (0x1 << 20) | (0x6 << 16) | (0x7 <<12) | (0x7 << 8) | (0x3 << 4 ) | (0x0));
//
CORES_RATIO = 0x5;
HPM_RATIO = 0x0;
COPY_RATIO = 0x6;
CLK_DIV_CPU1 = ((0x5 << 8) |(0x0 << 4) | (0x6));
// 6. Set APLL = 1400000000
APLL_CON1 = 0x00803800;
APLL_CON0 = (1<<31 | 0xAF<<16 | 0x3<<8 | 0x0);
// 7. Set MPLL = 800000000
MPLL_CON1 = 0x00803800;
MPLL_CON0 = (1<<31 | 0x64<<16 | 0x3<<8 | 0x0);
// 8. Set EPLL = 96000000
EPLL_CON2 = 0x00000080;
EPLL_CON1 = 0x66010000;
EPLL_CON0 = (1<<31 | 0x40<<16 | 0x2<<8 | 0x3);
// 9. Set VPLL = 350000000
VPLL_CON2 = 0x00000080;
VPLL_CON1 = 0x66010000;
VPLL_CON0 = (1<<31 | 0x48<<16 | 0x2<<8 | 0x3);
//10. Modify the source
CLK_SRC_CPU = 0x01000001;
CLK_SRC_DMC = 0x00011000;
CLK_SRC_TOP0 = 0x00000110;
CLK_SRC_TOP1 = 0x01111000;
}
2. Compile and burn experiments
According to the methods introduced in the previous sections, upload the program to the server for compilation, burn it to the SD card, and power on the development board. The phenomenon is exactly the same as in the second experiment.
Previous article:Exynos4412 bare metal program operation ICache
Next article:Exynos4412 clock system analysis
- 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
- Melexis launches ultra-low power automotive contactless micro-power switch chip
- Melexis launches ultra-low power automotive contactless micro-power switch chip
- Molex leverages SAP solutions to drive smart supply chain collaboration
- Pickering Launches New Future-Proof PXIe Single-Slot Controller for High-Performance Test and Measurement Applications
- Apple faces class action lawsuit from 40 million UK iCloud users, faces $27.6 billion in claims
- Apple faces class action lawsuit from 40 million UK iCloud users, faces $27.6 billion in claims
- The US asked TSMC to restrict the export of high-end chips, and the Ministry of Commerce responded
- The US asked TSMC to restrict the export of high-end chips, and the Ministry of Commerce responded
- ASML predicts that its revenue in 2030 will exceed 457 billion yuan! Gross profit margin 56-60%
- Detailed explanation of intelligent car body perception system
- SWD cannot be downloaded, what is the reason? ?
- A rather strange op amp, take a look
- Undergraduate entrance examination
- Bill of Materials Problem
- PADS PCB 3D component library
- C2000-GNAG Operation and Use
- HyperLynx High-Speed Circuit Design and Simulation (VI) Non-ideal Transmission Line Differential Pair Eye Diagram (Impedance Mismatch)
- [ESK32-360 Review] 6. Hello! Hello! Hello! Hello!
- [NXP Rapid IoT Review] NXP Rapid IOT Experience
- Is there any teacher who can help me write a program for Mitsubishi FX3U to output pulses?