TINY4412 bare metal program, clock operation

Publisher:中华古风Latest update time:2022-01-17 Source: eefocusKeywords:TINY4412 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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 the 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 value of this bit 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:


system_clock_disable_apll: Do not use APLL, let the CPU run at 24MHz frequency, and observe whether the LED flashing becomes slower

system_clock_apll: Reset APLL to make the CPU run at 1.4GHz and observe whether the LED flashes faster.

system_clock_plls: Refer to the u-boot code provided by the manufacturer to set up 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 the previous experiment based on "Tiny4412's 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:

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 the system clock of 4412

 */

void system_clock_init(void)

{

/* IROM or BL1 sets APLL,

* This program does not 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 the system clock of 4412

* Final result: APLL=1.4GHz

*/

void system_clock_init(void)

{

/*

* 1. Before setting APLL, first set the clock source to crystal oscillator

*/

CLK_SRC_CPU = 0x0;

 

/*

* 2. Set APLL

*/

 

/* 2.1 Set lock time: PDIV=3 in APLL_CON0, so APLL_LOCK = 270x3 */

APLL_LOCK = 270 * 3;

 

/* 2.2 Set 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 post a picture).


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 system clock of 4412

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));

[1] [2]
Keywords:TINY4412 Reference address:TINY4412 bare metal program, clock operation

Previous article:TINY4412 bare metal program, key detection
Next article:tiny4412 bare metal program 1. Description

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号