Exynos4412 bare metal program, clock operation

Publisher:谁与争锋1Latest update time:2018-10-14 Source: eefocusKeywords:Exynos4412 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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:

CLK_DIV_CPU0

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:

ARM CLK

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

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:

ARM CLK_SETD

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.


Keywords:Exynos4412 Reference address:Exynos4412 bare metal program, clock operation

Previous article:Exynos4412 bare metal program operation ICache
Next article:Exynos4412 clock system analysis

Latest Microcontroller Articles
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号