时钟系统与UART

关于时钟设置原理:

clip_image002

关于如何设置系统时钟的思路。

clip_image004

其中锁定时间需要一个寄存器,PLL需要一个寄存器(MPLLCL),分频还需要一个寄存器,总计三个寄存器。步骤如下:

1. 上电后,FCLK=Fin

2. 启动MPLL,经过LOCKTIME后,频率达到要求。

3. 具体寄存器设置如下:

clip_image006的比例。

clip_image008

clip_image010

If HDIVN is not 0, the CPU bus mode has to be changed from the fast bus mode to the asynchronous

bus mode using following instructions(S3C2440 does not support synchronous bus mode).

MMU_SetAsyncBusMode

mrc p15,0,r0,c1,c0,0

orr r0,r0,#R1_nF:OR:R1_iA

mcr p15,0,r0,c1,c0,0

代码例程如下(此处仅为时钟初始化代码):

clip_image012

/*

* 关闭WATCHDOG,否则CPU会不断重启

*/

void disable_watch_dog(void)

{

WTCON = 0; // 关闭WATCHDOG很简单,往这个寄存器写0即可

}

#define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))

#define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))

/*

* 对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV

* 有如下计算公式:

* S3C2410: MPLL(FCLK) = (m * Fin)/(p * 2^s)

* S3C2440: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)

* 其中: m = MDIV + 8, p = PDIV + 2, s = SDIV

* 对于本开发板,Fin = 12MHz

* 设置CLKDIVN,令分频比为:FCLK:HCLK:PCLK=1:2:4,

* FCLK=200MHz,HCLK=100MHz,PCLK=50MHz

*/

void clock_init(void)

{

// LOCKTIME = 0x00ffffff; // 使用默认值即可

CLKDIVN = 0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1

/* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */

__asm__(

"mrc p15, 0, r1, c1, c0, 0
" /* 读出控制寄存器 */ 

"orr r1, r1, #0xc0000000
" /* 设置为“asynchronous bus mode” */

"mcr p15, 0, r1, c1, c0, 0
" /* 写入控制寄存器 */

);

/* 判断是S3C2410还是S3C2440 */

if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

{

MPLLCON = S3C2410_MPLL_200MHZ; /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */

}

else

{

MPLLCON = S3C2440_MPLL_200MHZ; /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */

}

}

UART的使用

1. 原理图

clip_image014

2. 数据传输流程

clip_image016

clip_image018

PS:S3C2440有深度为64bit的FIFO

clip_image020

UART的使用流程:

clip_image022

clip_image024

clip_image026

clip_image028clip_image030

Ucon1,ucon2,ucon3的具体使用查芯片手册

clip_image032

clip_image034

clip_image036

clip_image038

PS:由于使用了SDRAM,但芯片上电后处于片内ram,即0地址,需要使用位置无关码来避免错误!

clip_image040

位置无关码实例:

void memsetup(void)

{

volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;

/* 这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值

* 写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到

* SDRAM之前就可以在steppingstone中运行

*/

/* 存储控制器13个寄存器的值 */

p[0] = 0x22011110; //BWSCON

p[1] = 0x00000700; //BANKCON0

p[2] = 0x00000700; //BANKCON1

p[3] = 0x00000700; //BANKCON2

p[4] = 0x00000700; //BANKCON3

p[5] = 0x00000700; //BANKCON4

p[6] = 0x00000700; //BANKCON5

p[7] = 0x00018005; //BANKCON6

p[8] = 0x00018005; //BANKCON7

/* REFRESH,

* HCLK=12MHz: 0x008C07A3,

* HCLK=100MHz: 0x008C04F4

*/ 

p[9] = 0x008C04F4;

p[10] = 0x000000B1; //BANKSIZE

p[11] = 0x00000030; //MRSRB6

p[12] = 0x00000030; //MRSRB7

bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启

// bl是位置无关码,相当于:PCnew = PC + 偏移

// PCnew = (4+8) + 0x28 = 0x34

//ldr pc, =disable_watch_dog /* 这样写将出错 */
原文地址:https://www.cnblogs.com/hyd-desert-camel/p/3359136.html