S3C6410 串口 UARTx 的时钟源比较复杂,具体应用时,可以通过寄存器 UCONn 来选择时钟的来源。
PCLK 由 APLL(同步模式时)分频得到,或由 MPLL(异步模式时)分频得到;
EXT_UCLK0 clock is external clock.(XpwmECLK PAD input),一般很少用;
EXT_UCLK1 clock is generated clock by SYSCON. SYSCON generates EXT_UCLK1 for dividing EPLL or MPLL output.
接下来我们看看 SYSCON 是如何产生 EXT_UCLK1 的?
上图的 CLKUART 其实就是 EXT_UCLK1,它和 PCLK 一样都可以为串口 IP 模块提供时钟源,即串口模块的波特率可以由该时钟源分频得到。既然这样为何不直接使用 PCLK 作为时钟源?这是因为 PCLK 最大可以产生的波特率是 115200bps,但是有时候用户可能需要更大的波特率,这就不得不用到 EXT_UCLK0 或 EXT_UCLK1。
MUXuart 开关控制着分频器之前的时钟来源,它由寄存器 CLK_SRC bit[13] 来设置。
CLK_SRC
DIVIDER 是将输入的时钟进行分频,最终得到 CLKUART(EXT_UCLK1),它由寄存器 CLK_DIV2 bit[19:16] 来设置。
CLK_DIV2
通过上述的分析我们知道,串口模块可以通过 UCONn 寄存器的 bit[11:10] 来选择时钟源为 PCLK 或 EXT_UCLK1。但是千万要注意,这仅仅是选择!它只是把 PCLK/EXT_UCLK1 到串口 IP 模块输入时钟(对于一个含有时序逻辑的 IP 模块,一定需要一个输入时钟作为基准)的这条路打开,这并不意味着 PCLK/EXT_UCLK1(这里只是泛泛地讲PCLK,确切来说应该叫做 PCLK_UARTx) 一定存在。这就好比说,我们打开了水龙头,但是这并不能保证一定会有水流出来,因为水泵都没有工作。
S3C6410 通过 PCLK_GATE 和 SCLK_GATE 来控制这些开关。
PCLK_GATE
SCLK_GATE
注意:当选择 PCLK 作为串口的时钟源时,寄存器相应位应该设置成什么和上一个状态有关系。
When you want to change EXT_UCLK0 to PCLK for UART baudrate , clock selection field must be set to 2’b00.
But, when you want to change EXT_UCLK1 to PCLK for UART baudrate , clock selection field must be set to 2’b10.
Tiny6410 提供的 u-boot 将串口的时钟源设为 EXT_UCLK1,因此当我们用 u-boot 调试裸机程序的时候,如果需要自己初始化串口应特别注意,可以按下面的示例代码初始化串口:
void uart_init(void)
{
GPACON &= ~0xff; /* 选择引脚功能 */
GPACON |= 0x22;
ULCON0 = 0x3; /* 数据位:8, 无较验, 停止位: 1, 8n1 */
UCON0 = 0x805; /* 使能UART发送、接收 选择时钟源*/
UFCON0 = 0x01; /* FIFO ENABLE */
UMCON0 = 0;
/* DIV_VAL = (PCLK / (bps x 16 ) ) - 1
* bps = 115200
* DIV_VAL = (66500000 / (115200 x 16 ) ) - 1 = 35.08
*/
UBRDIV0 = 35;
UDIVSLOT0 = 0x1;
}
补充:Tiny6410 提供的 u-boot 开启了 MMU(我是不知道它为何这么做???),因此使用 u-boot 下载(tftp/nfs)裸机程序到内存时,地址就不能简单地使用原来的内存地址 0x50000000-0x6fffffff,应该使用映射后的地址。u-boot 里面使用的映射关系比较简单,地址 0x50000000 映射到 0xc0000000(对于其他地址都存在线性关系),另外在源代码的开头要关闭 MMU。
——忠于梦想 勇于实践 linux_xpj@opencores.org
阅读(4131) | 评论(2) | 转发(4) |