210学习日记(3)
--支持串口
支持串口的代码我放到了"Tiny210学习日记_代码"目录下了,名为"2_clock_uart",因此,我就不在这里一一列出代码了,我讲讲我当初觉困难的地方吧:
1.初始化时钟:
代码如下:
void clock_init(void)
{
/* 设置时钟为:
* ARMCLK=1000MHz, HCLKM=200MHz, HCLKD=166.75MHz
* HCLKP =133.44MHz, PCLKM=100MHz, PCLKD=83.375MHz,
* PCLKP =66.7MHz
*/
/* SDIV[2:0] : S = 1
* PDIV[13:8] : P = 0x3
* MDIV[25:16]: M = 0x7d
* LOCKED [29]: 1 = 使能锁
* ENABLE [31]: 1 = 使能APLL控制器
* 得出FoutAPLL = 1000MHz
*/
APLL_CON = (1<<31)|(1<<29)|(0x7d<<16)|(0x3<<8)|(1<<0);
/* 时钟源的设置
* APLL_SEL[0] :1 = FOUTAPLL
* MPLL_SEL[4] :1 = FOUTMPLL
* EPLL_SEL[8] :1 = FOUTEPLL
* VPLL_SEL[12]:1 = FOUTVPLL
* MUX_MSYS_SEL[16]:0 = SCLKAPLL
* MUX_DSYS_SEL[20]:0 = SCLKMPLL
* MUX_PSYS_SEL[24]:0 = SCLKMPLL
* ONENAND_SEL [28]:1 = HCLK_DSYS
*/
CLK_SRC0 = (1<<28)|(1<<12)|(1<<8)|(1<<4)|(1<<0);
/* 设置分频系数
* APLL_RATIO[2:0]: APLL_RATIO = 0x0
* A2M_RATIO [6:4]: A2M_RATIO = 0x4
* HCLK_MSYS_RATIO[10:8]: HCLK_MSYS_RATIO = 0x4
* PCLK_MSYS_RATIO[14:12]:PCLK_MSYS_RATIO = 0x1
* HCLK_DSYS_RATIO[19:16]:HCLK_DSYS_RATIO = 0x3
* PCLK_DSYS_RATIO[22:20]:PCLK_DSYS_RATIO = 0x1
* HCLK_PSYS_RATIO[27:24]:HCLK_PSYS_RATIO = 0x4
* PCLK_PSYS_RATIO[30:28]:PCLK_PSYS_RATIO = 0x1
*/
CLK_DIV0 = (0x1<<28)|(0x4<<24)|(0x1<<20)|(0x3<<16)|(0x1<<12)|(0x4<<8)|(0x4<<4);
/* SDIV[2:0] : S = 1
* PDIV[13:8] : P = 0xc
* MDIV[25:16]: M = 0x29b
* VSEL [27]: 0
* LOCKED [29]: 1 = 使能锁
* ENABLE [31]: 1 = 使能MPLL控制器
* 得出FOUTmpll = 667MHz
*/
APLL_CON = (1<<31)|(1<<29)|(0x29d<<16)|(0xc<<8)|(1<<0);
}
我当初配置时钟的时候,自认为有一点基础了,就直接跑去看寄存器,进行相应的配置。但是一看寄存器,我就一头雾水了,S5PV210的寄存器太多,里面涉及的关系也太多,完全不知道来龙去脉,于是我就结合上下文看了看。发现一个很重要的参考资料,就是位于芯片手册的361页和362页的图,寄存器中涉及到的,在该图上面都能够找到,所以强烈推荐,配置S5PV210的时钟的时候,一定要参考该图。
上面给出的clock_init()函数,设置的寄存器参数,都是用的推荐值,在手册中都能够查到。
我以HCLKD为什么等于166.75MHz为例,来讲述如何借助芯片手册的361页和362页的图来配置时钟:
1.HCLKD是用于显示域(如LCD等)的时钟,因此在361页的途中找到HCLK_DSYS,顺着箭头方向往回找,发现它是由DIVhclkd分频而来,即HCLK_DSYS = MOUT_DSYS / (HCLK_DSYS_RATIO + 1),类似的分频系数对应于CLK_DIVn寄存器;
2.clock_init()函数将HCLK_DSYS_RATIO设置为了0x3;
3.从图可以得知,MOUT_DSYS要不是来源于SCLKmpll,就是是来源于SCLKa2m,而clock_init()函数将其设置为来源于SCLKmpll,类似于这样的选择时钟源,对应于CLK_SRCn寄存器;
4.从图可以得知,SCLKmpll要不来源于外部晶振的直接输入,要不来源于晶振经过锁相环倍频后的输出,而clock_init()函数将其设置为了来源于晶振经过锁相环倍频后的输出(即FOUTmpll = 667MHz);
最终:HCLKD = 667MHz / (0x3 + 1) = 166.75MHz
如果大家任然没有感悟到,可以再去看看声卡的日志中初始化时钟的部分。
2.初始化串口:
其实s5pv210的串口初始化和2440的串口初始化操作几乎一样:主要设置波特率,8位数据位,1位停止位,无校验,无流控,查询或者中断方式,这些我在提供的代码里面已经有详细的注释。
二者的主要差别就是波特率的设置,S5PV210多出了一个寄存器,是的波特率设置更加精确,描述如下:
分频系数 = ( 串口时钟源的频率 / (波特率 * 16)) - 1;
分频系数 = UBRDIVn寄存器的值 + (UDIVSLOTn寄存器中1的个数) / 16;
以时钟源为PCLKP =66.7MHz,波特率设为115200为例:
分频系数 = ( 66700000 / (115200 * 16)) - 1 = 35.2;
所以:
UBRDIVn寄存器的值 = 35;
UDIVSLOTn寄存器的值 = 0x808;
注意:
问:从这以后,在写Makefile的时候,一定要指明连接地址为0xD0020010,为什么?
答:1.在以后的写的代码将不再是位置无关码,相关知识,请看一期视频;
2.我在上篇学习日记中已经讲解了启动流程,请再参考一下;
注:
如有问题,请到韦东山LINUX视频讨论群里面,我们一起讨论学习,或者加我QQ:317312379