x210v3开发板u-boot-2012.10移植之七---六步轻松搞定串口初始化

来源:互联网 发布:上海电力有限公司知乎 编辑:程序博客网 时间:2024/05/16 09:15

                                                     疯雨-版权所有,转载请注明【http://blog.csdn.net/u010346967】

欢迎加入朱老师物联网大课堂qq群  一起学习进步 
群号:397164505 

串口是调试的利器,单纯靠led来调试是很痛苦的一件事,所以当务之急是初始化串口。注意:我这里是初始化的串口0.

首先,从需求开始,先想象一下软件需要做些什么?串口无非就是要实现接收和发送数据,那么从哪里发送或者接收数据呢?所以就要求配置GPIO为UART模式,说明从这里接收或发送数据。发送数据的速度多快呢?所以要设置波特率。然后,一次发送的数据长度为多少?是否使用奇偶校验,停止位设为多少位?这就要配置ULCON。当然,外设都得配置时钟源,所以UCON少不了。用不用FIFO应当要可配置,那么UFCON是必须的。还有流控开不开,这个如果不懂的话可以看我的另一篇文章,串口通信原理。

1.六步轻松搞定串口初始化

1.1 配置相应GPIO口为串口模式
1.2 配置ULCON
1.3 配置UCON
1.4配置UFCON
1.5配置UMCON
1.6设置波特率

2.具体初始化细节


2.1 通过datasheet也就是S5PV210_UM_REV1.1.pdf文件,找到UART0接在GPA0口。配置GPA0CON为0x22222222,这里把UART1也配置了。





2.2 配置ULCON0(如果是串口2则配置ULCON2)为 0x3



2.3 配置UCON0(串口2是UCON2)为0x305





2.4 配置UFCON0(串口2为UFCON2)为 0x1,这个简单使能fifo就可以了。其他几个状态寄存器不用管


2.5 配置UMCON0(串口2为UMCON2)为0x0,不使用流控,不管他


2.6 波特率设置为115200

需配置两个寄存器UBRDIV0(串口2为UBRDIV2)为34(注意十进制哦)和UDIVSLOT0(串口2为UDIVSLOT2)为0xDFDD
这个要计算了 计算公式手册上有,直接看手册提供的例子40000000是UART的时钟频率,也就是PCLK,我们的PCLK配置为66MHz。
DIV_VAL=(66000000/(115200X16))-1 = 34.8       0.8X16= 13  查表得到 UBRDIV0 = 0xDFDD




初始化代码贴下面:
uart_init:/* set GPIO to enable UART0-UART4 */movr0, r8ldrr1, =0x22222222strr1, [r0, #0x0]@ config UART0 and UART1ldrr1, =0x00002222strr1, [r0, #0x20]@ config UART2    ldr r0,=S5PC110_UART_BASE     @如果是使用串口2,只需将这里改为 ldr r0,=S5PC110_UART2_BASE    ldr r1,=0x3    str r1,[r0]    @ULCON=3        ldr r1,=0x305    str r1,[r0,#0x4]  @UCON=0x305    ldr r1,=0x1    str r1,[r0,#0x8]  @UFCON=1    ldr r1,=0x0    str r1,[r0,#0xc]  @UMCON=0    ldr r1,=34    str r1,[r0,#0x28] @Baud rate 115200    ldr r1,=0xDFDD    str r1,[r0,#0x2c] @UDIVSLOT    mov pc,lr

3.串口测试

 往串口写一个字符U并打印出来。串口数据是ASCII编码,百度一下U的ASCII码(0x55),0x55直接写入UTH0寄存器即可。

直接在uart_init 子过程的末尾mov pc,lr 的前一行增加代码,修改后如下图所示:



再检测下代码,看看有没有问题,好了确定没什么问题,现在可以编译了

root@crazyrain:/home/share/uboot/u-boot-2012.10# make
make成功

然后进行烧录,但是发现每次都要敲同样的命令效率太低,于是写个烧写脚本burnBootloader.sh
root@crazyrain:/home/share/uboot/u-boot-2012.10# vim burnBootloader.sh
脚本内容如下:
./mkv210 u-boot.bin u-boot_16k.bindd if=u-boot_16k.bin of=/dev/sdb seek=1
并为烧写脚本提供可执行权限:
root@crazyrain:/home/share/uboot/u-boot-2012.10# chmod a+x burnBootloader.sh 

将SD卡插入电脑,进行烧录
root@crazyrain:/home/share/uboot/u-boot-2012.10# ./burnBootloader.sh

拔出SD卡,插入开发板,连接串口0,并配置好SecureCRT连接。发现串口并没有打印出字符。
这时候纠结了,分析下原因?有两种可能,第一,代码有问题。第二,代码不在前16k。所以看看lowlevel_init是不是位于前16k,反汇编一下
root@crazyrain:/home/share/uboot/u-boot-2012.10# arm-linux-objdump -D u-boot > u-boot.dis
root@crazyrain:/home/share/uboot/u-boot-2012.10# vim u-boot.dis
查找lowlevel_init,看下图



一眼看出确实不在前16k,为啥呢?链接起始地址为0x34800000    0x3481fa14-0x34800000=0x1fa14   大于 16k=16*2^10=16*16^2*4=4*16^3=0x4000
记住几个常用值  0x1000为4k  那么16k就是4*0x1000=0x4000    0x100000为1M   比如5M  就是0x500000 能一下子看出来
那么接下来怎么把代码移动到前16k呢?
有两个办法,第一,修改Makefile。第二,修改链接脚本。
第一种办法我试过了,下面先试试第二种办法,
root@crazyrain:/home/share/uboot/u-boot-2012.10# vim u-boot.lds

在arch/arm/cpu/armv7/start.o (.text)后面添加一句,如下面所示:
  arch/arm/cpu/armv7/start.o (.text)
  board/samsung/x210v3/lowlevel_init.o (.text)

再次编译,记得先make  clean 再make  如下:
root@crazyrain:/home/share/uboot/u-boot-2012.10# make clean
root@crazyrain:/home/share/uboot/u-boot-2012.10# make

查看反汇编文件,这里还有另一种方式可以查看,就是编译后顶层目录下的u-boot.map文件,打开搜索lowlevel_init:

发现没点变化,因为前面犯了个错,前面修改的是顶层目录下的u-boot.lds,这个文件是临时生成的。真正的文件位于arch/arm/cpu/u-boot.lds
好,按照上面的修改,编译发现如下错误:重复定义错误,因为libx210.o里面也有一个lowlevel_init

board/samsung/x210v3/libx210v3.o: In function `lowlevel_init':/home/share/uboot/u-boot-2012.10/board/samsung/x210v3/lowlevel_init.S:46: multiple definition of `lowlevel_init'board/samsung/x210v3/lowlevel_init.o:/home/share/uboot/u-boot-2012.10/board/samsung/x210v3/lowlevel_init.S:46: first defined heremake: *** [u-boot] 错误 1

那么我干脆把libx210v3.o链接过去,而不是链接lowlevel_init.o,试试,竟然成功了



接着,查看下 u-boot.map,位于前16k了吧




好了,烧录运行下试试,竟然出现了,神奇的U。。。

























1 0